diff options
author | uruk | 2014-05-30 11:14:47 +0200 |
---|---|---|
committer | uruk | 2014-05-30 11:14:47 +0200 |
commit | bb2f8dd68e1d6b2b30b07f60c0cd4e125b47ea4d (patch) | |
tree | 9a1e28cfb1eb1a322225c05adc0962a2f96ea521 | |
parent | 5ad4e157e5398347651a0da0db07f9daf01bf373 (diff) | |
parent | 0a46d67baea121bed0511ce45bfdd8438a43d35d (diff) | |
download | scummvm-rg350-bb2f8dd68e1d6b2b30b07f60c0cd4e125b47ea4d.tar.gz scummvm-rg350-bb2f8dd68e1d6b2b30b07f60c0cd4e125b47ea4d.tar.bz2 scummvm-rg350-bb2f8dd68e1d6b2b30b07f60c0cd4e125b47ea4d.zip |
Merge branch 'master' of https://github.com/scummvm/scummvm into cge2
294 files changed, 66285 insertions, 3944 deletions
@@ -138,6 +138,11 @@ ScummVM Team Benjamin Haisch Filippos Karapetis + MADS: + Arnaud Boutonne + Paul Gilbert + Filippos Karapetis + Mohawk: Bastien Bouclet Matthew Hoops @@ -241,6 +246,10 @@ ScummVM Team Tucker: Gregory Montoir - (retired) + Voyeur: + Arnaud Boutonne + Paul Gilbert + Wintermute: Einar Johan T. Somaaen diff --git a/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in b/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in index 7b9273f2dd..56456f37e4 100644 --- a/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in +++ b/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -34,6 +34,9 @@ TARGET ScummVM_A0000658.exe TARGETPATH sys\bin TARGETTYPE exe OPTION GCCE -Wno-multichar -Wno-reorder -Wno-unused -Wno-format -fsigned-char +// fixes error "section .data loaded at [...] overlaps section .text loaded at [...]" +// in future simple add 'a' +LINKEROPTION GCCE -Tdata 0xAA00000 UID 0x100039ce 0xA0000658 @@ -90,9 +93,15 @@ STATICLIBRARY esdl.lib USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\engines USERINCLUDE ..\..\..\..\backends\fs ..\src ..\..\..\..\backends\platform\sdl ..\..\..\..\audio +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor SYSTEMINCLUDE \epoc32\include SYSTEMINCLUDE \epoc32\include\mw SYSTEMINCLUDE \epoc32\include\platform diff --git a/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in b/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in index 09ff968706..0c0dd9b6b6 100644 --- a/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in +++ b/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -90,9 +90,15 @@ STATICLIBRARY esdl.lib USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\engines USERINCLUDE ..\..\..\..\backends\fs ..\src ..\..\..\..\backends\platform\sdl ..\..\..\..\audio +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor SYSTEMINCLUDE \epoc32\include SYSTEMINCLUDE \epoc32\include\mw SYSTEMINCLUDE \epoc32\include\platform diff --git a/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg b/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg index c04b7f6d51..5f74bee1c7 100644 --- a/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg +++ b/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg @@ -76,31 +76,6 @@ "..\..\..\vkeybd\packs\vkeybd_default.zip"-"c:\data\scummvm\vkeybd_default.zip" "..\..\..\..\gui\themes\translations.dat"-"c:\data\scummvm\translations.dat" "..\..\..\..\gui\themes\scummmodern.zip"-"c:\data\scummvm\scummmodern.zip" -"..\..\..\..\gui\themes\fonts\Arial.bdf"-"c:\data\scummvm\Arial.bdf" -"..\..\..\..\gui\themes\fonts\Arial12.bdf"-"c:\data\scummvm\Arial12.bdf" -"..\..\..\..\gui\themes\fonts\ArialBold.bdf"-"c:\data\scummvm\ArialBold.bdf" -"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-1.bdf"-"c:\data\scummvm\clR6x12-iso-8859-1.bdf" -"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-2.bdf"-"c:\data\scummvm\clR6x12-iso-8859-2.bdf" -"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-5.bdf"-"c:\data\scummvm\clR6x12-iso-8859-5.bdf" -"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-7.bdf"-"c:\data\scummvm\clR6x12-iso-8859-7.bdf" -"..\..\..\..\gui\themes\fonts\clR6x12.bdf"-"c:\data\scummvm\clR6x12.bdf" -"..\..\..\..\gui\themes\fonts\courr12-iso-8859-1.bdf"-"c:\data\scummvm\courr12-iso-8859-1.bdf" -"..\..\..\..\gui\themes\fonts\fixed5x8-iso-8859-1.bdf"-"c:\data\scummvm\fixed5x8-iso-8859-1.bdf" -"..\..\..\..\gui\themes\fonts\fixed5x8-iso-8859-5.bdf"-"c:\data\scummvm\fixed5x8-iso-8859-5.bdf" -"..\..\..\..\gui\themes\fonts\fixed5x8-iso-8859-7.bdf"-"c:\data\scummvm\fixed5x8-iso-8859-7.bdf" -"..\..\..\..\gui\themes\fonts\fixed5x8.bdf"-"c:\data\scummvm\fixed5x8.bdf" -"..\..\..\..\gui\themes\fonts\FreeMonoBold.ttf"-"c:\data\scummvm\FreeMonoBold.ttf" -"..\..\..\..\gui\themes\fonts\FreeSans.ttf"-"c:\data\scummvm\FreeSans.ttf" -"..\..\..\..\gui\themes\fonts\FreeSansBold.ttf"-"c:\data\scummvm\FreeSansBold.ttf" -"..\..\..\..\gui\themes\fonts\helvB12-iso-8859-1.bdf"-"c:\data\scummvm\helvB12-iso-8859-1.bdf" -"..\..\..\..\gui\themes\fonts\helvB12-iso-8859-2.bdf"-"c:\data\scummvm\helvB12-iso-8859-2.bdf" -"..\..\..\..\gui\themes\fonts\helvB12-iso-8859-5.bdf"-"c:\data\scummvm\helvB12-iso-8859-5.bdf" -"..\..\..\..\gui\themes\fonts\helvB12.bdf"-"c:\data\scummvm\helvB12.bdf" -"..\..\..\..\gui\themes\fonts\helvBO12-iso-8859-1.bdf"-"c:\data\scummvm\helvBO12-iso-8859-1.bdf" -"..\..\..\..\gui\themes\fonts\helvBO12.bdf"-"c:\data\scummvm\helvBO12.bdf" -"..\..\..\..\gui\themes\fonts\helvR12-iso-8859-1.bdf"-"c:\data\scummvm\helvR12-iso-8859-1.bdf" -"..\..\..\..\gui\themes\fonts\helvR12.bdf"-"c:\data\scummvm\helvR12.bdf" -;"..\..\..\..\gui\themes\"-"c:\data\scummvm\" ; Config/log files: 'empty' will automagically be removed on uninstall ""-"c:\data\scummvm\scummvm.ini",FILENULL diff --git a/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3_split.pkg b/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3_split.pkg index 250076347a..4ef085d600 100644 --- a/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3_split.pkg +++ b/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3_split.pkg @@ -36,7 +36,7 @@ :"ScummVM" ; UID is the app's UID -#{"ScummVM S60v3"},(0xA0000657),1,70,0 +#{"ScummVM S60v3"},(0xA0000657),1,70,6 ;Supports Series 60 v 3.0 [0x101F7961], 0, 0, 0, {"Series60ProductID"} @@ -84,31 +84,6 @@ "..\..\..\vkeybd\packs\vkeybd_default.zip"-"c:\data\scummvm\vkeybd_default.zip" "..\..\..\..\gui\themes\translations.dat"-"c:\data\scummvm\translations.dat" "..\..\..\..\gui\themes\scummmodern.zip"-"c:\data\scummvm\scummmodern.zip" -"..\..\..\..\gui\themes\fonts\Arial.bdf"-"c:\data\scummvm\Arial.bdf" -"..\..\..\..\gui\themes\fonts\Arial12.bdf"-"c:\data\scummvm\Arial12.bdf" -"..\..\..\..\gui\themes\fonts\ArialBold.bdf"-"c:\data\scummvm\ArialBold.bdf" -"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-1.bdf"-"c:\data\scummvm\clR6x12-iso-8859-1.bdf" -"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-2.bdf"-"c:\data\scummvm\clR6x12-iso-8859-2.bdf" -"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-5.bdf"-"c:\data\scummvm\clR6x12-iso-8859-5.bdf" -"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-7.bdf"-"c:\data\scummvm\clR6x12-iso-8859-7.bdf" -"..\..\..\..\gui\themes\fonts\clR6x12.bdf"-"c:\data\scummvm\clR6x12.bdf" -"..\..\..\..\gui\themes\fonts\courr12-iso-8859-1.bdf"-"c:\data\scummvm\courr12-iso-8859-1.bdf" -"..\..\..\..\gui\themes\fonts\fixed5x8-iso-8859-1.bdf"-"c:\data\scummvm\fixed5x8-iso-8859-1.bdf" -"..\..\..\..\gui\themes\fonts\fixed5x8-iso-8859-5.bdf"-"c:\data\scummvm\fixed5x8-iso-8859-5.bdf" -"..\..\..\..\gui\themes\fonts\fixed5x8-iso-8859-7.bdf"-"c:\data\scummvm\fixed5x8-iso-8859-7.bdf" -"..\..\..\..\gui\themes\fonts\fixed5x8.bdf"-"c:\data\scummvm\fixed5x8.bdf" -"..\..\..\..\gui\themes\fonts\FreeMonoBold.ttf"-"c:\data\scummvm\FreeMonoBold.ttf" -"..\..\..\..\gui\themes\fonts\FreeSans.ttf"-"c:\data\scummvm\FreeSans.ttf" -"..\..\..\..\gui\themes\fonts\FreeSansBold.ttf"-"c:\data\scummvm\FreeSansBold.ttf" -"..\..\..\..\gui\themes\fonts\helvB12-iso-8859-1.bdf"-"c:\data\scummvm\helvB12-iso-8859-1.bdf" -"..\..\..\..\gui\themes\fonts\helvB12-iso-8859-2.bdf"-"c:\data\scummvm\helvB12-iso-8859-2.bdf" -"..\..\..\..\gui\themes\fonts\helvB12-iso-8859-5.bdf"-"c:\data\scummvm\helvB12-iso-8859-5.bdf" -"..\..\..\..\gui\themes\fonts\helvB12.bdf"-"c:\data\scummvm\helvB12.bdf" -"..\..\..\..\gui\themes\fonts\helvBO12-iso-8859-1.bdf"-"c:\data\scummvm\helvBO12-iso-8859-1.bdf" -"..\..\..\..\gui\themes\fonts\helvBO12.bdf"-"c:\data\scummvm\helvBO12.bdf" -"..\..\..\..\gui\themes\fonts\helvR12-iso-8859-1.bdf"-"c:\data\scummvm\helvR12-iso-8859-1.bdf" -"..\..\..\..\gui\themes\fonts\helvR12.bdf"-"c:\data\scummvm\helvR12.bdf" -;"..\..\..\..\gui\themes\"-"c:\data\scummvm\" ; Config/log files: 'empty' will automagically be removed on uninstall ""-"c:\data\scummvm\scummvm.ini",FILENULL diff --git a/backends/platform/symbian/help/ScummVM.rtf b/backends/platform/symbian/help/ScummVM.rtf index 522fab832c..4b5ae5afe0 100644 --- a/backends/platform/symbian/help/ScummVM.rtf +++ b/backends/platform/symbian/help/ScummVM.rtf @@ -1,16 +1,16 @@ -{\rtf1\ansi\ansicpg1251\uc1 \deff0\deflang1049\deflangfe1049{\fonttbl{\f0\froman\fcharset204\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fswiss\fcharset204\fprq2{\*\panose 020b0604020202020204}Arial;} +{\rtf1\ansi\ansicpg1251\uc1 \deff1\deflang1049\deflangfe1049{\fonttbl{\f0\froman\fcharset204\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fswiss\fcharset204\fprq2{\*\panose 020b0604020202020204}Arial;} {\f2\fmodern\fcharset204\fprq1{\*\panose 02070309020205020404}Courier New;}{\f3\froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}{\f8\froman\fcharset0\fprq2{\*\panose 00000000000000000000}Tms Rmn;} {\f14\fnil\fcharset2\fprq2{\*\panose 05000000000000000000}Wingdings;}{\f28\fswiss\fcharset204\fprq2{\*\panose 020b0604020202020204}Arial CYR;}{\f29\fmodern\fcharset204\fprq1{\*\panose 02070309020205020404}Courier New CYR;} -{\f43\froman\fcharset2\fprq2{\*\panose 05030102010509060703}Webdings;}{\f97\fswiss\fcharset204\fprq2{\*\panose 020b0506020202030204}Arial Narrow;}{\f109\froman\fcharset0\fprq2 Times New Roman;}{\f107\froman\fcharset238\fprq2 Times New Roman CE;} -{\f110\froman\fcharset161\fprq2 Times New Roman Greek;}{\f111\froman\fcharset162\fprq2 Times New Roman Tur;}{\f112\froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f113\froman\fcharset178\fprq2 Times New Roman (Arabic);} -{\f114\froman\fcharset186\fprq2 Times New Roman Baltic;}{\f117\fswiss\fcharset0\fprq2 Arial;}{\f115\fswiss\fcharset238\fprq2 Arial CE;}{\f118\fswiss\fcharset161\fprq2 Arial Greek;}{\f119\fswiss\fcharset162\fprq2 Arial Tur;} -{\f120\fswiss\fcharset177\fprq2 Arial (Hebrew);}{\f121\fswiss\fcharset178\fprq2 Arial (Arabic);}{\f122\fswiss\fcharset186\fprq2 Arial Baltic;}{\f125\fmodern\fcharset0\fprq1 Courier New;}{\f123\fmodern\fcharset238\fprq1 Courier New CE;} -{\f126\fmodern\fcharset161\fprq1 Courier New Greek;}{\f127\fmodern\fcharset162\fprq1 Courier New Tur;}{\f128\fmodern\fcharset177\fprq1 Courier New (Hebrew);}{\f129\fmodern\fcharset178\fprq1 Courier New (Arabic);} -{\f130\fmodern\fcharset186\fprq1 Courier New Baltic;}{\f333\fswiss\fcharset0\fprq2 Arial CYR;}{\f331\fswiss\fcharset238\fprq2 Arial CYR CE;}{\f334\fswiss\fcharset161\fprq2 Arial CYR Greek;}{\f335\fswiss\fcharset162\fprq2 Arial CYR Tur;} -{\f336\fswiss\fcharset177\fprq2 Arial CYR (Hebrew);}{\f337\fswiss\fcharset178\fprq2 Arial CYR (Arabic);}{\f338\fswiss\fcharset186\fprq2 Arial CYR Baltic;}{\f341\fmodern\fcharset0\fprq1 Courier New CYR;}{\f339\fmodern\fcharset238\fprq1 Courier New CYR CE;} -{\f342\fmodern\fcharset161\fprq1 Courier New CYR Greek;}{\f343\fmodern\fcharset162\fprq1 Courier New CYR Tur;}{\f344\fmodern\fcharset177\fprq1 Courier New CYR (Hebrew);}{\f345\fmodern\fcharset178\fprq1 Courier New CYR (Arabic);} -{\f346\fmodern\fcharset186\fprq1 Courier New CYR Baltic;}{\f885\fswiss\fcharset0\fprq2 Arial Narrow;}{\f883\fswiss\fcharset238\fprq2 Arial Narrow CE;}{\f886\fswiss\fcharset161\fprq2 Arial Narrow Greek;}{\f887\fswiss\fcharset162\fprq2 Arial Narrow Tur;} -{\f890\fswiss\fcharset186\fprq2 Arial Narrow Baltic;}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255; +{\f30\froman\fcharset2\fprq2{\*\panose 05030102010509060703}Webdings;}{\f31\fswiss\fcharset204\fprq2{\*\panose 020b0506020202030204}Arial Narrow;}{\f44\froman\fcharset0\fprq2 Times New Roman;}{\f42\froman\fcharset238\fprq2 Times New Roman CE;} +{\f45\froman\fcharset161\fprq2 Times New Roman Greek;}{\f46\froman\fcharset162\fprq2 Times New Roman Tur;}{\f47\froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f48\froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\f49\froman\fcharset186\fprq2 Times New Roman Baltic;}{\f52\fswiss\fcharset0\fprq2 Arial;}{\f50\fswiss\fcharset238\fprq2 Arial CE;}{\f53\fswiss\fcharset161\fprq2 Arial Greek;}{\f54\fswiss\fcharset162\fprq2 Arial Tur;} +{\f55\fswiss\fcharset177\fprq2 Arial (Hebrew);}{\f56\fswiss\fcharset178\fprq2 Arial (Arabic);}{\f57\fswiss\fcharset186\fprq2 Arial Baltic;}{\f60\fmodern\fcharset0\fprq1 Courier New;}{\f58\fmodern\fcharset238\fprq1 Courier New CE;} +{\f61\fmodern\fcharset161\fprq1 Courier New Greek;}{\f62\fmodern\fcharset162\fprq1 Courier New Tur;}{\f63\fmodern\fcharset177\fprq1 Courier New (Hebrew);}{\f64\fmodern\fcharset178\fprq1 Courier New (Arabic);} +{\f65\fmodern\fcharset186\fprq1 Courier New Baltic;}{\f268\fswiss\fcharset0\fprq2 Arial CYR;}{\f266\fswiss\fcharset238\fprq2 Arial CYR CE;}{\f269\fswiss\fcharset161\fprq2 Arial CYR Greek;}{\f270\fswiss\fcharset162\fprq2 Arial CYR Tur;} +{\f271\fswiss\fcharset177\fprq2 Arial CYR (Hebrew);}{\f272\fswiss\fcharset178\fprq2 Arial CYR (Arabic);}{\f273\fswiss\fcharset186\fprq2 Arial CYR Baltic;}{\f276\fmodern\fcharset0\fprq1 Courier New CYR;}{\f274\fmodern\fcharset238\fprq1 Courier New CYR CE;} +{\f277\fmodern\fcharset161\fprq1 Courier New CYR Greek;}{\f278\fmodern\fcharset162\fprq1 Courier New CYR Tur;}{\f279\fmodern\fcharset177\fprq1 Courier New CYR (Hebrew);}{\f280\fmodern\fcharset178\fprq1 Courier New CYR (Arabic);} +{\f281\fmodern\fcharset186\fprq1 Courier New CYR Baltic;}{\f292\fswiss\fcharset0\fprq2 Arial Narrow;}{\f290\fswiss\fcharset238\fprq2 Arial Narrow CE;}{\f293\fswiss\fcharset161\fprq2 Arial Narrow Greek;}{\f294\fswiss\fcharset162\fprq2 Arial Narrow Tur;} +{\f297\fswiss\fcharset186\fprq2 Arial Narrow Baltic;}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255; \red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\stylesheet{ \ql \li0\ri0\sa120\widctlpar\nooverflow\faroman\rin0\lin0\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 \snext0 Normal;}{\s1\ql \li0\ri0\sb360\sa240\keepn\widctlpar\nooverflow\faroman\rin0\lin0\itap0 \b\f1\fs32\lang2057\langfe1033\kerning28\cgrid\langnp2057\langfenp1033 \sbasedon0 \snext0 heading 1;}{\s2\ql \li0\ri0\sb120\sa120\keepn\widctlpar\brdrt\brdrs\brdrw30\brsp20 \brdrb\brdrs\brdrw30\brsp20 \tqr\tx9072\nooverflow\faroman\rin0\lin0\itap0 @@ -22,14 +22,14 @@ heading 5;}{\s6\ql \li0\ri0\sb240\sa60\widctlpar\nooverflow\faroman\rin0\lin0\it \s9\ql \li0\ri0\sb240\sa60\widctlpar\nooverflow\faroman\rin0\lin0\itap0 \i\f1\fs18\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 \sbasedon0 \snext0 heading 9;}{\*\cs10 \additive Default Paragraph Font;}{\*\cs15 \additive \b\f1\fs20 \sbasedon10 App Text;}{\s16\ql \li0\ri0\sb360\sa240\keepn\widctlpar\nooverflow\faroman\rin0\lin0\itap0 \b\f1\fs32\cf9\lang2057\langfe1033\kerning28\cgrid\langnp2057\langfenp1033 \sbasedon0 \snext16 Category UID;}{ \s17\ql \li0\ri0\sa120\widctlpar\nooverflow\faroman\rin0\lin0\itap0 \i\f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 \sbasedon0 \snext17 Comment;}{\s18\ql \fi-283\li283\ri0\sa120\widctlpar\brdrb\brdrs\brdrw15\brsp20 {\*\pn -\pnlvlblt\ilvl10\ls2047\pnrnot0\pnf43\pnstart1\pnindent283\pnhang{\pntxtb \'a2}}\nooverflow\faroman\ls2047\ilvl10\rin0\lin283\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 \sbasedon0 \snext18 Context;}{\*\cs19 \additive +\pnlvlblt\ilvl10\ls2047\pnrnot0\pnf30\pnstart1\pnindent283\pnhang{\pntxtb \'a2}}\nooverflow\faroman\ls2047\ilvl10\rin0\lin283\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 \sbasedon0 \snext18 Context;}{\*\cs19 \additive \i\f1\fs20\ulnone\cf0\nosupersub \sbasedon10 Context Comment;}{\s20\ql \li0\ri0\sa120\widctlpar\nooverflow\faroman\rin0\lin0\itap0 \f1\fs20\cf11\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 \sbasedon0 \snext20 Definition Term;}{ -\s21\ql \li0\ri0\sa120\widctlpar\nooverflow\faroman\rin0\lin0\itap0 \f1\fs20\cf11\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 \sbasedon20 \snext21 Definition Definition;}{\*\cs22 \additive \scaps\f97\fs20\cf13 \sbasedon10 Graphic Link;}{ +\s21\ql \li0\ri0\sa120\widctlpar\nooverflow\faroman\rin0\lin0\itap0 \f1\fs20\cf11\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 \sbasedon20 \snext21 Definition Definition;}{\*\cs22 \additive \scaps\f31\fs20\cf13 \sbasedon10 Graphic Link;}{ \s23\ql \fi-283\li283\ri0\sa120\widctlpar{\*\pn \pnlvlblt\ilvl10\ls2047\pnrnot0\pnf14\pnstart1\pnindent283\pnhang{\pntxtb F}}\nooverflow\faroman\ls2047\ilvl10\rin0\lin283\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 \sbasedon0 \snext23 Tip;}{\s24\ql \fi-283\li283\ri0\sa120\widctlpar{\*\pn \pnlvlblt\ilvl10\ls2047\pnrnot0\pnf14\pnstart1\pnindent283\pnhang{\pntxtb ?}}\nooverflow\faroman\ls2047\ilvl10\rin0\lin283\itap0 -\f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 \sbasedon23 \snext24 Note;}{\s25\ql \fi-283\li283\ri0\sa120\widctlpar{\*\pn \pnlvlblt\ilvl10\ls2047\pnrnot0\pnf43\pnstart1\pnindent283\pnhang{\pntxtb ~}} +\f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 \sbasedon23 \snext24 Note;}{\s25\ql \fi-283\li283\ri0\sa120\widctlpar{\*\pn \pnlvlblt\ilvl10\ls2047\pnrnot0\pnf30\pnstart1\pnindent283\pnhang{\pntxtb ~}} \nooverflow\faroman\ls2047\ilvl10\rin0\lin283\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 \sbasedon24 \snext25 Important;}{\s26\ql \fi-283\li283\ri0\sa120\widctlpar\brdrb\brdrs\brdrw15\brsp20 {\*\pn \pnlvlblt\ilvl10\ls2047\pnrnot0 -\pnf43\pnstart1\pnindent283\pnhang{\pntxtb i}}\nooverflow\faroman\ls2047\ilvl10\rin0\lin283\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 \sbasedon0 \snext26 Index;}{\*\cs27 \additive \b\f2\fs20 \sbasedon10 Key Name;}{ +\pnf30\pnstart1\pnindent283\pnhang{\pntxtb i}}\nooverflow\faroman\ls2047\ilvl10\rin0\lin283\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 \sbasedon0 \snext26 Index;}{\*\cs27 \additive \b\f2\fs20 \sbasedon10 Key Name;}{ \s28\ql \fi-284\li284\ri0\sa120\widctlpar{\*\pn \pnlvlbody\ilvl11\ls2047\pnrnot0\pndec\pnstart1\pnindent283\pnhang{\pntxta .}}\nooverflow\faroman\ls2047\ilvl11\rin0\lin284\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 \sbasedon0 \snext28 List Number;}{\s29\ql \fi-284\li284\ri0\sa120\widctlpar\tx284{\*\pn \pnlvlbody\ilvl0\ls2047\pnrnot0\pndec\pnf8 }\nooverflow\faroman\ls2047\rin0\lin284\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 \sbasedon28 \snext29 List Manual;}{\s30\ql \fi-284\li568\ri0\sa120\widctlpar{\*\pn \pnlvlbody\ilvl11\ls2047\pnrnot0\pndec\pnstart1\pnindent283\pnhang{\pntxta .}}\nooverflow\faroman\ls2047\ilvl11\rin0\lin568\itap0 @@ -44,34 +44,43 @@ Synonyms;}{\*\cs33 \additive \super \sbasedon10 endnote reference;}{\s34\ql \fi- {\list\listtemplateid1907811784\listsimple{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li643\jclisttab\tx643 }{\listname ;}\listid-125}{\list\listtemplateid1912741052\listsimple{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\chbrdr \brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid-120}{\list\listtemplateid-51363132\listsimple{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0 -{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid-119}}{\*\listoverridetable{\listoverride\listid-120\listoverridecount0\ls1} -{\listoverride\listid-129\listoverridecount0\ls2}{\listoverride\listid-119\listoverridecount0\ls3}{\listoverride\listid-125\listoverridecount0\ls4}}{\info{\author Fedor}{\operator Fedor}{\creatim\yr2013\mo11\dy30\hr23\min4} -{\revtim\yr2013\mo11\dy30\hr23\min24}{\version4}{\edmins20}{\nofpages7}{\nofwords1441}{\nofchars8219}{\*\company DEV}{\nofcharsws10093}{\vern8249}}\margl1701\margr850\margt1134\margb1134 -\deftab708\widowctrl\ftnbj\aenddoc\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\hyphcaps0\horzdoc\dghspace120\dgvspace120\dghorigin1701\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind4\viewscale100\nolnhtadjtbl \fet0\sectd -\linex0\sectdefaultcl {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang -{\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl8 -\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}\pard\plain \s17\ql \li0\ri0\sa120\widctlpar\nooverflow\faroman\rin0\lin0\itap0 -\i\f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {\lang1033\langfe1033\langnp1033 Author: Fedor Strizhniou.}{\f28 +{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid-119}{\list\listtemplateid947971744\listsimple{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0 +\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext\'01*;}{\levelnumbers;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 }{\listname ;}\listid-2}}{\*\listoverridetable{\listoverride\listid-120\listoverridecount0\ls1} +{\listoverride\listid-129\listoverridecount0\ls2}{\listoverride\listid-119\listoverridecount0\ls3}{\listoverride\listid-125\listoverridecount0\ls4}{\listoverride\listid-120\listoverridecount0\ls5}{\listoverride\listid-129\listoverridecount0\ls6} +{\listoverride\listid-119\listoverridecount0\ls7}{\listoverride\listid-125\listoverridecount0\ls8}{\listoverride\listid-120\listoverridecount0\ls9}{\listoverride\listid-129\listoverridecount0\ls10}{\listoverride\listid-119\listoverridecount0\ls11} +{\listoverride\listid-125\listoverridecount0\ls12}{\listoverride\listid-120\listoverridecount0\ls13}{\listoverride\listid-129\listoverridecount0\ls14}{\listoverride\listid-119\listoverridecount0\ls15}{\listoverride\listid-125\listoverridecount0\ls16} +{\listoverride\listid-2\listoverridecount1{\lfolevel\listoverrideformat{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelold\levelspace0\levelindent283{\leveltext\'01\u-3991 ?;}{\levelnumbers;}\f30\chbrdr +\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-283\li283 }}\ls17}{\listoverride\listid-2\listoverridecount1{\lfolevel\listoverrideformat{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelold\levelspace0 +\levelindent283{\leveltext\'01\u-3991 ?;}{\levelnumbers;}\f30\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-283\li283 }}\ls18}}{\info{\author Fedor}{\operator Fedor}{\creatim\yr2013\mo11\dy30\hr23\min4} +{\revtim\yr2013\mo12\dy14\hr12\min27}{\version95}{\edmins91}{\nofpages8}{\nofwords1514}{\nofchars8634}{\*\company DEV}{\nofcharsws0}{\vern8249}}\margl1701\margr850\margt1134\margb1134 +\deftab708\widowctrl\ftnbj\aenddoc\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\hyphcaps0\horzdoc\dghspace120\dgvspace120\dghorigin1701\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind4\viewscale100\nolnhtadjtbl \fet0{\*\template +E:\\Documents and Settings\\Administrator\\Application Data\\Microsoft\\\'d8\'e0\'e1\'eb\'ee\'ed\'fb\\cshelp2000.dot}\sectd \linex0\sectdefaultcl {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang +{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang{\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang +{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}\pard\plain +\s17\ql \li0\ri0\sa120\widctlpar\nooverflow\faroman\rin0\lin0\itap0 \i\f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {\lang1033\langfe1033\langnp1033 Author: Fedor Strizhniou.}{\f28 \par }{\lang1033\langfe1033\langnp1033 Date: November 2013}{\f28 \par }{\lang1033\langfe1033\langnp1033 Version: 1.7.0 \par }\pard\plain \s1\ql \li0\ri0\sb360\sa240\keepn\widctlpar\nooverflow\faroman\outlinelevel0\rin0\lin0\itap0 \b\f1\fs32\lang2057\langfe1033\kerning28\cgrid\langnp2057\langfenp1033 {ScummVM Help \par }\pard\plain \s16\ql \li0\ri0\sb360\sa240\keepn\widctlpar\nooverflow\faroman\rin0\lin0\itap0 \b\f1\fs32\cf9\lang2057\langfe1033\kerning28\cgrid\langnp2057\langfenp1033 {\lang1033\langfe1033\langnp1033 0x100039ce}{\lang1059\langfe1033\langnp1059 \par }\pard\plain \ql \li0\ri0\sa120\widctlpar\nooverflow\faroman\rin0\lin0\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {\f28 -\par }\pard\plain \s2\ql \li0\ri0\sb120\sa120\keepn\widctlpar\brdrt\brdrs\brdrw30\brsp20 \brdrb\brdrs\brdrw30\brsp20 \tqr\tx9072\nooverflow\faroman\outlinelevel1\rin0\lin0\itap0 \b\f1\fs24\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {\b0\f28 Introduction - -\par }\pard\plain \ql \li0\ri0\sa120\widctlpar\nooverflow\faroman\rin0\lin0\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {\f28 +\par }\pard\plain \s2\ql \li0\ri0\sb120\sa120\keepn\widctlpar\brdrt\brdrs\brdrw30\brsp20 \brdrb\brdrs\brdrw30\brsp20 \tqr\tx9072\nooverflow\faroman\outlinelevel1\rin0\lin0\itap0 \b\f1\fs24\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {\b0\f28 +About ScummVM Help +\par {\pntext\pard\plain\s26 \f30\fs20\lang2057\langfe1033\langnp2057\langfenp1033 \loch\af30\dbch\af0\hich\f30 \'69\tab}}\pard\plain \s26\ql \fi-283\li283\ri0\sa120\widctlpar\brdrb\brdrs\brdrw15\brsp20 {\*\pn \pnlvlblt\ilvl0\ls17\pnrnot0 +\pnf30\pnstart1\pnindent283\pnhang{\pntxtb i}}\nooverflow\faroman\ls17\rin0\lin283\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {About ScummVM Help +\par }\pard\plain \ql \li0\ri0\sa120\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\nooverflow\faroman\rin0\lin0\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {\f28 +\par }{ +This help file based on ScummVM forum thread with some elaborations(in Anotherguest section) and text correction. If you wish add some text or translate you may download and modify source document from https://sourceforge.net/projects/scummvms60git/ and t +hen send me to fedor_qd@mail.ru +\par Feel free to replace, merge or write you own instead 1st, 2nd and 3rd guides. Other sections require strict translations. And don\rquote t forget add your name :-) +\par First guide contain help by Anotherguest, second - VincentJ, third - murgo. This doc created by Fedor Strizhniou. +\par Enjoys, cheers! Always yours =)}{\lang1059\langfe1033\langnp1059 \par }{\f29 -This help file based on ScummVM forum thread with some elaborations(in Anotherguest section) and text correction. If you wish add some text you may download and modify source document from https://sourceforge.net/projects/scummvms60git/ and then send me t -o fedor_qd@mail.ru -\par First guide contain help by Anotherguest, second - VincentJ, third - murgo. -\par Enjoys, cheers! Always yous, Fedor Strizhniou =)}{\f29\lang1059\langfe1033\langnp1059 -\par }{\f29 -\par }\pard\plain \s2\ql \li0\ri0\sb120\sa120\keepn\widctlpar\brdrt\brdrs\brdrw30\brsp20 \brdrb\brdrs\brdrw30\brsp20 \tqr\tx9072\nooverflow\faroman\outlinelevel1\rin0\lin0\itap0 \b\f1\fs24\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {\b0\f28 First guide - -\par }\pard\plain \s32\ql \li0\ri0\sa120\widctlpar\nooverflow\faroman\rin0\lin0\itap0 \f1\fs20\cf13\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {Controls, Virtual keyboard, Shortcuts, ScummVM, Tips, S60, UIQ, UIQ3, S80, s80, S90, s90 -\par }\pard\plain \ql \li0\ri0\sa120\widctlpar\nooverflow\faroman\rin0\lin0\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {\f28 -\par -\par }{\f29 UIQ3 devices: To the top right (holding the phone portrait) you four icons, from the top they are +\par }\pard\plain \s2\ql \li0\ri0\sb120\sa120\keepn\widctlpar\brdrt\brdrs\brdrw30\brsp20 \brdrb\brdrs\brdrw30\brsp20 \tqr\tx9072{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\nooverflow\faroman\outlinelevel1\rin0\lin0\itap0 +\b\f1\fs24\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {\b0\f28 1st guide +\par {\pntext\pard\plain\s26 \f30\fs20\lang2057\langfe1033\langnp2057\langfenp1033 \loch\af30\dbch\af0\hich\f30 \'69\tab}}\pard\plain \s26\ql \fi-283\li283\ri0\sa120\widctlpar\brdrb\brdrs\brdrw15\brsp20 {\*\pn \pnlvlblt\ilvl0\ls17\pnrnot0 +\pnf30\pnstart1\pnindent283\pnhang{\pntxtb i}}\nooverflow\faroman\ls17\rin0\lin283\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {Controls, Virtual keyboard, Shortcuts, ScummVM, Tips, S60, UIQ, UIQ3, S80, s80, S90, s90 +\par }\pard\plain \ql \li0\ri0\sa120\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\nooverflow\faroman\rin0\lin0\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {\f28 +\par }{UIQ3 devices: To the top right (holding the phone portrait) you four icons, from the top they are \par \par * Toggle control mode, in control mode you can change text input , screen orientation and screen scaling \par * Mouse button, toggles between left, right and no button when tapping the screen. If no button is selected, 7 & Space works as left mouse button and 9 & Enter works as the right mouse button. @@ -81,11 +90,11 @@ o fedor_qd@mail.ru \par * Enter key \par * Backspace \par * Arrow Up/Down to scroll the keys available -\par * Virtual keyboard, tap letters to simulate keypresses. +\par * Virtual keyboard, tap letters to simulate key presses. \par \par S60 and UIQ3 devices: (Control Key = Green Phone key, to activate/deactivate control mode in SDL) -\par -\par * 1 = change Input Mode: Joystick | Keyboard | Cursor +\par }{\f29 +\par }{* 1 = change Input Mode: Joystick | Keyboard | Cursor \par * 2,'p' = change Video Mode: Landscape | Portrait \par * 3,'f' = change Orientation Mode for Landscape: 90\'b0 Left | 90\'b0 Right \par * 4,'s' = Toggle between stretched and non-stretched modes @@ -95,7 +104,7 @@ o fedor_qd@mail.ru \par * 9,'j' = Joystick input \par * 0,'m' = Mouse input \par * Up/Down = Alter global volume when not in 1-1 VGA mode. Pan around in VGA 1-1 Mode -\par * # = On/Off screen keyboard transparency +\par * # = On/Off screen keyboard transparency in some games \par \par S80 devices: \par @@ -110,65 +119,65 @@ o fedor_qd@mail.ru \par \par What are these Joystick, Keyboard and Cursor modes anyway? \par }{\f28 -\par }{\f29 Joystick mode sends SDL joystick events to ScummVM which acts as a mouse control in ScummVM. Cursor mod -e sends keyboard arrows instead, so for example it can be used to navigate through directorylist (one hand use perhaps!?) or save games etc. Keyboard mode is only available for S60 and enables multi-tap to enter text characters in save dialogs. These mode -s are implemented at the underlying SDL level, so this determines the types of events that ScummVM receives from SDL. +\par }{Joystick mode sends SDL joystick events to ScummVM which acts as a mouse control in ScummVM. Cursor mode sends keyboard arrows instead, so for example it can be used to navigate +through directorylist (one hand use perhaps!?) or save games etc. Keyboard mode is only available for S60 and enables multi-tap to enter text characters in save dialogs. These modes are implemented at the underlying SDL level, so this determines the types + of events that ScummVM receives from SDL. \par What are these Shrinked, Zoomed and Upscaled modes anyway? \par -\par Shrink displays the game on your screen but in a shrinked way, either in Portra -it or Landscape mode, so not all the pixels can be seen. Zoom mode uses the maximum resolution of your phone displaying a smaller part of the game zoomed at 1:1 pixels. For scrolling in S60 Zoom mode: 0+Cursor keys to scroll around, 0+Ok button to center -view. Upscale tries to fill the larger screens on S80/S90 devices in a better way for low resolution games. Currently it uses a pixel interpolation upscaling routine. +\par Shrink displays the game on your screen but in a shrinked way, either in Portrait or Landscape mode, so not all the pixels can be seen. Zoom mode uses the maximum resolution of your phone displaying a smaller part of the game zoomed at 1:1 pixels. For scr +olling in S60 Zoom mode: 0+Cursor keys to scroll around, 0+Ok button to center view. Upscale tries to fill the larger screens on S80/S90 devices in a better way for low resolution games. Currently it uses a pixel interpolation upscaling routine. \par \par You can also use a bluetooth mouse with S60v3 devices to control your game. You need the bluetooth hid library from Hinkka http://koti.mbnet.fi/hinkka/Download.html to get it to work properly. +\par }{\f29 \par +\par }\pard\plain \s2\ql \li0\ri0\sb120\sa120\keepn\widctlpar\brdrt\brdrs\brdrw30\brsp20 \brdrb\brdrs\brdrw30\brsp20 \tqr\tx9072{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\nooverflow\faroman\outlinelevel1\rin0\lin0\itap0 +\b\f1\fs24\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {\b0\f28 2nd guide +\par {\pntext\pard\plain\s26 \f30\fs20\lang2057\langfe1033\langnp2057\langfenp1033 \loch\af30\dbch\af0\hich\f30 \'69\tab}}\pard\plain \s26\ql \fi-283\li283\ri0\sa120\widctlpar\brdrb\brdrs\brdrw15\brsp20 {\*\pn \pnlvlblt\ilvl0\ls17\pnrnot0 +\pnf30\pnstart1\pnindent283\pnhang{\pntxtb i}}\nooverflow\faroman\ls17\rin0\lin283\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {Controls, Virtual keyboard, Shortcuts, ScummVM, Tips, S60, s60 +\par }\pard\plain \ql \li0\ri0\sa120\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\nooverflow\faroman\rin0\lin0\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {\f28 \par -\par }\pard\plain \s2\ql \li0\ri0\sb120\sa120\keepn\widctlpar\brdrt\brdrs\brdrw30\brsp20 \brdrb\brdrs\brdrw30\brsp20 \tqr\tx9072\nooverflow\faroman\outlinelevel1\rin0\lin0\itap0 \b\f1\fs24\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {\b0\f28 Second guide - -\par }\pard\plain \s32\ql \li0\ri0\sa120\widctlpar\nooverflow\faroman\rin0\lin0\itap0 \f1\fs20\cf13\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {Controls, Virtual keyboard, Shortcuts, ScummVM, Tips, S60, s60 -\par }\pard\plain \ql \li0\ri0\sa120\widctlpar\nooverflow\faroman\rin0\lin0\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {\f28 -\par -\par }{\f29 More user-friendly guide for Nokia phones (based on N96 but should apply to most phones) +\par }{More user-friendly guide for Nokia phones (based on N96 but should apply to most phones) \par \par Left Soft Key - Left Click \par }{\f28 -\par }{\f29 Right Soft Key - Right Click +\par }{Right Soft Key - Right Click \par }{\f28 -\par }{\f29 Navigation buttons - Move pointer on screen +\par }{Navigation buttons - Move pointer on screen \par }{\f28 -\par }{\f29 "C" or "Delete Key" - Space Bar (i.e. skip dialogue/cutscene) +\par }{"C" or "Delete Key" - Space Bar (i.e. skip dialogue/cutscene) \par }{\f28 -\par }{\f29 * - Bring up Menu (to Save, Load and change the game's options e.g. enable subtitles, speech etc. Varies from game to game) +\par }{* - Bring up Menu (to Save, Load and change the game's options e.g. enable subtitles, speech etc. Varies from game to game) \par \par The <> is a toggling left right mode. I.e. first click is left, next is right, next is left etc. \par \par Call Button - Enter/Exit Configuration Mode \par }{\f28 -\par }{\f29 Configuration Mode, when activated, shows the word "CTRL" in green in the upper right corner of the screen. It allows to quickly switch between various functions of ScummVM. The following buttons on your keypad are activated when "CTRL" is disp -layed- -\par -\par 1 - Change Input. +\par }{Configuration Mode, when activated, shows the word "CTRL" in green in the upper right corner of the screen. It allows to quickly switch between various functions of ScummVM. The following buttons on your keypad are activated when "CTRL" is displayed : + +\par }{\f29 +\par }{1 - Change Input. \par This is the option you'll probably use the most. There are three settings; A,C and J. \par -\par A - This is the "Text Input" mode. It allows you to type directly into ScummVM as if you were using a keyboard. Type the same way you would whe -n sending a text message off of your phone. Please note that the pointer is disabled when in this mode. Don't forget to exit Configuration Mode before typing! +\par A - This is the "Text Input" mode. It allows you to type directl +y into ScummVM as if you were using a keyboard. Type the same way you would when sending a text message off of your phone. Please note that the pointer is disabled when in this mode. Don't forget to exit Configuration Mode before typing! \par \par C - This is the "Cursor" mode. This emulates the arrow keys of the keyboard. Some games require using this instead of the mouse (e.g. the destruction derby section towards the end of Full Throttle). \par \par J - This is the "Joystick/Mouse" mode. Simply put, it allows you to use the navigation buttons to move the pointer around the screen. The left and right mouse buttons are used by the left and right Soft keys. \par \par The "C" button emulates the space bar, i.e. skip line of dialogue, skip cutscene or pause game (depending on the game, some games simply use the left mouse button to skip dialogue in which case it will pause the game instead) -\par -\par 2 - Toggle Landscape and Portrait +\par }{\f29 +\par }{2 - Toggle Landscape and Portrait \par Switches the screen output between having the phone held normally (Portrait) or on its side (Landscape). You'll probably never take it off Landscape mode as it offers the better display area. \par \par 3 - Change Landscape Orientation \par Only applies to Landscape mode, simply swaps the screen output between having the phone tilted on its left side or on its right side. \par \par 4 - Toggle Zoom On and Off -\par Zooms in on a portion of the screen. Handy for when you are looking through a screen for items or having trouble reading subtitles. Use the navigation buttons for panning around the play area. Don't forget you'll have to exit out of Configuration Mode bef -ore you can move the pointer again. Exiting Configuration Mode does not reset the zoom level. -\par -\par 5 & 6 - Unused +\par Zooms in on a portion of the screen. Handy for when you are looking through a screen for items or having trouble reading subtitles. Use the navigation buttons for panning around the play area. Don't forget you'll have to exit out of Confi +guration Mode before you can move the pointer again. Exiting Configuration Mode does not reset the zoom level. +\par }{\f29 +\par }{5 & 6 - Unused \par \par 7 - "Text Input" mode. Shortcut for entering "Text Input" mode directly instead of cycling through the other input types using the "1" key. \par @@ -183,16 +192,16 @@ ore you can move the pointer again. Exiting Configuration Mode does not reset th \par Up Navigation Button - Increase ScummVM sound volume. Note that the game itself may have its own independent sound settings (usually found under the * menu) \par \par Down Navigation Button - Decrease ScummVM sound volume. Note that the game itself may have its own independent sound settings (usually found under the * menu) +\par }{\f29 \par +\par }\pard\plain \s2\ql \li0\ri0\sb120\sa120\keepn\widctlpar\brdrt\brdrs\brdrw30\brsp20 \brdrb\brdrs\brdrw30\brsp20 \tqr\tx9072{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\nooverflow\faroman\outlinelevel1\rin0\lin0\itap0 +\b\f1\fs24\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {\b0\f28 3rd guide +\par {\pntext\pard\plain\s26 \f30\fs20\lang2057\langfe1033\langnp2057\langfenp1033 \loch\af30\dbch\af0\hich\f30 \'69\tab}}\pard\plain \s26\ql \fi-283\li283\ri0\sa120\widctlpar\brdrb\brdrs\brdrw15\brsp20 {\*\pn \pnlvlblt\ilvl0\ls17\pnrnot0 +\pnf30\pnstart1\pnindent283\pnhang{\pntxtb i}}\nooverflow\faroman\ls17\rin0\lin283\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {Controls, Virtual keyboard, Shortcuts, ScummVM, Tips, S60, s60 +\par }\pard\plain \ql \li0\ri0\sa120\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\nooverflow\faroman\rin0\lin0\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {\f28 \par -\par }\pard\plain \s2\ql \li0\ri0\sb120\sa120\keepn\widctlpar\brdrt\brdrs\brdrw30\brsp20 \brdrb\brdrs\brdrw30\brsp20 \tqr\tx9072\nooverflow\faroman\outlinelevel1\rin0\lin0\itap0 \b\f1\fs24\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {\b0\f28 Third guide - -\par }\pard\plain \s32\ql \li0\ri0\sa120\widctlpar\nooverflow\faroman\rin0\lin0\itap0 \f1\fs20\cf13\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {Controls, Virtual keyboard, Shortcuts, ScummVM, Tips, S60, s60 -\par }\pard\plain \ql \li0\ri0\sa120\widctlpar\nooverflow\faroman\rin0\lin0\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {\f28 -\par -\par }{\f29 ScummVM keys on Nokia e71 -(most likely on any other qwerty-device, too), tested on version 0.14.0svn (Feb. 18 2009 05:56:07). Number keys are inserted by first pressing fn-key (leftmost key at bottom row on E71) and then pressing correct key (e.g. 5 is fn+g). You don't have to pre -ss both keys simultaneously. +\par }{ScummVM keys on Nokia e71 (most likely on any other qwerty-device, too), tested on version 0.14.0svn (Feb. 18 2009 + 05:56:07). Number keys are inserted by first pressing fn-key (leftmost key at bottom row on E71) and then pressing correct key (e.g. 5 is fn+g). You don't have to press both keys simultaneously. \par \par Basic keys: \par @@ -233,8 +242,8 @@ ss both keys simultaneously. \par t -- Talk to \par s -- Push \par y -- Pull -\par -\par and in Full Throttle (from the top of my head): +\par }{\f29 +\par }{and in Full Throttle (from the top of my head): \par \par k -- kick (foot) \par t -- talk (mouth) @@ -242,13 +251,13 @@ ss both keys simultaneously. \par p -- punch (hand) \par \par AGI games (King's Quest, Police Quest etc.): -\par The games work beautifully on the E71, but there's some stupid bugs (in input). I recall fi -nding some debug keys and "last sentence" / "inventory" -keys in earlier version, but I can't find them any more. Also you can't turn on sirens in Police Quest, which kinda makes it unplayable. +\par The games work beautifully on the E71, but there's some stupid bugs (in input). I recall finding some debug keys and "last sentence" / "inventory" -keys in earlier version, but I can't find them any more. Also you can't turn on sirens in Police Quest, whi +ch kinda makes it unplayable. \par \par There's good side and bad side to each input mode: \par Keyboard (I use this primarily) -\par -\par * goes to menu +\par }{\f29 +\par }{* goes to menu \par + you can erase text \par + moving is relatively easy \par - you can't type in UPPER CASE @@ -256,11 +265,75 @@ nding some debug keys and "last sentence" / "inventory" -keys in earlier version \par - worthless 'current key' -display on left top corner \par \par Joystick / Cursor: -\par -\par + you can access menus +\par }{\f29 +\par }{+ you can access menus \par + you can type numbers (just make sure f-letter in left top corner is red before clicking "numbers". It works kinda funnily, but you'll get hang of it.) \par - you move mouse cursor which makes walking harder (joystick mode) \par - you can't erase text -\par -\par There might be some mistakes and some keys missing from the list, feel free to pm me corrections / suggestions.}{\f28 +\par }{\f28 +\par }\pard\plain \s2\ql \li0\ri0\sb120\sa120\keepn\widctlpar\brdrt\brdrs\brdrw30\brsp20 \brdrb\brdrs\brdrw30\brsp20 \tqr\tx9072{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\nooverflow\faroman\outlinelevel1\rin0\lin0\itap0 +\b\f1\fs24\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {ScummVM1 engines list +\par {\pntext\pard\plain\s26 \f30\fs20\lang2057\langfe1033\langnp2057\langfenp1033 \loch\af30\dbch\af0\hich\f30 \'69\tab}}\pard\plain \s26\ql \fi-283\li283\ri0\sa120\widctlpar\brdrb\brdrs\brdrw15\brsp20 {\*\pn \pnlvlblt\ilvl0\ls18\pnrnot0 +\pnf30\pnstart1\pnindent283\pnhang{\pntxtb i}}\nooverflow\faroman\ls18\rin0\lin283\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {Supported games +\par }\pard\plain \ql \li0\ri0\sa120\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\nooverflow\faroman\rin0\lin0\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {agi +\par agos +\par \tab AGOS2 +\par cine +\par composer +\par cruise +\par drascula +\par gob +\par groovie +\par \tab GROOVIE2 +\par kyra +\par \tab EOB +\par \tab LOL +\par lastexpress +\par made +\par neverhood +\par parallaction +\par queen +\par saga +\par \tab IHNM +\par \tab SAGA2 +\par scumm +\par \tab HE +\par \tab SCUMM_7_8 +\par touche +\par tucker +\par wintermute +\par +\par }\pard\plain \s2\ql \li0\ri0\sb120\sa120\keepn\widctlpar\brdrt\brdrs\brdrw30\brsp20 \brdrb\brdrs\brdrw30\brsp20 \tqr\tx9072{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\nooverflow\faroman\outlinelevel1\rin0\lin0\itap0 +\b\f1\fs24\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {ScummVM2 engines list +\par {\pntext\pard\plain\s26 \f30\fs20\lang2057\langfe1033\langnp2057\langfenp1033 \loch\af30\dbch\af0\hich\f30 \'69\tab}}\pard\plain \s26\ql \fi-283\li283\ri0\sa120\widctlpar\brdrb\brdrs\brdrw15\brsp20 {\*\pn \pnlvlblt\ilvl0\ls18\pnrnot0 +\pnf30\pnstart1\pnindent283\pnhang{\pntxtb i}}\nooverflow\faroman\ls18\rin0\lin283\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {Supported games +\par }\pard\plain \ql \li0\ri0\sa120\widctlpar\nooverflow\faroman\rin0\lin0\itap0 \f1\fs20\lang2057\langfe1033\cgrid\langnp2057\langfenp1033 {avalanche +\par cge +\par composer +\par draci +\par dreamweb +\par fullpipe +\par hopkins +\par hugo +\par lure +\par mohawk +\par \tab CSTIME +\par \tab MYST +\par \tab RIVEN +\par mortevielle +\par pegasus +\par sci +\par \tab SCI32 +\par sky +\par sword1 +\par sword2 +\par sword25(Not supported) +\par teenagent +\par testbed +\par tinsel +\par toltecs +\par tony +\par toon +\par tsage +\par zvision \par }}
\ No newline at end of file diff --git a/backends/platform/symbian/mmp/scummvm_agi.mmp.in b/backends/platform/symbian/mmp/scummvm_agi.mmp.in index a3eaa71065..d6f9e54b7d 100644 --- a/backends/platform/symbian/mmp/scummvm_agi.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_agi.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,5 +57,15 @@ SOURCEPATH ..\..\..\..\engines\agi USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_agos.mmp.in b/backends/platform/symbian/mmp/scummvm_agos.mmp.in index 92b8862794..d2b1329a24 100644 --- a/backends/platform/symbian/mmp/scummvm_agos.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_agos.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -63,5 +63,15 @@ SOURCEPATH ..\..\..\..\engines\agos USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_avalanche.mmp.in b/backends/platform/symbian/mmp/scummvm_avalanche.mmp.in index 1093181a4e..5260edc79d 100644 --- a/backends/platform/symbian/mmp/scummvm_avalanche.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_avalanche.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * Copyright (C) 2013 Strizniou Fedor * * ScummVM is the legal property of its developers, whose names @@ -58,5 +58,15 @@ SOURCEPATH ..\..\..\..\engines\avalanche USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_base.mmp.in b/backends/platform/symbian/mmp/scummvm_base.mmp.in index 358a2ec961..cc65980b71 100644 --- a/backends/platform/symbian/mmp/scummvm_base.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_base.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -34,7 +34,9 @@ TARGET scummvm_base.lib TARGETTYPE lib OPTION MSVC /QIfist /Ob1 /Oy /GF // /QIfist disables use of __ftol2 to avoid linker probs with MS libc: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/vcrefQIfistSuppress_ftol.asp OPTION GCC -Wno-multichar -Wno-reorder // don't optimize for ARM, platform way too sensitive for that :( just turn off some common warnings -OPTION GCCE -Wno-multichar -Wno-reorder -Wno-unused -Wno-format -fsigned-char +// using option -Wno-psabi to supress warning "note: the mangling of 'va_list' has changed in GCC 4.4" +// compiler will use png.h from libpng.lib instead ScummVM's +OPTION GCCE -Wno-multichar -Wno-reorder -Wno-unused -Wno-format -fsigned-char -Wno-psabi -I'/Symbian/S60_5th_Edition_SDK_v1.0/epoc32/include/png' ALWAYS_BUILD_AS_ARM // Note: the LIB:*.lib statements are used by AdaptAllMMPs.pl, so don't remove them! @@ -54,9 +56,12 @@ USERINCLUDE \epoc32\include\mpeg2dec //\epoc32\include\theora SYSTEMINCLUDE \epoc32\include\freetype SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora SYSTEMINCLUDE \epoc32\include\tremor SYSTEMINCLUDE \epoc32\include SYSTEMINCLUDE ..\src // for portdefs.h @@ -115,6 +120,7 @@ SOURCEPATH ..\..\..\..\video //STOP_AUTO_OBJECTS_VIDEO_// // add a few files manually, since they are not parsed from modules.mk files +SOURCE theora_decoder.cpp SOURCE bink_decoder.cpp SOURCE codecs\mpeg.cpp @@ -159,4 +165,5 @@ SOURCE backends\vkeybd\virtual-keyboard.cpp // Downscaler SOURCE graphics\scaler\downscaler.cpp +SOURCE graphics\scaler\downscalerARM.s MACRO SDL_BACKEND diff --git a/backends/platform/symbian/mmp/scummvm_cge.mmp.in b/backends/platform/symbian/mmp/scummvm_cge.mmp.in index 2d93671938..35cb0f2f98 100644 --- a/backends/platform/symbian/mmp/scummvm_cge.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_cge.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,5 +57,15 @@ SOURCEPATH ..\..\..\..\engines\cge USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_cine.mmp.in b/backends/platform/symbian/mmp/scummvm_cine.mmp.in index a308f92813..99b45cddb8 100644 --- a/backends/platform/symbian/mmp/scummvm_cine.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_cine.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,4 +57,15 @@ SOURCEPATH ..\..\..\..\engines\cine USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL +SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_composer.mmp.in b/backends/platform/symbian/mmp/scummvm_composer.mmp.in index cfe43b59a2..5a215f2d8d 100644 --- a/backends/platform/symbian/mmp/scummvm_composer.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_composer.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,5 +57,15 @@ SOURCEPATH ..\..\..\..\engines\COMPOSER USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_cruise.mmp.in b/backends/platform/symbian/mmp/scummvm_cruise.mmp.in index 58aed70f81..21a674dc1f 100644 --- a/backends/platform/symbian/mmp/scummvm_cruise.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_cruise.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,4 +57,15 @@ SOURCEPATH ..\..\..\..\engines\cruise USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL +SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_draci.mmp.in b/backends/platform/symbian/mmp/scummvm_draci.mmp.in index ba1759c00b..fe899a91ff 100644 --- a/backends/platform/symbian/mmp/scummvm_draci.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_draci.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,5 +57,15 @@ SOURCEPATH ..\..\..\..\engines\draci USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_drascula.mmp.in b/backends/platform/symbian/mmp/scummvm_drascula.mmp.in index c4419dd71e..8f532d4498 100644 --- a/backends/platform/symbian/mmp/scummvm_drascula.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_drascula.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,4 +57,15 @@ SOURCEPATH ..\..\..\..\engines\drascula USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL +SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_dreamweb.mmp.in b/backends/platform/symbian/mmp/scummvm_dreamweb.mmp.in index a5cc758ff6..89ffd23ebd 100644 --- a/backends/platform/symbian/mmp/scummvm_dreamweb.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_dreamweb.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * Copyright (C) 2013 Strizniou Fedor * * ScummVM is the legal property of its developers, whose names @@ -58,5 +58,15 @@ SOURCEPATH ..\..\..\..\engines\dreamweb USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_fullpipe.mmp.in b/backends/platform/symbian/mmp/scummvm_fullpipe.mmp.in index 59666b7b74..7612ad2bae 100644 --- a/backends/platform/symbian/mmp/scummvm_fullpipe.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_fullpipe.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * Copyright (C) 2013 Strizniou Fedor * * ScummVM is the legal property of its developers, whose names @@ -58,5 +58,15 @@ SOURCEPATH ..\..\..\..\engines\fullpipe USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_gob.mmp.in b/backends/platform/symbian/mmp/scummvm_gob.mmp.in index c2c36626ff..884b06c61a 100644 --- a/backends/platform/symbian/mmp/scummvm_gob.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_gob.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,4 +57,15 @@ SOURCEPATH ..\..\..\..\engines\gob USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL +SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_groovie.mmp.in b/backends/platform/symbian/mmp/scummvm_groovie.mmp.in index 639a794260..de6483bebf 100644 --- a/backends/platform/symbian/mmp/scummvm_groovie.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_groovie.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,5 +57,15 @@ SOURCEPATH ..\..\..\..\engines\groovie USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_hopkins.mmp.in b/backends/platform/symbian/mmp/scummvm_hopkins.mmp.in index cfe47d09ba..bafc11e65f 100644 --- a/backends/platform/symbian/mmp/scummvm_hopkins.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_hopkins.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,5 +57,15 @@ SOURCEPATH ..\..\..\..\engines\HOPKINS USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h
\ No newline at end of file diff --git a/backends/platform/symbian/mmp/scummvm_hugo.mmp.in b/backends/platform/symbian/mmp/scummvm_hugo.mmp.in index fceeb5e5d1..58622a83fd 100644 --- a/backends/platform/symbian/mmp/scummvm_hugo.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_hugo.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,5 +57,15 @@ SOURCEPATH ..\..\..\..\engines\hugo USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h
\ No newline at end of file diff --git a/backends/platform/symbian/mmp/scummvm_kyra.mmp.in b/backends/platform/symbian/mmp/scummvm_kyra.mmp.in index 2f8d22595e..3fa05e856d 100644 --- a/backends/platform/symbian/mmp/scummvm_kyra.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_kyra.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -70,4 +70,15 @@ SOURCEPATH ..\..\..\..\engines\kyra USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL +SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_lastexpress.mmp.in b/backends/platform/symbian/mmp/scummvm_lastexpress.mmp.in index fe2ebdfa1b..8e0b3026c7 100644 --- a/backends/platform/symbian/mmp/scummvm_lastexpress.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_lastexpress.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,5 +57,15 @@ SOURCEPATH ..\..\..\..\engines\lastexpress USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_lure.mmp.in b/backends/platform/symbian/mmp/scummvm_lure.mmp.in index f8b42bf337..89c93d058d 100644 --- a/backends/platform/symbian/mmp/scummvm_lure.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_lure.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,4 +57,15 @@ SOURCEPATH ..\..\..\..\engines\lure USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL +SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_m4.mmp.in b/backends/platform/symbian/mmp/scummvm_m4.mmp.in index 05395c1816..b3024c93c3 100644 --- a/backends/platform/symbian/mmp/scummvm_m4.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_m4.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,5 +57,15 @@ SOURCEPATH ..\..\..\..\engines\m4 USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_made.mmp.in b/backends/platform/symbian/mmp/scummvm_made.mmp.in index b0a0e7d34c..d4a63f8d87 100644 --- a/backends/platform/symbian/mmp/scummvm_made.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_made.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,5 +57,16 @@ SOURCEPATH ..\..\..\..\engines\made USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h + diff --git a/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in b/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in index 005b5f873e..e9175593ec 100644 --- a/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -76,5 +76,15 @@ SOURCEPATH ..\..\..\..\engines\mohawk USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_mortevielle.mmp.in b/backends/platform/symbian/mmp/scummvm_mortevielle.mmp.in index 90af4cb835..f118ddbef0 100644 --- a/backends/platform/symbian/mmp/scummvm_mortevielle.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_mortevielle.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * Copyright (C) 2013 Strizniou Fedor * * ScummVM is the legal property of its developers, whose names @@ -58,5 +58,15 @@ SOURCEPATH ..\..\..\..\engines\mortevielle USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_neverhood.mmp.in b/backends/platform/symbian/mmp/scummvm_neverhood.mmp.in index b65f0f6ab6..a57161577f 100644 --- a/backends/platform/symbian/mmp/scummvm_neverhood.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_neverhood.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,5 +57,15 @@ SOURCEPATH ..\..\..\..\engines\neverhood USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_parallaction.mmp.in b/backends/platform/symbian/mmp/scummvm_parallaction.mmp.in index 92d916224e..cefdd1b282 100644 --- a/backends/platform/symbian/mmp/scummvm_parallaction.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_parallaction.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,5 +57,15 @@ SOURCEPATH ..\..\..\..\engines\parallaction USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_pegasus.mmp.in b/backends/platform/symbian/mmp/scummvm_pegasus.mmp.in index 66863f2d74..68b2c12774 100644 --- a/backends/platform/symbian/mmp/scummvm_pegasus.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_pegasus.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,5 +57,15 @@ SOURCEPATH ..\..\..\..\engines\PEGASUS USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h
\ No newline at end of file diff --git a/backends/platform/symbian/mmp/scummvm_queen.mmp.in b/backends/platform/symbian/mmp/scummvm_queen.mmp.in index 3d8cfc1949..94835aae90 100644 --- a/backends/platform/symbian/mmp/scummvm_queen.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_queen.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,4 +57,15 @@ SOURCEPATH ..\..\..\..\engines\queen USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL +SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_saga.mmp.in b/backends/platform/symbian/mmp/scummvm_saga.mmp.in index 9ca633972b..77bf839efe 100644 --- a/backends/platform/symbian/mmp/scummvm_saga.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_saga.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -69,4 +69,15 @@ SOURCEPATH ..\..\..\..\engines\saga USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL +SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_sci.mmp.in b/backends/platform/symbian/mmp/scummvm_sci.mmp.in index 109b277667..d08501e471 100644 --- a/backends/platform/symbian/mmp/scummvm_sci.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_sci.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -65,5 +65,15 @@ SOURCEPATH ..\..\..\..\engines\sci USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_scumm.mmp.in b/backends/platform/symbian/mmp/scummvm_scumm.mmp.in index cc008766a8..a11dd071d3 100644 --- a/backends/platform/symbian/mmp/scummvm_scumm.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_scumm.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -81,7 +81,14 @@ SOURCE smush/codec47ARM.s // ARM version: add ASM routines USERINCLUDE ..\..\..\..\engines ..\..\..\..\engines\scumm\smush ..\..\..\..\engines\scumm\insane USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor SYSTEMINCLUDE \epoc32\include SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_sky.mmp.in b/backends/platform/symbian/mmp/scummvm_sky.mmp.in index 0ab35dffd7..37fdc89f99 100644 --- a/backends/platform/symbian/mmp/scummvm_sky.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_sky.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,4 +57,15 @@ SOURCEPATH ..\..\..\..\engines\sky USERINCLUDE ..\..\..\..\engines ..\..\..\..\engines\sky\music USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL +SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_sword1.mmp.in b/backends/platform/symbian/mmp/scummvm_sword1.mmp.in index 3b709fe1de..352cbe59f0 100644 --- a/backends/platform/symbian/mmp/scummvm_sword1.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_sword1.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,4 +57,15 @@ SOURCEPATH ..\..\..\..\engines\sword1 USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL +SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_sword2.mmp.in b/backends/platform/symbian/mmp/scummvm_sword2.mmp.in index ec5ccaefc9..7b79bf7f5c 100644 --- a/backends/platform/symbian/mmp/scummvm_sword2.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_sword2.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,4 +57,15 @@ SOURCEPATH ..\..\..\..\engines\sword2 USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL +SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_sword25.mmp.in b/backends/platform/symbian/mmp/scummvm_sword25.mmp.in index 62907f9245..4159350bce 100644 --- a/backends/platform/symbian/mmp/scummvm_sword25.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_sword25.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * Copyright (C) 2013 Strizniou Fedor * * ScummVM is the legal property of its developers, whose names @@ -59,5 +59,15 @@ SOURCEPATH ..\..\..\..\engines\sword25 USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src USERINCLUDE ..\..\..\..\engines\sword25\util\lua ..\..\..\..\engines\sword25\util\pluto + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_teenagent.mmp.in b/backends/platform/symbian/mmp/scummvm_teenagent.mmp.in index 73a86b9913..332b9f20ac 100644 --- a/backends/platform/symbian/mmp/scummvm_teenagent.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_teenagent.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,5 +57,15 @@ SOURCEPATH ..\..\..\..\engines\teenagent USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_testbed.mmp.in b/backends/platform/symbian/mmp/scummvm_testbed.mmp.in index 07d1df625d..20d3789a31 100644 --- a/backends/platform/symbian/mmp/scummvm_testbed.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_testbed.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * Copyright (C) 2013 Strizniou Fedor * * ScummVM is the legal property of its developers, whose names @@ -58,5 +58,15 @@ SOURCEPATH ..\..\..\..\engines\testbed USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in b/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in index 6436aaaa9b..15c5850cee 100644 --- a/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,4 +57,15 @@ SOURCEPATH ..\..\..\..\engines\tinsel USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL +SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h
\ No newline at end of file diff --git a/backends/platform/symbian/mmp/scummvm_toltecs.mmp.in b/backends/platform/symbian/mmp/scummvm_toltecs.mmp.in index 8685f80f71..df75290d81 100644 --- a/backends/platform/symbian/mmp/scummvm_toltecs.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_toltecs.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,5 +57,15 @@ SOURCEPATH ..\..\..\..\engines\TOLTECS USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_tony.mmp.in b/backends/platform/symbian/mmp/scummvm_tony.mmp.in index 01d4712cbb..bcdbc1c979 100644 --- a/backends/platform/symbian/mmp/scummvm_tony.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_tony.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,5 +57,15 @@ SOURCEPATH ..\..\..\..\engines\TONY USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_toon.mmp.in b/backends/platform/symbian/mmp/scummvm_toon.mmp.in index 2cddddd777..7bfec38dc5 100644 --- a/backends/platform/symbian/mmp/scummvm_toon.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_toon.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,5 +57,15 @@ SOURCEPATH ..\..\..\..\engines\toon USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_touche.mmp.in b/backends/platform/symbian/mmp/scummvm_touche.mmp.in index 24ca777c70..407e275ae3 100644 --- a/backends/platform/symbian/mmp/scummvm_touche.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_touche.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,5 +57,15 @@ SOURCEPATH ..\..\..\..\engines\touche USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_tsage.mmp.in b/backends/platform/symbian/mmp/scummvm_tsage.mmp.in index d017be593b..cd5c5ec7b9 100644 --- a/backends/platform/symbian/mmp/scummvm_tsage.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_tsage.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,5 +57,15 @@ SOURCEPATH ..\..\..\..\engines\tsage USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_tucker.mmp.in b/backends/platform/symbian/mmp/scummvm_tucker.mmp.in index f30bbfc469..c457dd4083 100644 --- a/backends/platform/symbian/mmp/scummvm_tucker.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_tucker.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,5 +57,15 @@ SOURCEPATH ..\..\..\..\engines\tucker USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_wintermute.mmp.in b/backends/platform/symbian/mmp/scummvm_wintermute.mmp.in index 5d26f36df5..a430f64847 100644 --- a/backends/platform/symbian/mmp/scummvm_wintermute.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_wintermute.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT @@ -57,5 +57,15 @@ SOURCEPATH ..\..\..\..\engines\wintermute USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src + +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h diff --git a/backends/platform/symbian/mmp/scummvm_zvision.mmp.in b/backends/platform/symbian/mmp/scummvm_zvision.mmp.in index a007f45f5b..f8448e0423 100644 --- a/backends/platform/symbian/mmp/scummvm_zvision.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_zvision.mmp.in @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-2014 The ScummVM Team + * Copyright (C) 2005-2013 The ScummVM project * Copyright (C) 2013 Strizniou Fedor * * ScummVM is the legal property of its developers, whose names @@ -58,5 +58,14 @@ SOURCEPATH ..\..\..\..\engines\zvision USERINCLUDE ..\..\..\..\engines USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec +SYSTEMINCLUDE \epoc32\include\jpeg +SYSTEMINCLUDE \epoc32\include\png +SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version -SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src +SYSTEMINCLUDE \epoc32\include\libc +SYSTEMINCLUDE \epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\tremor +SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE ..\src // for portdefs.h @@ -1843,6 +1843,15 @@ if test "$_global_constructors" = yes; then fi echo $_global_constructors +echo_n "Checking for $_host_alias-strings... " >> "$TMPLOG" +if test ! "x$(which $_host_alias-strings 2>/dev/null)" = "x"; then +_strings=$_host_alias-strings +echo yes >> "$TMPLOG" +else +_strings=strings +echo no >> "$TMPLOG" +fi + # # Check for endianness # @@ -1857,9 +1866,9 @@ void _ebcdic() { char* s = (char*) ebcdic_mm; s = (char*) ebcdic_ii; } int main() { _ascii (); _ebcdic (); return 0; } EOF $CXX $CXXFLAGS -c -o $TMPO.o tmp_endianness_check.cpp -if strings $TMPO.o | grep BIGenDianSyS >/dev/null; then +if $_strings $TMPO.o | grep BIGenDianSyS >/dev/null; then _endian=big -elif strings $TMPO.o | grep LiTTleEnDian >/dev/null; then +elif $_strings $TMPO.o | grep LiTTleEnDian >/dev/null; then _endian=little fi echo $_endian; @@ -2194,6 +2203,49 @@ case $_host_os in echo "Set staticlib-prefix to ${_staticlibpath}" fi fi + + # Fink + # There is no way to get the prefix, so implementing a hack here + fink_version=`fink -V 2>/dev/null` + if test "$?" -eq 0; then + fink_version="`echo "${fink_version}" | sed -ne 's/Package manager version: \([0-9.]*\)/\1/gp'`" + echo_n "You seem to be running Fink version ${fink_version}..." + + fink_prefix=`which fink` + # strip off /bin/fink from /sw/bin/port + fink_prefix=`dirname ${fink_prefix}` + fink_prefix=`dirname ${fink_prefix}` + + echo "adding ${fink_prefix} to paths" + + LDFLAGS="-L${fink_prefix}/lib $LDFLAGS" + CXXFLAGS="-I${fink_prefix}/include $CXXFLAGS" + + if test -z "$_staticlibpath"; then + _staticlibpath=${fink_prefix} + echo "Set staticlib-prefix to ${_staticlibpath}" + fi + fi + + # Homebrew + brew_version=`brew -v 2>/dev/null` + if test "$?" -eq 0; then + brew_version="`echo "${brew_version}" | sed -ne 's/Homebrew \([0-9.]*\)/\1/gp'`" + echo_n "You seem to be running Homebrew version ${brew_version}..." + + brew_prefix=`brew --prefix` + + echo "adding ${brew_prefix} to paths" + + LDFLAGS="-L${brew_prefix}/lib $LDFLAGS" + CXXFLAGS="-I${brew_prefix}/include $CXXFLAGS" + + if test -z "$_staticlibpath"; then + _staticlibpath=${brew_prefix} + echo "Set staticlib-prefix to ${_staticlibpath}" + fi + fi + # If _staticlibpath is not set yet try first /sw (fink) then /usr/local # (the macports case is handled above). if test -z "$_staticlibpath"; then @@ -2710,7 +2762,10 @@ if test -n "$_host"; then # This trick doesn't work for tremor right now, as the PS2 port the resulting library # libtremor, while our code later on expects it to be called libvorbisidec. # TODO: Enable tremor, e.g. by adding -ltremor or by renaming the lib. - _tremor=yes + # Disable this for older SDK as this breaks the build otherwise... + if test -z "$PS2SDK_OLD"; then + _tremor=yes + fi _mad=yes _zlib=yes # HACK to fix compilation of C source files for now. diff --git a/devtools/credits.pl b/devtools/credits.pl index 53f0d11307..5f2f6c12f9 100755 --- a/devtools/credits.pl +++ b/devtools/credits.pl @@ -645,6 +645,12 @@ begin_credits("Credits"); add_person("Filippos Karapetis", "[md5]", ""); end_section(); + begin_section("MADS"); + add_person("Arnaud Boutonné", "Strangerke", ""); + add_person("Paul Gilbert", "dreammaster", ""); + add_person("Filippos Karapetis", "[md5]", ""); + end_section(); + begin_section("Mohawk"); add_person("Bastien Bouclet", "bgk", ""); add_person("Matthew Hoops", "clone2727", ""); @@ -767,6 +773,11 @@ begin_credits("Credits"); add_person("Gregory Montoir", "cyx", "(retired)"); end_section(); + begin_section("Voyeur"); + add_person("Arnaud Boutonné", "Strangerke", ""); + add_person("Paul Gilbert", "dreammaster", ""); + end_section(); + begin_section("Wintermute"); add_person("Einar Johan T. Sømåen", "somaen", ""); end_section(); diff --git a/engines/agi/console.cpp b/engines/agi/console.cpp index 5f222adf89..6d7f9384cd 100644 --- a/engines/agi/console.cpp +++ b/engines/agi/console.cpp @@ -32,27 +32,27 @@ namespace Agi { Console::Console(AgiEngine *vm) : GUI::Debugger() { _vm = vm; - DCmd_Register("debug", WRAP_METHOD(Console, Cmd_Debug)); - DCmd_Register("cont", WRAP_METHOD(Console, Cmd_Cont)); - DCmd_Register("agiver", WRAP_METHOD(Console, Cmd_Agiver)); - DCmd_Register("flags", WRAP_METHOD(Console, Cmd_Flags)); - DCmd_Register("logic0", WRAP_METHOD(Console, Cmd_Logic0)); - DCmd_Register("objs", WRAP_METHOD(Console, Cmd_Objs)); - DCmd_Register("runopcode", WRAP_METHOD(Console, Cmd_RunOpcode)); - DCmd_Register("opcode", WRAP_METHOD(Console, Cmd_Opcode)); - DCmd_Register("step", WRAP_METHOD(Console, Cmd_Step)); - DCmd_Register("trigger", WRAP_METHOD(Console, Cmd_Trigger)); - DCmd_Register("vars", WRAP_METHOD(Console, Cmd_Vars)); - DCmd_Register("setvar", WRAP_METHOD(Console, Cmd_SetVar)); - DCmd_Register("setflag", WRAP_METHOD(Console, Cmd_SetFlag)); - DCmd_Register("setobj", WRAP_METHOD(Console, Cmd_SetObj)); - DCmd_Register("room", WRAP_METHOD(Console, Cmd_Room)); - DCmd_Register("bt", WRAP_METHOD(Console, Cmd_BT)); + registerCmd("debug", WRAP_METHOD(Console, Cmd_Debug)); + registerCmd("cont", WRAP_METHOD(Console, Cmd_Cont)); + registerCmd("agiver", WRAP_METHOD(Console, Cmd_Agiver)); + registerCmd("flags", WRAP_METHOD(Console, Cmd_Flags)); + registerCmd("logic0", WRAP_METHOD(Console, Cmd_Logic0)); + registerCmd("objs", WRAP_METHOD(Console, Cmd_Objs)); + registerCmd("runopcode", WRAP_METHOD(Console, Cmd_RunOpcode)); + registerCmd("opcode", WRAP_METHOD(Console, Cmd_Opcode)); + registerCmd("step", WRAP_METHOD(Console, Cmd_Step)); + registerCmd("trigger", WRAP_METHOD(Console, Cmd_Trigger)); + registerCmd("vars", WRAP_METHOD(Console, Cmd_Vars)); + registerCmd("setvar", WRAP_METHOD(Console, Cmd_SetVar)); + registerCmd("setflag", WRAP_METHOD(Console, Cmd_SetFlag)); + registerCmd("setobj", WRAP_METHOD(Console, Cmd_SetObj)); + registerCmd("room", WRAP_METHOD(Console, Cmd_Room)); + registerCmd("bt", WRAP_METHOD(Console, Cmd_BT)); } bool Console::Cmd_SetVar(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Usage: setvar <varnum> <value>\n"); + debugPrintf("Usage: setvar <varnum> <value>\n"); return true; } int p1 = (int)atoi(argv[1]); @@ -64,7 +64,7 @@ bool Console::Cmd_SetVar(int argc, const char **argv) { bool Console::Cmd_SetFlag(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Usage: setvar <varnum> <value>\n"); + debugPrintf("Usage: setvar <varnum> <value>\n"); return true; } int p1 = (int)atoi(argv[1]); @@ -76,7 +76,7 @@ bool Console::Cmd_SetFlag(int argc, const char **argv) { bool Console::Cmd_SetObj(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Usage: setvar <varnum> <value>\n"); + debugPrintf("Usage: setvar <varnum> <value>\n"); return true; } int p1 = (int)atoi(argv[1]); @@ -88,7 +88,7 @@ bool Console::Cmd_SetObj(int argc, const char **argv) { bool Console::Cmd_RunOpcode(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: runopcode <name> <parameter0> ....\n"); + debugPrintf("Usage: runopcode <name> <parameter0> ....\n"); return true; } @@ -96,7 +96,7 @@ bool Console::Cmd_RunOpcode(int argc, const char **argv) { if (!strcmp(argv[1], logicNamesCmd[i].name)) { uint8 p[16]; if ((argc - 2) != logicNamesCmd[i].argumentsLength()) { - DebugPrintf("AGI command wants %d arguments\n", logicNamesCmd[i].argumentsLength()); + debugPrintf("AGI command wants %d arguments\n", logicNamesCmd[i].argumentsLength()); return 0; } p[0] = argv[2] ? (char)strtoul(argv[2], NULL, 0) : 0; @@ -113,7 +113,7 @@ bool Console::Cmd_RunOpcode(int argc, const char **argv) { } } - DebugPrintf("Unknown opcode\n"); + debugPrintf("Unknown opcode\n"); return true; } @@ -125,7 +125,7 @@ bool Console::Cmd_Agiver(int argc, const char **argv) { maj = (ver >> 12) & 0xf; min = ver & 0xfff; - DebugPrintf(maj <= 2 ? "%x.%03x\n" : "%x.002.%03x\n", maj, min); + debugPrintf(maj <= 2 ? "%x.%03x\n" : "%x.002.%03x\n", maj, min); return true; } @@ -133,17 +133,17 @@ bool Console::Cmd_Agiver(int argc, const char **argv) { bool Console::Cmd_Flags(int argc, const char **argv) { int i, j; - DebugPrintf(" "); + debugPrintf(" "); for (j = 0; j < 10; j++) - DebugPrintf("%d ", j); - DebugPrintf("\n"); + debugPrintf("%d ", j); + debugPrintf("\n"); for (i = 0; i < 255;) { - DebugPrintf("%3d ", i); + debugPrintf("%3d ", i); for (j = 0; j < 10; j++, i++) { - DebugPrintf("%c ", _vm->getflag(i) ? 'T' : 'F'); + debugPrintf("%c ", _vm->getflag(i) ? 'T' : 'F'); } - DebugPrintf("\n"); + debugPrintf("\n"); } return true; @@ -154,9 +154,9 @@ bool Console::Cmd_Vars(int argc, const char **argv) { for (i = 0; i < 255;) { for (j = 0; j < 5; j++, i++) { - DebugPrintf("%03d:%3d ", i, _vm->getvar(i)); + debugPrintf("%03d:%3d ", i, _vm->getvar(i)); } - DebugPrintf("\n"); + debugPrintf("\n"); } return true; @@ -166,7 +166,7 @@ bool Console::Cmd_Objs(int argc, const char **argv) { unsigned int i; for (i = 0; i < _vm->_game.numObjects; i++) { - DebugPrintf("%3d]%-24s(%3d)\n", i, _vm->objectName(i), _vm->objectGetLocation(i)); + debugPrintf("%3d]%-24s(%3d)\n", i, _vm->objectName(i), _vm->objectGetLocation(i)); } return true; @@ -174,7 +174,7 @@ bool Console::Cmd_Objs(int argc, const char **argv) { bool Console::Cmd_Opcode(int argc, const char **argv) { if (argc != 2 || (strcmp(argv[1], "on") && strcmp(argv[1], "off"))) { - DebugPrintf("Usage: opcode on|off\n"); + debugPrintf("Usage: opcode on|off\n"); return true; } @@ -185,7 +185,7 @@ bool Console::Cmd_Opcode(int argc, const char **argv) { bool Console::Cmd_Logic0(int argc, const char **argv) { if (argc != 2 || (strcmp(argv[1], "on") && strcmp(argv[1], "off"))) { - DebugPrintf("Usage: logic0 on|off\n"); + debugPrintf("Usage: logic0 on|off\n"); return true; } @@ -196,7 +196,7 @@ bool Console::Cmd_Logic0(int argc, const char **argv) { bool Console::Cmd_Trigger(int argc, const char **argv) { if (argc != 2 || (strcmp(argv[1], "on") && strcmp(argv[1], "off"))) { - DebugPrintf("Usage: trigger on|off\n"); + debugPrintf("Usage: trigger on|off\n"); return true; } _vm->_debug.ignoretriggers = strcmp (argv[1], "on"); @@ -236,13 +236,13 @@ bool Console::Cmd_Room(int argc, const char **argv) { _vm->newRoom(strtoul(argv[1], NULL, 0)); } - DebugPrintf("Current room: %d\n", _vm->getvar(0)); + debugPrintf("Current room: %d\n", _vm->getvar(0)); return true; } bool Console::Cmd_BT(int argc, const char **argv) { - DebugPrintf("Current script: %d\nStack depth: %d\n", _vm->_game.lognum, _vm->_game.execStack.size()); + debugPrintf("Current script: %d\nStack depth: %d\n", _vm->_game.lognum, _vm->_game.execStack.size()); uint8 *code = NULL; uint8 op = 0; @@ -257,12 +257,12 @@ bool Console::Cmd_BT(int argc, const char **argv) { memmove(p, &code[it->curIP], num); memset(p + num, 0, CMD_BSIZE - num); - DebugPrintf("%d(%d): %s(", it->script, it->curIP, logicNamesCmd[op].name); + debugPrintf("%d(%d): %s(", it->script, it->curIP, logicNamesCmd[op].name); for (int i = 0; i < num; i++) - DebugPrintf("%d, ", p[i]); + debugPrintf("%d, ", p[i]); - DebugPrintf(")\n"); + debugPrintf(")\n"); } return true; @@ -271,9 +271,9 @@ bool Console::Cmd_BT(int argc, const char **argv) { MickeyConsole::MickeyConsole(MickeyEngine *mickey) : GUI::Debugger() { _mickey = mickey; - DCmd_Register("room", WRAP_METHOD(MickeyConsole, Cmd_Room)); - DCmd_Register("drawPic", WRAP_METHOD(MickeyConsole, Cmd_DrawPic)); - DCmd_Register("drawObj", WRAP_METHOD(MickeyConsole, Cmd_DrawObj)); + registerCmd("room", WRAP_METHOD(MickeyConsole, Cmd_Room)); + registerCmd("drawPic", WRAP_METHOD(MickeyConsole, Cmd_DrawPic)); + registerCmd("drawObj", WRAP_METHOD(MickeyConsole, Cmd_DrawObj)); } bool MickeyConsole::Cmd_Room(int argc, const char **argv) { @@ -287,7 +287,7 @@ bool MickeyConsole::Cmd_Room(int argc, const char **argv) { bool MickeyConsole::Cmd_DrawPic(int argc, const char **argv) { if (argc != 2) - DebugPrintf("Usage: %s <Picture number>\n", argv[0]); + debugPrintf("Usage: %s <Picture number>\n", argv[0]); else _mickey->drawPic(atoi(argv[1])); return true; @@ -295,7 +295,7 @@ bool MickeyConsole::Cmd_DrawPic(int argc, const char **argv) { bool MickeyConsole::Cmd_DrawObj(int argc, const char **argv) { if (argc != 2) - DebugPrintf("Usage: %s <Object number>\n", argv[0]); + debugPrintf("Usage: %s <Object number>\n", argv[0]); else _mickey->drawObj((ENUM_MSA_OBJECT)atoi(argv[1]), 0, 0); return true; @@ -304,7 +304,7 @@ bool MickeyConsole::Cmd_DrawObj(int argc, const char **argv) { WinnieConsole::WinnieConsole(WinnieEngine *winnie) : GUI::Debugger() { _winnie = winnie; - DCmd_Register("curRoom", WRAP_METHOD(WinnieConsole, Cmd_CurRoom)); + registerCmd("curRoom", WRAP_METHOD(WinnieConsole, Cmd_CurRoom)); } bool WinnieConsole::Cmd_CurRoom(int argc, const char **argv) { diff --git a/engines/agi/preagi_mickey.cpp b/engines/agi/preagi_mickey.cpp index 561b56d199..4ca8d00824 100644 --- a/engines/agi/preagi_mickey.cpp +++ b/engines/agi/preagi_mickey.cpp @@ -2228,10 +2228,10 @@ void MickeyEngine::waitAnyKey(bool anim) { // Console-related functions void MickeyEngine::debugCurRoom() { - _console->DebugPrintf("Current Room = %d\n", _gameStateMickey.iRoom); + _console->debugPrintf("Current Room = %d\n", _gameStateMickey.iRoom); if (_gameStateMickey.iRmObj[_gameStateMickey.iRoom] != IDI_MSA_OBJECT_NONE) { - _console->DebugPrintf("Object %d is in the room\n", _gameStateMickey.iRmObj[_gameStateMickey.iRoom]); + _console->debugPrintf("Object %d is in the room\n", _gameStateMickey.iRmObj[_gameStateMickey.iRoom]); } } diff --git a/engines/agi/preagi_winnie.cpp b/engines/agi/preagi_winnie.cpp index d5ae0b59a0..a91ad24fc6 100644 --- a/engines/agi/preagi_winnie.cpp +++ b/engines/agi/preagi_winnie.cpp @@ -1308,7 +1308,7 @@ void WinnieEngine::printStrWinnie(char *szMsg) { // Console-related functions void WinnieEngine::debugCurRoom() { - _console->DebugPrintf("Current Room = %d\n", _room); + _console->debugPrintf("Current Room = %d\n", _room); } WinnieEngine::WinnieEngine(OSystem *syst, const AGIGameDescription *gameDesc) : PreAgiEngine(syst, gameDesc) { diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp index 7266c75474..6eda2eb9aa 100644 --- a/engines/agos/agos.cpp +++ b/engines/agos/agos.cpp @@ -21,6 +21,7 @@ */ #include "common/config-manager.h" +#include "common/debug-channels.h" #include "common/file.h" #include "common/fs.h" #include "common/textconsole.h" @@ -144,6 +145,14 @@ AGOSEngine_Elvira1::AGOSEngine_Elvira1(OSystem *system, const AGOSGameDescriptio AGOSEngine::AGOSEngine(OSystem *system, const AGOSGameDescription *gd) : Engine(system), _rnd("agos"), _gameDescription(gd) { + DebugMan.addDebugChannel(kDebugOpcode, "opcode", "Opcode debug level"); + DebugMan.addDebugChannel(kDebugVGAOpcode, "vga_opcode", "VGA Opcode debug level"); + DebugMan.addDebugChannel(kDebugSubroutine, "subroutine", "Subroutine debug level"); + DebugMan.addDebugChannel(kDebugVGAScript, "vga_script", "VGA Script debug level"); + //Image dumping command disabled as it doesn't work well +#if 0 + DebugMan.addDebugChannel(kDebugImageDump, "image_dump", "Enable dumping of images to files"); +#endif _vcPtr = 0; _vcGetOutOfCode = 0; _gameOffsetsPtr = 0; @@ -243,13 +252,6 @@ AGOSEngine::AGOSEngine(OSystem *system, const AGOSGameDescription *gd) _backFlag = false; - _debugMode = 0; - _dumpScripts = false; - _dumpOpcodes = false; - _dumpVgaScripts = false; - _dumpVgaOpcodes = false; - _dumpImages = false; - _copyProtection = false; _pause = false; _speech = false; @@ -675,15 +677,6 @@ Common::Error AGOSEngine::init() { _subtitles = true; } - // TODO: Use special debug levels instead of the following hack. - _debugMode = (gDebugLevel >= 0); - switch (gDebugLevel) { - case 2: _dumpOpcodes = true; break; - case 3: _dumpVgaOpcodes = true; break; - case 4: _dumpScripts = true; break; - case 5: _dumpVgaScripts = true; break; - } - return Common::kNoError; } diff --git a/engines/agos/agos.h b/engines/agos/agos.h index 5e49fce5ff..b6b5e427e1 100644 --- a/engines/agos/agos.h +++ b/engines/agos/agos.h @@ -61,6 +61,14 @@ struct Surface; namespace AGOS { +enum { + kDebugOpcode = 1 << 0, + kDebugVGAOpcode = 1 << 1, + kDebugSubroutine = 1 << 2, + kDebugVGAScript = 1 << 3, + kDebugImageDump = 1 << 4 +}; + uint fileReadItemID(Common::SeekableReadStream *in); #define CHECK_BOUNDS(x, y) assert((uint)(x) < ARRAYSIZE(y)) @@ -324,15 +332,9 @@ protected: bool _fastMode; bool _backFlag; - uint16 _debugMode; Common::Language _language; bool _copyProtection; bool _pause; - bool _dumpScripts; - bool _dumpOpcodes; - bool _dumpVgaScripts; - bool _dumpVgaOpcodes; - bool _dumpImages; bool _speech; bool _subtitles; bool _vgaVar9; diff --git a/engines/agos/debugger.cpp b/engines/agos/debugger.cpp index 512137b685..7ad742c928 100644 --- a/engines/agos/debugger.cpp +++ b/engines/agos/debugger.cpp @@ -32,44 +32,21 @@ Debugger::Debugger(AGOSEngine *vm) : GUI::Debugger() { _vm = vm; - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("level", WRAP_METHOD(Debugger, Cmd_DebugLevel)); - DCmd_Register("music", WRAP_METHOD(Debugger, Cmd_PlayMusic)); - DCmd_Register("sound", WRAP_METHOD(Debugger, Cmd_PlaySound)); - DCmd_Register("voice", WRAP_METHOD(Debugger, Cmd_PlayVoice)); - DCmd_Register("bit", WRAP_METHOD(Debugger, Cmd_SetBit)); - DCmd_Register("bit2", WRAP_METHOD(Debugger, Cmd_SetBit2)); - DCmd_Register("bit3", WRAP_METHOD(Debugger, Cmd_SetBit3)); - DCmd_Register("var", WRAP_METHOD(Debugger, Cmd_SetVar)); - DCmd_Register("obj", WRAP_METHOD(Debugger, Cmd_SetObjectFlag)); - DCmd_Register("sub", WRAP_METHOD(Debugger, Cmd_StartSubroutine)); - DCmd_Register("dumpimage", WRAP_METHOD(Debugger, Cmd_dumpImage)); - DCmd_Register("dumpscript", WRAP_METHOD(Debugger, Cmd_dumpScript)); + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("music", WRAP_METHOD(Debugger, Cmd_PlayMusic)); + registerCmd("sound", WRAP_METHOD(Debugger, Cmd_PlaySound)); + registerCmd("voice", WRAP_METHOD(Debugger, Cmd_PlayVoice)); + registerCmd("bit", WRAP_METHOD(Debugger, Cmd_SetBit)); + registerCmd("bit2", WRAP_METHOD(Debugger, Cmd_SetBit2)); + registerCmd("bit3", WRAP_METHOD(Debugger, Cmd_SetBit3)); + registerCmd("var", WRAP_METHOD(Debugger, Cmd_SetVar)); + registerCmd("obj", WRAP_METHOD(Debugger, Cmd_SetObjectFlag)); + registerCmd("sub", WRAP_METHOD(Debugger, Cmd_StartSubroutine)); + registerCmd("dumpimage", WRAP_METHOD(Debugger, Cmd_dumpImage)); + registerCmd("dumpscript", WRAP_METHOD(Debugger, Cmd_dumpScript)); } - -bool Debugger::Cmd_DebugLevel(int argc, const char **argv) { - if (argc == 1) { - if (_vm->_debugMode == false) - DebugPrintf("Debugging is not enabled at this time\n"); - else - DebugPrintf("Debugging is currently set at level %d\n", gDebugLevel); - } else { // set level - gDebugLevel = atoi(argv[1]); - if (0 <= gDebugLevel && gDebugLevel < 11) { - _vm->_debugMode = true; - DebugPrintf("Debug level set to level %d\n", gDebugLevel); - } else if (gDebugLevel < 0) { - _vm->_debugMode = false; - DebugPrintf("Debugging is now disabled\n"); - } else - DebugPrintf("Not a valid debug level (0 - 10)\n"); - } - - return true; -} - bool Debugger::Cmd_PlayMusic(int argc, const char **argv) { if (argc > 1) { uint music = atoi(argv[1]); @@ -83,9 +60,9 @@ bool Debugger::Cmd_PlayMusic(int argc, const char **argv) { _vm->playMusic(music, 0); } } else - DebugPrintf("Music out of range (0 - %d)\n", _vm->_numMusic); + debugPrintf("Music out of range (0 - %d)\n", _vm->_numMusic); } else - DebugPrintf("Syntax: music <musicnum>\n"); + debugPrintf("Syntax: music <musicnum>\n"); return true; } @@ -96,9 +73,9 @@ bool Debugger::Cmd_PlaySound(int argc, const char **argv) { if (sound <= _vm->_numSFX) _vm->_sound->playEffects(sound); else - DebugPrintf("Sound out of range (0 - %d)\n", _vm->_numSFX); + debugPrintf("Sound out of range (0 - %d)\n", _vm->_numSFX); } else - DebugPrintf("Syntax: sound <soundnum>\n"); + debugPrintf("Syntax: sound <soundnum>\n"); return true; } @@ -109,9 +86,9 @@ bool Debugger::Cmd_PlayVoice(int argc, const char **argv) { if (voice <= _vm->_numSpeech) _vm->_sound->playVoice(voice); else - DebugPrintf("Voice out of range (0 - %d)\n", _vm->_numSpeech); + debugPrintf("Voice out of range (0 - %d)\n", _vm->_numSpeech); } else - DebugPrintf("Syntax: voice <voicenum>\n"); + debugPrintf("Syntax: voice <voicenum>\n"); return true; } @@ -123,15 +100,15 @@ bool Debugger::Cmd_SetBit(int argc, const char **argv) { value = atoi(argv[2]); if (value <= 1) { _vm->setBitFlag(bit, value != 0); - DebugPrintf("Set bit %d to %d\n", bit, value); + debugPrintf("Set bit %d to %d\n", bit, value); } else - DebugPrintf("Bit value out of range (0 - 1)\n"); + debugPrintf("Bit value out of range (0 - 1)\n"); } else if (argc > 1) { bit = atoi(argv[1]); value = _vm->getBitFlag(bit); - DebugPrintf("Bit %d is %d\n", bit, value); + debugPrintf("Bit %d is %d\n", bit, value); } else - DebugPrintf("Syntax: bit <bitnum> <value>\n"); + debugPrintf("Syntax: bit <bitnum> <value>\n"); return true; } @@ -143,18 +120,18 @@ bool Debugger::Cmd_SetBit2(int argc, const char **argv) { value = atoi(argv[2]); if (value == 0) { _vm->_bitArrayTwo[bit / 16] &= ~(1 << (bit & 15)); - DebugPrintf("Set bit2 %d to %d\n", bit, value); + debugPrintf("Set bit2 %d to %d\n", bit, value); } else if (value == 1) { _vm->_bitArrayTwo[bit / 16] |= (1 << (bit & 15)); - DebugPrintf("Set bit2 %d to %d\n", bit, value); + debugPrintf("Set bit2 %d to %d\n", bit, value); } else - DebugPrintf("Bit2 value out of range (0 - 1)\n"); + debugPrintf("Bit2 value out of range (0 - 1)\n"); } else if (argc > 1) { bit = atoi(argv[1]); value = (_vm->_bitArrayTwo[bit / 16] & (1 << (bit & 15))) != 0; - DebugPrintf("Bit2 %d is %d\n", bit, value); + debugPrintf("Bit2 %d is %d\n", bit, value); } else - DebugPrintf("Syntax: bit2 <bitnum> <value>\n"); + debugPrintf("Syntax: bit2 <bitnum> <value>\n"); return true; } @@ -166,18 +143,18 @@ bool Debugger::Cmd_SetBit3(int argc, const char **argv) { value = atoi(argv[2]); if (value == 0) { _vm->_bitArrayThree[bit / 16] &= ~(1 << (bit & 15)); - DebugPrintf("Set bit3 %d to %d\n", bit, value); + debugPrintf("Set bit3 %d to %d\n", bit, value); } else if (value == 1) { _vm->_bitArrayThree[bit / 16] |= (1 << (bit & 15)); - DebugPrintf("Set bit3 %d to %d\n", bit, value); + debugPrintf("Set bit3 %d to %d\n", bit, value); } else - DebugPrintf("Bit3 value out of range (0 - 1)\n"); + debugPrintf("Bit3 value out of range (0 - 1)\n"); } else if (argc > 1) { bit = atoi(argv[1]); value = (_vm->_bitArrayThree[bit / 16] & (1 << (bit & 15))) != 0; - DebugPrintf("Bit3 %d is %d\n", bit, value); + debugPrintf("Bit3 %d is %d\n", bit, value); } else - DebugPrintf("Syntax: bit3 <bitnum> <value>\n"); + debugPrintf("Syntax: bit3 <bitnum> <value>\n"); return true; } @@ -190,15 +167,15 @@ bool Debugger::Cmd_SetVar(int argc, const char **argv) { if (argc > 2) { value = atoi(argv[2]); _vm->writeVariable(var, value); - DebugPrintf("Set var %d to %d\n", var, value); + debugPrintf("Set var %d to %d\n", var, value); } else { value = _vm->readVariable(var); - DebugPrintf("Var %d is %d\n", var, value); + debugPrintf("Var %d is %d\n", var, value); } } else - DebugPrintf("Var out of range (0 - %d)\n", _vm->_numVars - 1); + debugPrintf("Var out of range (0 - %d)\n", _vm->_numVars - 1); } else - DebugPrintf("Syntax: var <varnum> <value>\n"); + debugPrintf("Syntax: var <varnum> <value>\n"); return true; } @@ -217,22 +194,22 @@ bool Debugger::Cmd_SetObjectFlag(int argc, const char **argv) { if (argc > 3) { value = atoi(argv[3]); o->objectFlagValue[offs] = value; - DebugPrintf("Object %d Flag %d set to %d\n", obj, prop, value); + debugPrintf("Object %d Flag %d set to %d\n", obj, prop, value); } else { value = o->objectFlagValue[offs]; - DebugPrintf("Object %d Flag %d is %d\n", obj, prop, value); + debugPrintf("Object %d Flag %d is %d\n", obj, prop, value); } } else { - DebugPrintf("Object flag out of range\n"); + debugPrintf("Object flag out of range\n"); } } else { - DebugPrintf("Item isn't an object\n"); + debugPrintf("Item isn't an object\n"); } } else { - DebugPrintf("Item out of range (1 - %d)\n", _vm->_itemArraySize - 1); + debugPrintf("Item out of range (1 - %d)\n", _vm->_itemArraySize - 1); } } else { - DebugPrintf("Syntax: obj <itemnum> <flag> <value>\n"); + debugPrintf("Syntax: obj <itemnum> <flag> <value>\n"); } return true; @@ -246,7 +223,7 @@ bool Debugger::Cmd_StartSubroutine(int argc, const char **argv) { if (sub != NULL) _vm->startSubroutine(sub); } else - DebugPrintf("Subroutine %d\n", _vm->_currentTable->id); + debugPrintf("Subroutine %d\n", _vm->_currentTable->id); return true; } @@ -259,11 +236,11 @@ bool Debugger::Cmd_dumpImage(int argc, const char **argv) { if (vpe->vgaFile2 != NULL) { _vm->dumpVgaBitmaps(zoneNum); } else { - DebugPrintf("Invalid Zone Number %d\n", zoneNum); + debugPrintf("Invalid Zone Number %d\n", zoneNum); } } else - DebugPrintf("Syntax: dumpimage <zonenum>\n"); + debugPrintf("Syntax: dumpimage <zonenum>\n"); return true; } @@ -276,11 +253,11 @@ bool Debugger::Cmd_dumpScript(int argc, const char **argv) { if (vpe->vgaFile1 != NULL) { _vm->dumpVgaFile(vpe->vgaFile1); } else { - DebugPrintf("Invalid Zone Number %d\n", zoneNum); + debugPrintf("Invalid Zone Number %d\n", zoneNum); } } else - DebugPrintf("Syntax: dumpscript <zonenum>\n"); + debugPrintf("Syntax: dumpscript <zonenum>\n"); return true; } diff --git a/engines/agos/debugger.h b/engines/agos/debugger.h index caac6e2caf..026194410f 100644 --- a/engines/agos/debugger.h +++ b/engines/agos/debugger.h @@ -37,7 +37,6 @@ public: private: AGOSEngine *_vm; - bool Cmd_DebugLevel(int argc, const char **argv); bool Cmd_PlayMusic(int argc, const char **argv); bool Cmd_PlaySound(int argc, const char **argv); bool Cmd_PlayVoice(int argc, const char **argv); diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp index 6e97084811..33145b7d0d 100644 --- a/engines/agos/gfx.cpp +++ b/engines/agos/gfx.cpp @@ -20,6 +20,7 @@ * */ +#include "common/debug-channels.h" #include "common/endian.h" #include "common/system.h" #include "common/textconsole.h" @@ -1129,7 +1130,7 @@ void AGOSEngine::animate(uint16 windowNum, uint16 zoneNum, uint16 vgaSpriteId, i assert(READ_BE_UINT16(&((AnimationHeader_WW *) p)->id) == vgaSpriteId); } - if (_dumpVgaScripts) { + if (DebugMan.isDebugChannelEnabled(kDebugVGAScript)) { if (getGameType() == GType_FF || getGameType() == GType_PP) { dumpVgaScript(_curVgaFile1 + READ_LE_UINT16(&((AnimationHeader_Feeble*)p)->scriptOffs), zoneNum, vgaSpriteId); } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { @@ -1235,7 +1236,7 @@ void AGOSEngine::setImage(uint16 vgaSpriteId, bool vgaScript) { } } - if (_dumpVgaScripts) { + if (DebugMan.isDebugChannelEnabled(kDebugVGAScript)) { if (getGameType() == GType_FF || getGameType() == GType_PP) { dumpVgaScript(_curVgaFile1 + READ_LE_UINT16(&((ImageHeader_Feeble*)b)->scriptOffs), zoneNum, vgaSpriteId); } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { diff --git a/engines/agos/script.cpp b/engines/agos/script.cpp index 6f809d9e2d..1dbb9c255a 100644 --- a/engines/agos/script.cpp +++ b/engines/agos/script.cpp @@ -22,6 +22,7 @@ // Item script opcodes for Simon1/Simon2 +#include "common/debug-channels.h" #include "common/endian.h" #include "common/system.h" #include "common/textconsole.h" @@ -987,7 +988,7 @@ int AGOSEngine::runScript() { return 1; do { - if (_dumpOpcodes) + if (DebugMan.isDebugChannelEnabled(kDebugOpcode)) dumpOpcode(_codePtr); if (getGameType() == GType_ELVIRA1) { diff --git a/engines/agos/subroutine.cpp b/engines/agos/subroutine.cpp index 39bc468dea..1e6ecaa829 100644 --- a/engines/agos/subroutine.cpp +++ b/engines/agos/subroutine.cpp @@ -20,8 +20,7 @@ * */ - - +#include "common/debug-channels.h" #include "common/file.h" #include "common/textconsole.h" @@ -531,7 +530,7 @@ int AGOSEngine::startSubroutine(Subroutine *sub) { _classMode1 = 0; _classMode2 = 0; - if (_dumpScripts) + if (DebugMan.isDebugChannelEnabled(kDebugSubroutine)) dumpSubroutine(sub); if (++_recursionDepth > 40) @@ -564,8 +563,7 @@ restart: else _codePtr += 8; - if (_dumpOpcodes) - debug("; %d", sub->id); + debugC(kDebugOpcode, "; %d", sub->id); result = runScript(); if (result != 0) { break; diff --git a/engines/agos/vga.cpp b/engines/agos/vga.cpp index c656c0167a..f761c3fc3f 100644 --- a/engines/agos/vga.cpp +++ b/engines/agos/vga.cpp @@ -27,6 +27,7 @@ #include "agos/intern.h" #include "agos/vga.h" +#include "common/debug-channels.h" #include "common/endian.h" #include "common/system.h" #include "common/textconsole.h" @@ -152,7 +153,7 @@ void AGOSEngine::runVgaScript() { for (;;) { uint opcode; - if (_dumpVgaOpcodes) { + if (DebugMan.isDebugChannelEnabled(kDebugVGAOpcode)) { if (_vcPtr != (const byte *)&_vcGetOutOfCode) { debugN("%.5d %.5X: %5d %4d ", _vgaTickCounter, (unsigned int)(_vcPtr - _curVgaFile1), _vgaCurSpriteId, _vgaCurZoneNum); dumpVideoScript(_vcPtr, true); @@ -381,8 +382,7 @@ void AGOSEngine::vcSkipNextInstruction() { _vcPtr += opcodeParamLenPN[opcode]; } - if (_dumpVgaOpcodes) - debugN("; skipped\n"); + debugCN(kDebugVGAOpcode, "; skipped\n"); } // VGA Script commands @@ -648,7 +648,7 @@ void AGOSEngine::drawImage_init(int16 image, uint16 palette, int16 x, int16 y, u if (height == 0 || width == 0) return; - if (_dumpImages) + if (DebugMan.isDebugChannelEnabled(kDebugImageDump)) dumpSingleBitmap(_vgaCurZoneNum, state.image, state.srcPtr, width, height, state.palette); state.width = state.draw_width = width; /* cl */ diff --git a/engines/avalanche/console.cpp b/engines/avalanche/console.cpp index 29ae5cf9c3..d4923affc1 100644 --- a/engines/avalanche/console.cpp +++ b/engines/avalanche/console.cpp @@ -31,7 +31,7 @@ namespace Avalanche { AvalancheConsole::AvalancheConsole(AvalancheEngine *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("magic_lines", WRAP_METHOD(AvalancheConsole, Cmd_MagicLines)); + registerCmd("magic_lines", WRAP_METHOD(AvalancheConsole, Cmd_MagicLines)); } AvalancheConsole::~AvalancheConsole() { @@ -42,7 +42,7 @@ AvalancheConsole::~AvalancheConsole() { */ bool AvalancheConsole::Cmd_MagicLines(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Usage: %s\n", argv[0]); return true; } diff --git a/engines/avalanche/ghostroom.cpp b/engines/avalanche/ghostroom.cpp index 16c79fdee0..047a3670c2 100644 --- a/engines/avalanche/ghostroom.cpp +++ b/engines/avalanche/ghostroom.cpp @@ -49,6 +49,9 @@ GhostRoom::GhostRoom(AvalancheEngine *vm) { _greldetCount = 0; _redGreldet = false; _wasLoaded = false; + + _ghost = nullptr; + _glerk = nullptr; } GhostRoom::~GhostRoom() { diff --git a/engines/cge/console.cpp b/engines/cge/console.cpp index 447875c06f..e926e89506 100644 --- a/engines/cge/console.cpp +++ b/engines/cge/console.cpp @@ -26,7 +26,7 @@ namespace CGE { CGEConsole::CGEConsole(CGEEngine *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("Boundaries", WRAP_METHOD(CGEConsole, Cmd_boundaries)); + registerCmd("Boundaries", WRAP_METHOD(CGEConsole, Cmd_boundaries)); } CGEConsole::~CGEConsole() { @@ -37,7 +37,7 @@ CGEConsole::~CGEConsole() { */ bool CGEConsole::Cmd_boundaries(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Usage: %s\n", argv[0]); return true; } diff --git a/engines/cine/console.cpp b/engines/cine/console.cpp index 82197693d4..4646bdf280 100644 --- a/engines/cine/console.cpp +++ b/engines/cine/console.cpp @@ -29,7 +29,7 @@ bool labyrinthCheat; CineConsole::CineConsole(CineEngine *vm) : GUI::Debugger(), _vm(vm) { assert(_vm); - DCmd_Register("labyrinthCheat", WRAP_METHOD(CineConsole, Cmd_LabyrinthCheat)); + registerCmd("labyrinthCheat", WRAP_METHOD(CineConsole, Cmd_LabyrinthCheat)); labyrinthCheat = false; } diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp index f6419ecafc..b9175cac72 100644 --- a/engines/cine/gfx.cpp +++ b/engines/cine/gfx.cpp @@ -1902,7 +1902,9 @@ void maskBgOverlay(const byte *bgPtr, const byte *maskPtr, int16 width, int16 he destPtr++; srcPtr++; - maskPtr++; + + if (maskPtr) + maskPtr++; } } diff --git a/engines/cine/pal.cpp b/engines/cine/pal.cpp index f3985c691e..18f260cab7 100644 --- a/engines/cine/pal.cpp +++ b/engines/cine/pal.cpp @@ -332,9 +332,9 @@ byte *Palette::save(byte *buf, const uint size, const Graphics::PixelFormat form // Save the palette to the output in the specified format for (uint i = firstIndex; i < firstIndex + numColors; i++) { - const uint r = (_colors[i].r * rNewMax) / rOrigMax; - const uint g = (_colors[i].g * gNewMax) / gOrigMax; - const uint b = (_colors[i].b * bNewMax) / bOrigMax; + const uint r = (_colors[i].r * rNewMax) / (rOrigMax == 0 ? 1 : rOrigMax); + const uint g = (_colors[i].g * gNewMax) / (gOrigMax == 0 ? 1 : gOrigMax); + const uint b = (_colors[i].b * bNewMax) / (bOrigMax == 0 ? 1 : bOrigMax); buf[i * format.bytesPerPixel + rBytePos] |= r << (format.rShift % 8); buf[i * format.bytesPerPixel + gBytePos] |= g << (format.gShift % 8); diff --git a/engines/cruise/debugger.cpp b/engines/cruise/debugger.cpp index 4ef66ee11e..d4e706a094 100644 --- a/engines/cruise/debugger.cpp +++ b/engines/cruise/debugger.cpp @@ -29,9 +29,9 @@ namespace Cruise { Debugger::Debugger(): GUI::Debugger() { - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("hotspots", WRAP_METHOD(Debugger, cmd_hotspots)); - DCmd_Register("items", WRAP_METHOD(Debugger, cmd_items)); + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("hotspots", WRAP_METHOD(Debugger, cmd_hotspots)); + registerCmd("items", WRAP_METHOD(Debugger, cmd_items)); } /** @@ -70,7 +70,7 @@ bool Debugger::cmd_hotspots(int argc, const char **argv) { if (*pObjectName) { getMultipleObjectParam(currentObject->overlay, currentObject->idx, ¶ms); - DebugPrintf("%s %s - %d,%d\n", pObjectName, pObjType, params.X, params.Y); + debugPrintf("%s %s - %d,%d\n", pObjectName, pObjType, params.X, params.Y); } } @@ -96,7 +96,7 @@ bool Debugger::cmd_items(int argc, const char **argv) { getSingleObjectParam(i, j, 5, &returnVar); if (returnVar < -1) - DebugPrintf("%s\n", getObjectName(j, pOvlData->arrayNameObj)); + debugPrintf("%s\n", getObjectName(j, pOvlData->arrayNameObj)); } } } diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp index 4893b0fe34..4fbf2d31ea 100644 --- a/engines/draci/game.cpp +++ b/engines/draci/game.cpp @@ -50,44 +50,46 @@ enum { }; Game::Game(DraciEngine *vm) : _vm(vm), _walkingState(vm) { - uint i; - _dialogueLinesNum = 0; _blockNum = 0; - for (i = 0; i < kDialogueLines; i++) - _dialogueAnims[0] = 0; + for (uint i = 0; i < kDialogueLines; i++) + _dialogueAnims[0] = nullptr; _loopStatus = kStatusOrdinary; _loopSubstatus = kOuterLoop; - _shouldQuit = 0; - _shouldExitLoop = 0; - _isReloaded = 0; _speechTick = 0; _speechDuration = 0; - _objUnderCursor = 0; - _animUnderCursor = 0; _markedAnimationIndex = 0; _scheduledPalette = 0; _fadePhases = 0; _fadePhase = 0; _fadeTick = 0; - _isFadeOut = 1; _mouseChangeTick = 0; - _enableQuickHero = 0; - _wantQuickHero = 0; - _enableSpeedText = 0; - _titleAnim = 0; - _inventoryAnim = 0; - _walkingMapOverlay = 0; - _walkingShortestPathOverlay = 0; - _walkingObliquePathOverlay = 0; - _currentItem = 0; - _itemUnderCursor = 0; _previousItemPosition = 0; - for (i = 0; i < kInventorySlots; i++) - _inventory[i] = 0; + _shouldQuit = false; + _shouldExitLoop = false; + _isReloaded = false; + _isPositionLoaded = false; + _isFadeOut = true; + _enableQuickHero = false; + _wantQuickHero = false; + _enableSpeedText = false; + _isPositionLoaded = false; + + _objUnderCursor = nullptr; + _animUnderCursor = nullptr; + _titleAnim = nullptr; + _inventoryAnim = nullptr; + _walkingMapOverlay = nullptr; + _walkingShortestPathOverlay = nullptr; + _walkingObliquePathOverlay = nullptr; + _currentItem = nullptr; + _itemUnderCursor = nullptr; + + for (int i = 0; i < kInventorySlots; i++) + _inventory[i] = nullptr; _newRoom = 0; _newGate = 0; @@ -95,10 +97,10 @@ Game::Game(DraciEngine *vm) : _vm(vm), _walkingState(vm) { _pushedNewRoom = 0; _pushedNewGate = 0; _currentDialogue = 0; - _dialogueArchive = 0; - _dialogueBlocks = 0; - _dialogueBegin = 0; - _dialogueExit = 0; + _dialogueArchive = nullptr; + _dialogueBlocks = nullptr; + _dialogueBegin = false; + _dialogueExit = false; _currentBlock = 0; _lastBlock = 0; @@ -113,7 +115,7 @@ Game::Game(DraciEngine *vm) : _vm(vm), _walkingState(vm) { uint numPersons = file->_length / personSize; _persons = new Person[numPersons]; - for (i = 0; i < numPersons; ++i) { + for (uint i = 0; i < numPersons; ++i) { _persons[i]._x = personData.readUint16LE(); _persons[i]._y = personData.readUint16LE(); _persons[i]._fontColor = personData.readByte(); @@ -126,9 +128,9 @@ Game::Game(DraciEngine *vm) : _vm(vm), _walkingState(vm) { uint numDialogues = file->_length / sizeof(uint16); _dialogueOffsets = new uint[numDialogues]; - uint curOffset; - for (i = 0, curOffset = 0; i < numDialogues; ++i) { - _dialogueOffsets[i] = curOffset; + uint curOffset, idx; + for (idx = 0, curOffset = 0; idx < numDialogues; ++idx) { + _dialogueOffsets[idx] = curOffset; curOffset += dialogueData.readUint16LE(); } @@ -163,7 +165,7 @@ Game::Game(DraciEngine *vm) : _vm(vm), _walkingState(vm) { _variables = new int[numVariables]; Common::MemoryReadStream variableData(file->_data, file->_length); - for (i = 0; i < numVariables; ++i) { + for (uint i = 0; i < numVariables; ++i) { _variables[i] = variableData.readUint16LE(); } @@ -181,7 +183,7 @@ Game::Game(DraciEngine *vm) : _vm(vm), _walkingState(vm) { _objects = new GameObject[numObjects]; Common::MemoryReadStream objStatus(file->_data, file->_length); - for (i = 0; i < numObjects; ++i) { + for (uint i = 0; i < numObjects; ++i) { byte tmp = objStatus.readByte(); // Set object visibility @@ -251,14 +253,14 @@ void Game::init() { setLoopStatus(kStatusGate); setLoopSubstatus(kOuterLoop); - _animUnderCursor = NULL; + _animUnderCursor = nullptr; - _currentItem = _itemUnderCursor = NULL; + _currentItem = _itemUnderCursor = nullptr; _previousItemPosition = -1; _vm->_mouse->setCursorType(kHighlightedCursor); // anything different from kNormalCursor - _objUnderCursor = NULL; + _objUnderCursor = nullptr; // Set the inventory to empty initially memset(_inventory, 0, kInventorySlots * sizeof(GameItem *)); @@ -402,12 +404,12 @@ void Game::handleInventoryLoop() { // an overlay, for which we check. Item animations have their IDs // calculated by offseting their itemID from the ID of the last "special" // animation ID. In this way, we obtain its itemID. - if (_animUnderCursor != NULL && _animUnderCursor != _inventoryAnim && _animUnderCursor->getID() != kOverlayImage) { + if (_animUnderCursor != nullptr && _animUnderCursor != _inventoryAnim && _animUnderCursor->getID() != kOverlayImage) { _itemUnderCursor = getItem(kInventoryItemsID - _animUnderCursor->getID()); - assert(_itemUnderCursor != NULL); + assert(_itemUnderCursor != nullptr); assert(_itemUnderCursor->_anim == _animUnderCursor); } else { - _itemUnderCursor = NULL; + _itemUnderCursor = nullptr; } // If the user pressed the left mouse button @@ -824,7 +826,7 @@ void Game::removeItem(GameItem *item) { return; for (uint i = 0; i < kInventorySlots; ++i) { if (_inventory[i] == item) { - _inventory[i] = NULL; + _inventory[i] = nullptr; item->_anim->stop(); break; } @@ -931,7 +933,7 @@ void Game::inventoryDone() { _walkingState.callbackLast(); // Reset item under cursor - _itemUnderCursor = NULL; + _itemUnderCursor = nullptr; // Don't start the inventory mode again if the mouse is on the top. _mouseChangeTick = kMouseDoNotSwitch; @@ -1640,7 +1642,7 @@ void Game::DoSync(Common::Serializer &s, uint8 saveVersion) { _currentItem = getItem(handItemID); } } else { - _currentItem = 0; + _currentItem = nullptr; } } diff --git a/engines/draci/walking.cpp b/engines/draci/walking.cpp index 6914898ec1..04cd929ac6 100644 --- a/engines/draci/walking.cpp +++ b/engines/draci/walking.cpp @@ -453,7 +453,7 @@ void WalkingState::callback() { _callback = NULL; _vm->_script->runWrapper(originalCallback, _callbackOffset, true, false); _callbackLast = NULL; - _callbackOffset = NULL; + _callbackOffset = 0; } void WalkingState::callbackLast() { diff --git a/engines/drascula/console.cpp b/engines/drascula/console.cpp index 50e96c8757..b545c096d0 100644 --- a/engines/drascula/console.cpp +++ b/engines/drascula/console.cpp @@ -27,7 +27,7 @@ namespace Drascula { Console::Console(DrasculaEngine *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("room", WRAP_METHOD(Console, Cmd_Room)); + registerCmd("room", WRAP_METHOD(Console, Cmd_Room)); } Console::~Console() { @@ -35,7 +35,7 @@ Console::~Console() { bool Console::Cmd_Room(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: room <number>\n"); + debugPrintf("Usage: room <number>\n"); return true; } diff --git a/engines/fullpipe/console.cpp b/engines/fullpipe/console.cpp index cb76345d66..dd3d1bf693 100644 --- a/engines/fullpipe/console.cpp +++ b/engines/fullpipe/console.cpp @@ -28,14 +28,14 @@ namespace Fullpipe { Console::Console(FullpipeEngine *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("scene", WRAP_METHOD(Console, Cmd_Scene)); + registerCmd("scene", WRAP_METHOD(Console, Cmd_Scene)); } bool Console::Cmd_Scene(int argc, const char **argv) { if (argc != 2) { int sceneTag = _vm->_currentScene->_sceneId; - DebugPrintf("Current scene: %d (scene tag: %d)\n", _vm->getSceneFromTag(sceneTag), sceneTag); - DebugPrintf("Use %s <scene> to change the current scene\n", argv[0]); + debugPrintf("Current scene: %d (scene tag: %d)\n", _vm->getSceneFromTag(sceneTag), sceneTag); + debugPrintf("Use %s <scene> to change the current scene\n", argv[0]); return true; } else { int scene = _vm->convertScene(atoi(argv[1])); diff --git a/engines/fullpipe/detection.cpp b/engines/fullpipe/detection.cpp index 62c5dd3b80..de0ed04d25 100644 --- a/engines/fullpipe/detection.cpp +++ b/engines/fullpipe/detection.cpp @@ -26,6 +26,7 @@ #include "common/file.h" #include "fullpipe/fullpipe.h" +#include "fullpipe/gameloader.h" namespace Fullpipe { @@ -87,15 +88,72 @@ public: } virtual bool hasFeature(MetaEngineFeature f) const; + virtual int getMaximumSaveSlot() const { return 8; } + virtual SaveStateList listSaves(const char *target) const; + virtual void removeSaveState(const char *target, int slot) const; + virtual SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const; virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; }; bool FullpipeMetaEngine::hasFeature(MetaEngineFeature f) const { - return false; + return + (f == kSupportsListSaves) || + (f == kSupportsDeleteSave) || + (f == kSavesSupportMetaInfo) || + (f == kSavesSupportThumbnail) || + (f == kSavesSupportCreationDate) || + (f == kSupportsLoadingDuringStartup); } -bool Fullpipe::FullpipeEngine::hasFeature(EngineFeature f) const { - return false; +SaveStateList FullpipeMetaEngine::listSaves(const char *target) const { + Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); + Common::StringArray filenames; + Common::String pattern("fullpipe.s??"); + + filenames = saveFileMan->listSavefiles(pattern); + sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..) + + SaveStateList saveList; + for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) { + // Obtain the last 2 digits of the filename, since they correspond to the save slot + int slotNum = atoi(file->c_str() + file->size() - 2); + + if (slotNum >= 0 && slotNum <= getMaximumSaveSlot()) { + Common::InSaveFile *in = saveFileMan->openForLoading(*file); + if (in) { + Fullpipe::FullpipeSavegameHeader header; + Fullpipe::readSavegameHeader(in, header); + saveList.push_back(SaveStateDescriptor(slotNum, header.saveName)); + delete header.thumbnail; + delete in; + } + } + } + + return saveList; +} + +void FullpipeMetaEngine::removeSaveState(const char *target, int slot) const { + g_system->getSavefileManager()->removeSavefile(Fullpipe::getSavegameFile(slot)); +} + +SaveStateDescriptor FullpipeMetaEngine::querySaveMetaInfos(const char *target, int slot) const { + Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading( + Fullpipe::getSavegameFile(slot)); + + if (f) { + Fullpipe::FullpipeSavegameHeader header; + Fullpipe::readSavegameHeader(f, header); + delete f; + + // Create the return descriptor + SaveStateDescriptor desc(slot, header.saveName); + desc.setThumbnail(header.thumbnail); + + return desc; + } + + return SaveStateDescriptor(); } bool FullpipeMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { diff --git a/engines/fullpipe/fullpipe.cpp b/engines/fullpipe/fullpipe.cpp index 5369c05de7..85a5167841 100644 --- a/engines/fullpipe/fullpipe.cpp +++ b/engines/fullpipe/fullpipe.cpp @@ -37,6 +37,7 @@ #include "fullpipe/scenes.h" #include "fullpipe/floaters.h" #include "fullpipe/console.h" +#include "fullpipe/constants.h" namespace Fullpipe { @@ -205,7 +206,39 @@ void FullpipeEngine::initialize() { } void FullpipeEngine::restartGame() { - warning("STUB: FullpipeEngine::restartGame()"); + _floaters->stopAll(); + + clearGlobalMessageQueueList(); + clearMessages(); + + initObjectStates(); + + if (_scene2) { + _scene2->getAniMan(); + _scene2 = 0; + } + + if (_currentScene) { + _gameLoader->unloadScene(_currentScene->_sceneId); + + _currentScene = 0; + } + + _gameLoader->restoreDefPicAniInfos(); + + getGameLoaderInventory()->clear(); + getGameLoaderInventory()->addItem(ANI_INV_MAP, 1); + getGameLoaderInventory()->rebuildItemRects(); + + initMap(); + + if (_flgPlayIntro) { + _gameLoader->loadScene(SC_INTRO1); + _gameLoader->gotoScene(SC_INTRO1, TrubaUp); + } else { + _gameLoader->loadScene(SC_1); + _gameLoader->gotoScene(SC_1, TrubaLeft); + } } Common::Error FullpipeEngine::run() { @@ -347,7 +380,7 @@ void FullpipeEngine::updateEvents() { case Common::EVENT_QUIT: _gameContinue = false; break; - case Common::EVENT_RBUTTONDOWN: + case Common::EVENT_RBUTTONDOWN: if (!_inputArFlag && (_updateTicks - _lastInputTicks) >= 2) { ex = new ExCommand(0, 17, 107, event.mouse.x, event.mouse.y, 0, 1, 0, 0, 0); ex->_excFlags |= 3; @@ -477,7 +510,20 @@ void FullpipeEngine::setObjectState(const char *name, int state) { } void FullpipeEngine::disableSaves(ExCommand *ex) { - warning("STUB: FullpipeEngine::disableSaves()"); + if (_isSaveAllowed) { + _isSaveAllowed = false; + + if (_globalMessageQueueList->size() && (*_globalMessageQueueList)[0] != 0) { + for (int i = 0; i < _globalMessageQueueList->size(); i++) { + if ((*_globalMessageQueueList)[i]->_flags & 1) + if ((*_globalMessageQueueList)[i]->_id != ex->_parId && !(*_globalMessageQueueList)[i]->_isFinished) + return; + } + } + + if (_currentScene) + _gameLoader->writeSavegame(_currentScene, "savetmp.sav"); + } } diff --git a/engines/fullpipe/fullpipe.h b/engines/fullpipe/fullpipe.h index 27505252ab..afdc493258 100644 --- a/engines/fullpipe/fullpipe.h +++ b/engines/fullpipe/fullpipe.h @@ -99,7 +99,6 @@ public: const ADGameDescription *_gameDescription; const char *getGameId() const; Common::Platform getPlatform() const; - bool hasFeature(EngineFeature f) const; Common::RandomSource *_rnd; diff --git a/engines/fullpipe/gameloader.cpp b/engines/fullpipe/gameloader.cpp index d9f7327a6b..c8b01939dd 100644 --- a/engines/fullpipe/gameloader.cpp +++ b/engines/fullpipe/gameloader.cpp @@ -21,6 +21,7 @@ */ #include "fullpipe/fullpipe.h" +#include "graphics/thumbnail.h" #include "fullpipe/gameloader.h" #include "fullpipe/scene.h" @@ -501,6 +502,14 @@ void GameLoader::updateSystems(int counterdiff) { } } +void GameLoader::readSavegame(const char *fname) { + warning("STUB: readSavegame(%s)", fname); +} + +void GameLoader::writeSavegame(Scene *sc, const char *fname) { + warning("STUB: writeSavegame(sc, %s)", fname); +} + Sc2::Sc2() { _sceneId = 0; _field_2 = 0; @@ -593,6 +602,42 @@ bool PreloadItems::load(MfcArchive &file) { return true; } +const char *getSavegameFile(int saveGameIdx) { + static char buffer[20]; + sprintf(buffer, "fullpipe.s%02d", saveGameIdx); + return buffer; +} + +bool readSavegameHeader(Common::InSaveFile *in, FullpipeSavegameHeader &header) { + char saveIdentBuffer[6]; + header.thumbnail = NULL; + + // Validate the header Id + in->read(saveIdentBuffer, 6); + if (strcmp(saveIdentBuffer, "SVMCR")) + return false; + + header.version = in->readByte(); + if (header.version != FULLPIPE_SAVEGAME_VERSION) + return false; + + // Read in the string + header.saveName.clear(); + char ch; + while ((ch = (char)in->readByte()) != '\0') header.saveName += ch; + + // Get the thumbnail + header.thumbnail = Graphics::loadThumbnail(*in); + if (!header.thumbnail) + return false; + + return true; +} + +void GameLoader::restoreDefPicAniInfos() { + warning("STUB: restoreDefPicAniInfos()"); +} + GameVar *FullpipeEngine::getGameLoaderGameVar() { if (_gameLoader) return _gameLoader->_gameVar; diff --git a/engines/fullpipe/gameloader.h b/engines/fullpipe/gameloader.h index a79c0e11b4..772cc51130 100644 --- a/engines/fullpipe/gameloader.h +++ b/engines/fullpipe/gameloader.h @@ -29,6 +29,8 @@ namespace Fullpipe { +#define FULLPIPE_SAVEGAME_VERSION 1 + class SceneTag; class MctlCompound; class InputController; @@ -72,6 +74,12 @@ class PreloadItems : public Common::Array<PreloadItem *>, public CObject { virtual bool load(MfcArchive &file); }; +struct FullpipeSavegameHeader { + uint8 version; + Common::String saveName; + Graphics::Surface *thumbnail; +}; + class GameLoader : public CObject { public: GameLoader(); @@ -89,6 +97,11 @@ class GameLoader : public CObject { void applyPicAniInfos(Scene *sc, PicAniInfo **picAniInfo, int picAniInfoCount); void saveScenePicAniInfos(int sceneId); + void readSavegame(const char *fname); + void writeSavegame(Scene *sc, const char *fname); + + void restoreDefPicAniInfos(); + GameProject *_gameProject; InteractionController *_interactionController; InputController *_inputController; @@ -108,6 +121,9 @@ class GameLoader : public CObject { int _preloadEntranceId; }; +const char *getSavegameFile(int saveGameIdx); +bool readSavegameHeader(Common::InSaveFile *in, FullpipeSavegameHeader &header); + Inventory2 *getGameLoaderInventory(); InteractionController *getGameLoaderInteractionController(); MctlCompound *getSc2MctlCompoundBySceneId(int16 sceneId); diff --git a/engines/fullpipe/gfx.cpp b/engines/fullpipe/gfx.cpp index 7c66a9a747..520e81835b 100644 --- a/engines/fullpipe/gfx.cpp +++ b/engines/fullpipe/gfx.cpp @@ -145,7 +145,7 @@ void Background::addPictureObject(PictureObject *pct) { bool inserted = false; for (uint i = 1; i < _picObjList.size(); i++) { - if (((PictureObject *)_picObjList[i])->_priority <= pct->_priority) { + if (_picObjList[i]->_priority <= pct->_priority) { _picObjList.insert_at(i, pct); inserted = true; break; @@ -192,7 +192,7 @@ bool PictureObject::load(MfcArchive &file, bool bigPicture) { _picture->load(file); - _pictureObject2List = new PtrList(); + _pictureObject2List = new Common::Array<GameObject *>; int count = file.readUint16LE(); @@ -351,7 +351,25 @@ void GameObject::setOXY(int x, int y) { _oy = y; } -void GameObject::renumPictures(PtrList *lst) { +void GameObject::renumPictures(Common::Array<StaticANIObject *> *lst) { + int *buf = (int *)calloc(lst->size() + 2, sizeof(int)); + + for (uint i = 0; i < lst->size(); i++) { + if (_id == ((GameObject *)((*lst)[i]))->_id) + buf[((GameObject *)((*lst)[i]))->_okeyCode] = 1; + } + + if (buf[_okeyCode]) { + uint count; + for (count = 1; buf[count] && count < lst->size() + 2; count++) + ; + _okeyCode = count; + } + + free(buf); +} + +void GameObject::renumPictures(Common::Array<PictureObject *> *lst) { int *buf = (int *)calloc(lst->size() + 2, sizeof(int)); for (uint i = 0; i < lst->size(); i++) { @@ -380,6 +398,7 @@ bool GameObject::getPicAniInfo(PicAniInfo *info) { info->ox = _ox; info->oy = _oy; info->priority = _priority; + warning("Yep %d", _id); return true; } diff --git a/engines/fullpipe/gfx.h b/engines/fullpipe/gfx.h index b3e22b610b..191df7709a 100644 --- a/engines/fullpipe/gfx.h +++ b/engines/fullpipe/gfx.h @@ -92,7 +92,7 @@ class Picture : public MemoryObject { virtual bool load(MfcArchive &file); void setAOIDs(); - void init(); + virtual void init(); void getDibInfo(); Bitmap *getPixelData(); virtual void draw(int x, int y, int style, int angle); @@ -141,7 +141,8 @@ class GameObject : public CObject { virtual bool load(MfcArchive &file); void setOXY(int x, int y); - void renumPictures(PtrList *lst); + void renumPictures(Common::Array<StaticANIObject *> *lst); + void renumPictures(Common::Array<PictureObject *> *lst); void setFlags(int16 flags) { _flags = flags; } void clearFlags() { _flags = 0; } const char *getName() { return _objectName; } @@ -153,7 +154,7 @@ class GameObject : public CObject { class PictureObject : public GameObject { public: Picture *_picture; - PtrList *_pictureObject2List; + Common::Array<GameObject *> *_pictureObject2List; int _ox2; int _oy2; @@ -178,7 +179,7 @@ class PictureObject : public GameObject { class Background : public CObject { public: - PtrList _picObjList; + Common::Array<PictureObject *> _picObjList; char *_bgname; int _x; diff --git a/engines/fullpipe/messagehandlers.cpp b/engines/fullpipe/messagehandlers.cpp index 15aa78d342..d4f79d1dd8 100644 --- a/engines/fullpipe/messagehandlers.cpp +++ b/engines/fullpipe/messagehandlers.cpp @@ -392,12 +392,10 @@ int global_messageHandler3(ExCommand *cmd) { } return result; case 29: - if (!g_fp->_currentScene) - return result; - - if (g_fp->_gameLoader->_interactionController->_flag24) { + if (g_fp->_gameLoader->_interactionController->_flag24 && g_fp->_currentScene) { ani = g_fp->_currentScene->getStaticANIObjectAtPos(cmd->_sceneClickX, cmd->_sceneClickY); ani2 = g_fp->_currentScene->getStaticANIObject1ById(g_fp->_gameLoader->_field_FA, -1); + if (ani) { if (g_fp->_msgObjectId2 == ani->_id && g_fp->_msgId == ani->_okeyCode) { cmd->_messageKind = 0; diff --git a/engines/fullpipe/messages.cpp b/engines/fullpipe/messages.cpp index 8257d1459f..b643ff9b8f 100644 --- a/engines/fullpipe/messages.cpp +++ b/engines/fullpipe/messages.cpp @@ -26,6 +26,7 @@ #include "fullpipe/messages.h" #include "fullpipe/modal.h" #include "fullpipe/statics.h" +#include "fullpipe/gameloader.h" namespace Fullpipe { @@ -394,8 +395,18 @@ void MessageQueue::update() { } void MessageQueue::messageQueueCallback1(int par) { - // Autosave - debug(3, "STUB: MessageQueue::messageQueueCallback1()"); + if (g_fp->_isSaveAllowed && par == 16) { + if (g_fp->_globalMessageQueueList->size() && (*g_fp->_globalMessageQueueList)[0] != 0) { + for (int i = 0; i < g_fp->_globalMessageQueueList->size(); i++) { + if ((*g_fp->_globalMessageQueueList)[i]->_flags & 1) + if ((*g_fp->_globalMessageQueueList)[i] != this && !(*g_fp->_globalMessageQueueList)[i]->_isFinished) + return; + } + } + + if (g_fp->_currentScene) + g_fp->_gameLoader->writeSavegame(g_fp->_currentScene, "savetmp.sav"); + } } void MessageQueue::addExCommand(ExCommand *ex) { diff --git a/engines/fullpipe/modal.cpp b/engines/fullpipe/modal.cpp index bba5df0cd5..8981cdb8e6 100644 --- a/engines/fullpipe/modal.cpp +++ b/engines/fullpipe/modal.cpp @@ -34,6 +34,8 @@ #include "graphics/palette.h" #include "video/avi_decoder.h" +#include "engines/savestate.h" + namespace Fullpipe { ModalIntro::ModalIntro() { @@ -1084,17 +1086,17 @@ void ModalMainMenu::updateSoundVolume(Sound *snd) { b = 800 - dx; } - int32 pp = b * a; //(0x51EB851F * b * a) >> 32) >> 8; // TODO FIXME + int32 pp = b * a; - snd->setPanAndVolume(pan + (pp >> 31) + pp, par); + snd->setPanAndVolume(pan + pp / 800, par); return; } int dx = _screct.left - ani->_ox; if (dx <= 800) { - int32 s = 0x51EB851F * (800 - dx) * (g_fp->_sfxVolume - (-3500)); // TODO FIXME - int32 p = -3500 + (s >> 31) + (s >> 8); + int32 s = (800 - dx) * (g_fp->_sfxVolume - (-3500)); + int32 p = -3500 + s / 800; if (p > g_fp->_sfxVolume) p = g_fp->_sfxVolume; @@ -1103,8 +1105,6 @@ void ModalMainMenu::updateSoundVolume(Sound *snd) { } else { snd->setPanAndVolume(-3500, 0); } - - warning("STUB: ModalMainMenu::updateSoundVolume()"); } void ModalMainMenu::updateSliderPos() { @@ -1460,6 +1460,8 @@ ModalSaveGame::ModalSaveGame() { _rect = g_fp->_sceneRect; _queryDlg = 0; _mode = 1; + + _objtype = kObjTypeModalSaveGame; } ModalSaveGame::~ModalSaveGame() { @@ -1591,9 +1593,9 @@ void ModalSaveGame::setup(Scene *sc, int mode) { fileinfo = new FileInfo; memset(fileinfo, 0, sizeof(FileInfo)); - snprintf(fileinfo->filename, 160, "save%02d.sav", i); + strncpy(fileinfo->filename, getSavegameFile(i), 160); - if (!getFileInfo(fileinfo->filename, fileinfo)) { + if (!getFileInfo(i, fileinfo)) { fileinfo->empty = true; w = _emptyD->getDimensions(&point)->x; } else { @@ -1623,12 +1625,175 @@ char *ModalSaveGame::getSaveName() { return _files[_queryRes]->filename; } -bool ModalSaveGame::getFileInfo(char *filename, FileInfo *fileinfo) { - warning("STUB: ModalSaveGame::getFileInfo()"); +bool ModalSaveGame::getFileInfo(int slot, FileInfo *fileinfo) { + Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading( + Fullpipe::getSavegameFile(slot)); + + if (!f) + return false; + + Fullpipe::FullpipeSavegameHeader header; + Fullpipe::readSavegameHeader(f, header); + delete f; + + // Create the return descriptor + SaveStateDescriptor desc(slot, header.saveName); + char res[17]; + + snprintf(res, 17, "%s %s", desc.getSaveDate().c_str(), desc.getSaveTime().c_str()); + + for (int i = 0; i < 16; i++) { + switch(res[i]) { + case '.': + fileinfo->date[i] = 11; + break; + case ' ': + fileinfo->date[i] = 12; + break; + case ':': + fileinfo->date[i] = 10; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + fileinfo->date[i] = res[i] - '0'; + break; + default: + error("Incorrect date format: %s", res); + } + } + + return true; +} + +void ModalSaveGame::update() { + if (_menuScene) + _menuScene->draw(); + + _bgr->draw(); + + if (_queryDlg) { + _queryDlg->update(); + + return; + } + + g_fp->_cursorId = PIC_CSR_DEFAULT; + + g_fp->setCursor(g_fp->_cursorId); + + Common::Point point; + + for (uint i = 0; i < _files.size(); i++) { + if (g_fp->_mouseScreenPos.x < _files[i]->fx1 || g_fp->_mouseScreenPos.x > _files[i]->fx2 || + g_fp->_mouseScreenPos.y < _files[i]->fy1 || g_fp->_mouseScreenPos.y > _files[i]->fy2 ) { + if (_files[i]->empty) { + _emptyD->setOXY(_files[i]->fx1, _files[i]->fy1); + _emptyD->draw(); + } else { + int x = _files[i]->fx1; + + for (int j = 0; j < 16; j++) { + _arrayL[_files[i]->date[j]]->setOXY(x + 1, _files[i]->fy1); + _arrayL[_files[i]->date[j]]->draw(); + + x += _arrayL[_files[i]->date[j]]->getDimensions(&point)->x + 2; + } + } + } else { + if (_files[i]->empty) { + _emptyL->setOXY(_files[i]->fx1, _files[i]->fy1); + _emptyL->draw(); + } else { + int x = _files[i]->fx1; + + for (int j = 0; j < 16; j++) { + _arrayD[_files[i]->date[j]]->setOXY(x + 1, _files[i]->fy1); + _arrayD[_files[i]->date[j]]->draw(); + + x += _arrayD[_files[i]->date[j]]->getDimensions(&point)->x + 2; + } + } + } + } + if (_cancelL->isPixelHitAtPos(g_fp->_mouseScreenPos.x, g_fp->_mouseScreenPos.y)) + _cancelL->draw(); + else if (_okL->isPixelHitAtPos(g_fp->_mouseScreenPos.x, g_fp->_mouseScreenPos.y)) + _okL->draw(); +} + +bool ModalSaveGame::handleMessage(ExCommand *cmd) { + if (_queryDlg) + return _queryDlg->handleMessage(cmd); + + if (cmd->_messageNum == 29) + processMouse(cmd->_x, cmd->_y); + else if (cmd->_messageNum == 36) + processKey(cmd->_keyCode); return false; } +void ModalSaveGame::processMouse(int x, int y) { + for (uint i = 0; i < _files.size(); i++) { + if (x >= _files[i]->fx1 && x <= _files[i]->fx2 && y >= _files[i]->fy1 && y <= _files[i]->fy2) { + _queryRes = i + 1; + + if (_mode) { + if (!_files[i]->empty) { + _queryDlg = new ModalQuery; + + _queryDlg->create(_menuScene, 0, PIC_MOV_BGR); + } + } + + return; + } + } + + if (_cancelL->isPixelHitAtPos(x, y)) + _queryRes = 0; +} + +void ModalSaveGame::saveload() { + if (_objtype != kObjTypeModalSaveGame) + return; + + if (_mode) { + if (getSaveName()) { + bool allowed = true; + + for (Common::Array<MessageQueue *>::iterator s = g_fp->_globalMessageQueueList->begin(); s != g_fp->_globalMessageQueueList->end(); ++s) { + if (!(*s)->_isFinished && ((*s)->getFlags() & 1)) + allowed = false; + } + + if (g_fp->_isSaveAllowed && allowed) + g_fp->_gameLoader->writeSavegame(g_fp->_currentScene, getSaveName()); + } + } else { + if (getSaveName()) { + if (_parentObj) { + delete _parentObj; + + _parentObj = 0; + } + + g_fp->stopAllSoundStreams(); + g_fp->stopSoundStream2(); + + g_fp->_gameLoader->readSavegame(getSaveName()); + } + } +} + void FullpipeEngine::openHelp() { if (!_modalObject) { ModalHelp *help = new ModalHelp; diff --git a/engines/fullpipe/modal.h b/engines/fullpipe/modal.h index a214b1c639..01d8e6b0ee 100644 --- a/engines/fullpipe/modal.h +++ b/engines/fullpipe/modal.h @@ -32,10 +32,7 @@ class Sound; struct FileInfo { char filename[260]; bool empty; - int day; - int month; - int year; - int time; + char date[16]; int fx1; int fx2; int fy1; @@ -46,9 +43,10 @@ class BaseModalObject { public: BaseModalObject *_parentObj; + ObjType _objtype; public: - BaseModalObject() : _parentObj(0) {} + BaseModalObject() : _parentObj(0) { _objtype = kObjTypeDefault; } virtual ~BaseModalObject() {} @@ -256,17 +254,19 @@ public: virtual ~ModalSaveGame(); virtual bool pollEvent() { return true; } - virtual bool handleMessage(ExCommand *message) { return false; } + virtual bool handleMessage(ExCommand *message); virtual bool init(int counterdiff); - virtual void update() {} - virtual void saveload() {} + virtual void update(); + virtual void saveload(); + + void processMouse(int x, int y); void setScene(Scene *sc); void setup(Scene *sc, int mode); void processKey(int key); char *getSaveName(); - bool getFileInfo(char *filename, FileInfo *fileinfo); + bool getFileInfo(int slot, FileInfo *fileinfo); Common::Rect _rect; int _oldBgX; diff --git a/engines/fullpipe/motion.cpp b/engines/fullpipe/motion.cpp index 35da154570..5b7419c7f4 100644 --- a/engines/fullpipe/motion.cpp +++ b/engines/fullpipe/motion.cpp @@ -125,9 +125,10 @@ void MctlCompound::addObject(StaticANIObject *obj) { } int MctlCompound::removeObject(StaticANIObject *obj) { - warning("STUB: MctlCompound::removeObject()"); + for (uint i = 0; i < _motionControllers.size(); i++) + _motionControllers[i]->_motionControllerObj->removeObject(obj); - return 0; + return 1; } void MctlCompound::initMovGraph2() { @@ -193,7 +194,8 @@ MessageQueue *MctlCompound::method34(StaticANIObject *ani, int sourceX, int sour if (idx == sourceIdx) return _motionControllers[idx]->_motionControllerObj->method34(ani, sourceX, sourceY, fuzzyMatch, staticsId); - MctlConnectionPoint *cp = findClosestConnectionPoint(ani->_ox, ani->_oy, idx, sourceX, sourceY, sourceIdx, &sourceIdx); + double dist; + MctlConnectionPoint *cp = findClosestConnectionPoint(ani->_ox, ani->_oy, idx, sourceX, sourceY, sourceIdx, &dist); if (!cp) return 0; @@ -261,7 +263,8 @@ MessageQueue *MctlCompound::doWalkTo(StaticANIObject *subj, int xpos, int ypos, if (match1 == match2) return _motionControllers[match1]->_motionControllerObj->doWalkTo(subj, xpos, ypos, fuzzyMatch, staticsId); - MctlConnectionPoint *closestP = findClosestConnectionPoint(subj->_ox, subj->_oy, match1, xpos, ypos, match2, &match2); + double dist; + MctlConnectionPoint *closestP = findClosestConnectionPoint(subj->_ox, subj->_oy, match1, xpos, ypos, match2, &dist); if (!closestP) return 0; @@ -427,14 +430,75 @@ MessageQueue *MctlLadder::controllerWalkTo(StaticANIObject *ani, int off) { return doWalkTo(ani, _ladderX + off * _width, _ladderY + off * _height, 1, 0); } -MctlConnectionPoint *MctlCompound::findClosestConnectionPoint(int ox, int oy, int destIndex, int connectionX, int connectionY, int sourceIndex, int *minDistancePtr) { +MctlConnectionPoint *MctlCompound::findClosestConnectionPoint(int ox, int oy, int destIndex, int connectionX, int connectionY, int sourceIndex, double *minDistancePtr) { +#if 0 + if (destIndex == sourceIndex) { + *minDistancePtr = sqrt((double)((oy - connectionY) * (oy - connectionY) + (ox - connectionX) * (ox - connectionX))); + + return 0; + } + + v11 = this->_motionControllers.m_pData; + currDistance = 0.0; + v12 = 0; + v13 = (MctlCompoundArrayItem *)*(&v11->vmt + sourceIndex); + minDistance = 1.0e10; + minConnectionPoint = 0; + if (v13->mctlConnectionPointsArray.CObArray.m_nSize > 0) { + do { + v14 = 0; + for (currMctlIndex = 0; v14 < this->_motionControllers.m_nSize; currMctlIndex = v14) { + v15 = this->_motionControllers.m_pData; + v16 = *(MovGraphReact **)(*(&v15->vmt + v14) + offsetof(MctlCompoundArrayItem, movGraphReactObj)); + if (v16) { + v17 = *(MctlConnectionPoint **)(*(_DWORD *)(*(&v15->vmt + sourceIndex) + 0x10) + 4 * v12);// MctlCompoundArrayItem.mctlConnectionPointsArray.CObArray.m_pData + LOBYTE(v18) = (*(bool (__thiscall **)(MovGraphReact *, int, int))(v16->CObject.vmt + offsetof(MovGraphReactVmt, pointInRegion)))(v16, v17->_connectionX, v17->_connectionY); + if (v18) { + v14 = currMctlIndex; + v19 = *(MctlConnectionPoint **)(*(_DWORD *)(*(&this->_motionControllers.m_pData->vmt + sourceIndex) + 0x10) + 4 * v12); + v20 = MctlCompound_findClosestConnectionPoint(this, ox, oy, destIndex, v19->_connectionX, v19->_connectionY, currMctlIndex, (int *)&currDistance); + if (currDistance < minDistance) { + minDistance = currDistance; + if (v20) + minConnectionPoint = v20; + else + minConnectionPoint = *(MctlConnectionPoint **)(*(_DWORD *)(*(&this->_motionControllers.m_pData->vmt + sourceIndex) + 0x10) + 4 * v12); + } + } else { + v14 = currMctlIndex; + } + } + ++v14; + } + ++v12; + } while (v12 < *(_DWORD *)(*(&this->_motionControllers.m_pData->vmt + sourceIndex) + 0x14)); // MctlCompoundArrayItem.mctlConnectionPointsArray.CObArray.m_nSize + } + + *minDistancePtr = minDistance; + + return minConnectionPoint; +} +#endif warning("STUB: MctlCompound::findClosestConnectionPoint()"); return 0; } void MctlCompound::replaceNodeX(int from, int to) { - warning("STUB: MctlCompound::replaceNodeX()"); + for (uint i = 0; i < _motionControllers.size(); i++) { + if (_motionControllers[i]->_motionControllerObj->_objtype == kObjTypeMovGraph) { + MovGraph *gr = (MovGraph *)_motionControllers[i]->_motionControllerObj; + + for (ObList::iterator n = gr->_nodes.begin(); n != gr->_nodes.end(); ++n) { + MovGraphNode *node = (MovGraphNode *)*n; + + if (node->_x == from) + node->_x = to; + } + + gr->calcNodeDistancesAndAngles(); + } + } } MctlConnectionPoint::MctlConnectionPoint() { @@ -493,15 +557,7 @@ bool MctlCompoundArray::load(MfcArchive &file) { MovGraphItem::MovGraphItem() { ani = 0; field_4 = 0; - field_8 = 0; - field_C = 0; - field_10 = 0; - field_14 = 0; - field_18 = 0; - field_1C = 0; - field_20 = 0; - field_24 = 0; - items = 0; + movitems = 0; count = 0; field_30 = 0; field_34 = 0; @@ -509,16 +565,36 @@ MovGraphItem::MovGraphItem() { field_3C = 0; } +void MovGraphItem::free() { + for (uint i = 0; i < movitems->size(); i++) { + (*movitems)[i]->movarr->_movSteps.clear(); + delete (*movitems)[i]->movarr; + } + + delete movitems; + + movitems = 0; +} + int MovGraph_messageHandler(ExCommand *cmd); -int MovGraphCallback(int a1, int a2, int a3) { - warning("STUB: MovgraphCallback"); +MovArr *movGraphCallback(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter) { + int residx = 0; + int itemidx = 0; - return 0; + while (counter > 1) { + if ((*items)[itemidx]->_mfield_4 > (*items)[itemidx + 1]->_mfield_4) + residx = itemidx; + + counter--; + itemidx++; + } + + return (*items)[residx]->movarr; } MovGraph::MovGraph() { - _callback1 = MovGraphCallback; + _callback1 = movGraphCallback; _field_44 = 0; insertMessageHandler(MovGraph_messageHandler, getMessageHandlersCount() - 1, 129); @@ -562,54 +638,482 @@ int MovGraph::removeObject(StaticANIObject *obj) { } void MovGraph::freeItems() { - warning("STUB: MovGraph::freeItems()"); + for (uint i = 0; i < _items.size(); i++) { + _items[i]->free(); + + _items[i]->movarr._movSteps.clear(); + } + + _items.clear(); } +Common::Array<MovItem *> *MovGraph::method28(StaticANIObject *ani, int x, int y, int flag1, int *rescount) { + *rescount = 0; + + if (_items.size() <= 0) + return 0; + + int idx = 0; -int MovGraph::method28() { - warning("STUB: MovGraph::method28()"); + while (_items[idx]->ani != ani) { + idx++; + + if (idx >= _items.size()) + return 0; + } + _items[idx]->free(); + + calcNodeDistancesAndAngles(); + + _items[idx]->movarr._movSteps.clear(); + + Common::Point point; + + point.x = ani->_ox; + point.y = ani->_oy; + + if (!calcChunk(idx, ani->_ox, ani->_oy, &_items[idx]->movarr, 0)) + findClosestLink(idx, &point, &_items[idx]->movarr); + + _items[idx]->count = 0; + + delete _items[idx]->movitems; + _items[idx]->movitems = 0; + + int arrSize; + Common::Array<MovArr *> *movarr = genMovArr(x, y, &arrSize, flag1, 0); + + if (movarr) { + for (int i = 0; i < arrSize; i++) { + int sz; + Common::Array<MovItem *> *movitems = calcMovItems(&_items[idx]->movarr, (*movarr)[i], &sz); + + if (sz > 0) { + for (uint j = 0; j < sz; j++) + _items[idx]->movitems->push_back(movitems[j]); + + delete movitems; + } + } + + delete movarr; + } + + if (_items[idx]->count) { + *rescount = _items[idx]->count; + + return _items[idx]->movitems; + } return 0; } -int MovGraph::method2C(StaticANIObject *obj, int x, int y) { +bool MovGraph::method2C(StaticANIObject *obj, int x, int y) { obj->setOXY(x, y); return method3C(obj, 1); } -MessageQueue *MovGraph::method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { - warning("STUB: MovGraph::method34()"); +MessageQueue *MovGraph::method34(StaticANIObject *ani, int xpos, int ypos, int fuzzyMatch, int staticsId) { + if (!ani) { + if (!_items.size()) + return 0; - return 0; -} + ani = _items[0]->ani; + } + + if (ABS(ani->_ox - xpos) < 50 && ABS(ani->_oy - ypos) < 50) + return 0; -int MovGraph::changeCallback() { - warning("STUB: MovGraph::changeCallback()"); + if (!ani->isIdle()) + return 0; - return 0; + if (ani->_flags & 0x100) + return 0; + + int count; + Common::Array<MovItem *> *movitems = method28(ani, xpos, ypos, fuzzyMatch, &count); + + if (!movitems) + return 0; + + if (ani->_movement) { + Common::Point point; + + ani->calcStepLen(&point); + + MessageQueue *mq = sub1(ani, ani->_ox - point.x, ani->_oy - point.y, ani->_movement->_staticsObj1->_staticsId, xpos, ypos, 0, fuzzyMatch); + + if (!mq || !mq->getExCommandByIndex(0)) + return 0; + + ExCommand *ex = mq->getExCommandByIndex(0); + + if ((ex->_messageKind != 1 && ex->_messageKind != 20) || ex->_messageNum != ani->_movement->_id || + (ex->_field_14 >= 1 && ex->_field_14 <= ani->_movement->_currDynamicPhaseIndex)) { + mq = new MessageQueue(g_fp->_globalMessageQueueList->compact()); + + ex = new ExCommand(ani->_id, 21, 0, 0, 0, 0, 1, 0, 0, 0); + ex->_keyCode = ani->_okeyCode; + ex->_field_3C = 1; + ex->_field_24 = 0; + mq->addExCommandToEnd(ex); + + ex = new ExCommand(ani->_id, 51, 0, xpos, ypos, 0, 1, 0, 0, 0); + ex->_keyCode = ani->_okeyCode; + ex->_field_3C = 1; + ex->_field_24 = 0; + ex->_field_20 = fuzzyMatch; + mq->addExCommandToEnd(ex); + + if (mq->chain(0)) + return mq; + + delete mq; + + return 0; + } + + int count2; + + ani->setSomeDynamicPhaseIndex(ex->_field_14); + method28(ani, xpos, ypos, fuzzyMatch, &count2); + + int idx = getItemIndexByStaticAni(ani); + count = _items[idx]->count; + movitems = _items[idx]->movitems; + } + + return method50(ani, _callback1(ani, movitems, count), staticsId); } -int MovGraph::method3C(StaticANIObject *ani, int flag) { - warning("STUB: MovGraph::method3C()"); +void MovGraph::changeCallback(MovArr *(*callback1)(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter)) { + _callback1 = callback1; +} - return 0; +bool MovGraph::method3C(StaticANIObject *ani, int flag) { + int idx = getItemIndexByStaticAni(ani); + + if (idx == -1) + return false; + + Common::Point point; + MovArr movarr; + + point.x = ani->_ox; + point.y = ani->_oy; + + findClosestLink(idx, &point, &movarr); + ani->setOXY(point.x, point.y); + + if (flag) { + Statics *st; + + if (ani->_statics) { + int t = _mgm.refreshOffsets(ani->_id, ani->_statics->_staticsId, movarr._link->_dwordArray2[_field_44]); + if (t > _mgm.refreshOffsets(ani->_id, ani->_statics->_staticsId, movarr._link->_dwordArray2[_field_44 + 1])) + st = ani->getStaticsById(movarr._link->_dwordArray2[_field_44 + 1]); + else + st = ani->getStaticsById(movarr._link->_dwordArray2[_field_44]); + } else { + ani->stopAnim_maybe(); + st = ani->getStaticsById(movarr._link->_dwordArray2[_field_44]); + } + + ani->_statics = st; + } + + return true; } -int MovGraph::method44() { - warning("STUB: MovGraph::method44()"); +bool MovGraph::method44(StaticANIObject *ani, int x, int y) { + int idx = getItemIndexByStaticAni(ani); + MovArr m; - return 0; + if (idx != -1) { + if (x != -1 || y != -1) { + int counter; + + Common::Array<MovItem *> *movitem = method28(ani, x, y, 0, &counter); + + if (movitem) { + MovArr *movarr = _callback1(ani, movitem, counter); + int cnt = movarr->_movStepCount; + + if (cnt > 0) { + if (movarr->_movSteps[cnt - 1]->link->_flags & 0x4000000) + return true; + } + } + } else if (calcChunk(idx, ani->_ox, ani->_oy, &m, 0) && m._link && (m._link->_flags & 0x4000000)) { + return true; + } + } + + return false; } MessageQueue *MovGraph::doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { - warning("STUB: MovGraph::doWalkTo()"); + PicAniInfo picAniInfo; + int ss; + + Common::Array<MovItem *> *movitem = method28(subj, xpos, ypos, fuzzyMatch, &ss); + + subj->getPicAniInfo(&picAniInfo); + + if (movitem) { + MovArr *goal = _callback1(subj, movitem, ss); + int idx = getItemIndexByStaticAni(subj); + + for (int i = 0; i < _items[idx]->count; i++) { + if ((*_items[idx]->movitems)[i]->movarr == goal) { + if (subj->_movement) { + Common::Point point; + + subj->calcStepLen(&point); + + MessageQueue *mq = sub1(subj, subj->_ox - point.x, subj->_oy - point.y, subj->_movement->_staticsObj1->_staticsId, xpos, ypos, 0, fuzzyMatch); + + if (!mq || !mq->getExCommandByIndex(0)) + return 0; + + ExCommand *ex = mq->getExCommandByIndex(0); + + if ((ex->_messageKind != 1 && ex->_messageKind != 20) || + ex->_messageNum != subj->_movement->_id || + (ex->_field_14 >= 1 && ex->_field_14 <= subj->_movement->_currDynamicPhaseIndex)) + subj->playIdle(); + } + } + } + } + + movitem = method28(subj, xpos, ypos, fuzzyMatch, &ss); + if (movitem) { + MovArr *goal = _callback1(subj, movitem, ss); + int idx = getItemIndexByStaticAni(subj); + + if (_items[idx]->count > 0) { + int arridx = 0; + + while ((*_items[idx]->movitems)[arridx]->movarr != goal) { + arridx++; + + if (arridx >= _items[idx]->count) { + subj->setPicAniInfo(&picAniInfo); + return 0; + } + } + + _items[idx]->movarr._movSteps.clear(); + _items[idx]->movarr = *(*_items[idx]->movitems)[arridx]->movarr; + _items[idx]->movarr._movSteps = (*_items[idx]->movitems)[arridx]->movarr->_movSteps; + _items[idx]->movarr._afield_8 = -1; + _items[idx]->movarr._link = 0; + + MessageQueue *mq = fillMGMinfo(_items[idx]->ani, &_items[idx]->movarr, staticsId); + if (mq) { + ExCommand *ex = new ExCommand(); + ex->_messageKind = 17; + ex->_messageNum = 54; + ex->_parentId = subj->_id; + ex->_field_3C = 1; + mq->addExCommandToEnd(ex); + } + subj->setPicAniInfo(&picAniInfo); + + return mq; + } + } + + subj->setPicAniInfo(&picAniInfo); return 0; } -int MovGraph::method50() { - warning("STUB: MovGraph::method50()"); +MessageQueue *MovGraph::sub1(StaticANIObject *ani, int x, int y, int stid, int x1, int y1, int stid2, int flag1) { + PicAniInfo picinfo; - return 0; + ani->getPicAniInfo(&picinfo); + + ani->_statics = ani->getStaticsById(stid); + ani->_movement = 0; + ani->setOXY(x, y); + + int rescount; + + Common::Array<MovItem *> *movitems = method28(ani, x1, y1, flag1, &rescount); + + if (!movitems) { + ani->setPicAniInfo(&picinfo); + + return 0; + } + + MessageQueue *res = 0; + + MovArr *goal = _callback1(ani, movitems, rescount); + int idx = getItemIndexByStaticAni(ani); + + MovGraphItem *movgitem = _items[idx]; + int cnt = movgitem->count; + + for (int nidx = 0; nidx < cnt; nidx++) { + if ((*movgitem->movitems)[nidx]->movarr == goal) { + movgitem->movarr._movSteps.clear(); + _items[idx]->movarr = *(*movgitem->movitems)[nidx]->movarr; + _items[idx]->movarr._movSteps = (*movgitem->movitems)[nidx]->movarr->_movSteps; + _items[idx]->movarr._afield_8 = -1; + _items[idx]->movarr._link = 0; + + res = fillMGMinfo(_items[idx]->ani, &_items[idx]->movarr, stid2); + } + } + + ani->setPicAniInfo(&picinfo); + + return res; +} + +MessageQueue *MovGraph::fillMGMinfo(StaticANIObject *ani, MovArr *movarr, int staticsId) { + if (!movarr->_movStepCount) + return 0; + + MessageQueue *mq = 0; + int ox = ani->_ox; + int oy = ani->_oy; + int id1 = 0; + int id2; + + for (int i = 0; i < movarr->_movStepCount; i++) { + while (i < movarr->_movStepCount - 1) { + if (movarr->_movSteps[i ]->link->_dwordArray1[movarr->_movSteps[i - 1]->sfield_0 + _field_44] != + movarr->_movSteps[i + 1]->link->_dwordArray1[movarr->_movSteps[i ]->sfield_0 + _field_44]) + break; + i++; + } + + MovStep *st = movarr->_movSteps[i]; + + ani->getMovementById(st->link->_dwordArray1[_field_44 + st->sfield_0]); + + if (i == movarr->_movStepCount - 1 && staticsId) { + id2 = staticsId; + } else { + if (i < movarr->_movStepCount - 1) + id2 = ani->getMovementById(movarr->_movSteps[i + 1]->link->_dwordArray1[_field_44 + st->sfield_0])->_staticsObj1->_staticsId; + else + id2 = st->link->_dwordArray2[_field_44 + st->sfield_0]; + } + + int nx, ny, nd; + + if (i == movarr->_movStepCount - 1) { + nx = movarr->_point.x; + ny = movarr->_point.y; + nd = st->link->_movGraphNode1->_distance; + } else { + if (st->sfield_0) { + nx = st->link->_movGraphNode1->_x; + ny = st->link->_movGraphNode1->_y; + nd = st->link->_movGraphNode1->_distance; + } else { + nx = st->link->_movGraphNode2->_x; + ny = st->link->_movGraphNode2->_y; + nd = st->link->_movGraphNode2->_distance; + } + } + + MGMInfo mgminfo; + + memset(&mgminfo, 0, sizeof(mgminfo)); + mgminfo.ani = ani; + mgminfo.staticsId2 = id2; + mgminfo.staticsId1 = id1; + mgminfo.x1 = nx; + mgminfo.x2 = ox; + mgminfo.y2 = oy; + mgminfo.y1 = ny; + mgminfo.field_1C = nd; + mgminfo.movementId = st->link->_dwordArray1[_field_44 + st->sfield_0]; + + mgminfo.flags = 0xe; + if (mq) + mgminfo.flags |= 0x31; + + MessageQueue *newmq = _mgm.genMovement(&mgminfo); + + if (mq) { + if (newmq) { + mq->transferExCommands(newmq); + + delete newmq; + } + } else { + mq = newmq; + } + + ox = nx; + oy = ny; + id1 = id2; + } + + return mq; +} + +MessageQueue *MovGraph::method50(StaticANIObject *ani, MovArr *movarr, int staticsId) { + if (_items.size() == 0) + return 0; + + uint idx; + int movidx; + bool done = false; + + for (idx = 0; idx <= _items.size() && !done; idx++) { + if (idx == _items.size()) + return 0; + + if (_items[idx]->ani == ani) { + if (!_items[idx]->movitems) + return 0; + + if (_items[idx]->count < 1) + return 0; + + for (movidx = 0; movidx < _items[idx]->count; movidx++) { + if ((*_items[idx]->movitems)[movidx]->movarr == movarr) { + done = true; + + break; + } + } + } + } + + _items[idx]->movarr._movSteps.clear(); + _items[idx]->movarr = *(*_items[idx]->movitems)[movidx]->movarr; + _items[idx]->movarr._movSteps = (*_items[idx]->movitems)[movidx]->movarr->_movSteps; + _items[idx]->movarr._afield_8 = -1; + _items[idx]->movarr._link = 0; + + MessageQueue *mq = fillMGMinfo(_items[idx]->ani, &_items[idx]->movarr, 0); + + if (!mq) + return 0; + + ExCommand *ex = new ExCommand(); + + ex->_messageKind = 17; + ex->_messageNum = 54; + ex->_parentId = ani->_id; + ex->_field_3C = 1; + mq->addExCommandToEnd(ex); + + if (!mq->chain(ani)) { + delete mq; + + return 0; + } + + return mq; } double MovGraph::calcDistance(Common::Point *point, MovGraphLink *link, int fuzzyMatch) { @@ -660,6 +1164,61 @@ void MovGraph::calcNodeDistancesAndAngles() { } } +bool MovGraph::findClosestLink(int unusedArg, Common::Point *p, MovArr *movarr) { + MovGraphLink *link = 0; + double mindist = 1.0e20; + int resx = 0, resy = 0; + + for (ObList::iterator i = _links.begin(); i != _links.end(); ++i) { + MovGraphLink *lnk = (MovGraphLink *)*i; + + if ((lnk->_flags & 0x10000000) && !(lnk->_flags & 0x20000000) ) { + double dx1 = lnk->_movGraphNode1->_x - p->x; + double dy1 = lnk->_movGraphNode1->_y - p->y; + double dx2 = lnk->_movGraphNode2->_x - p->x; + double dy2 = lnk->_movGraphNode2->_y - p->y; + double dx3 = lnk->_movGraphNode2->_x - lnk->_movGraphNode1->_x; + double dy3 = lnk->_movGraphNode2->_y - lnk->_movGraphNode1->_y; + double sq1 = sqrt(dy1 * dy1 + dx1 * dx1); + double sdist = (dy3 * dy1 + dx3 * dx1) / lnk->_distance / sq1; + double ldist = sdist * sq1; + double dist = sqrt(1.0 - sdist * sdist) * sq1; + + if (ldist < 0.0) { + ldist = 0.0; + dist = sqrt(dx1 * dx1 + dy1 * dy1); + } + + if (ldist > lnk->_distance) { + ldist = lnk->_distance; + dist = sqrt(dx2 * dx2 + dy2 * dy2); + } + + if (ldist >= 0.0 && ldist <= lnk->_distance && dist < mindist) { + resx = lnk->_movGraphNode1->_x + (int)(dx3 * ldist / lnk->_distance); + resy = lnk->_movGraphNode1->_y + (int)(dy3 * ldist / lnk->_distance); + + mindist = dist; + link = lnk; + } + } + } + + if (mindist < 1.0e20) { + if (movarr) + movarr->_link = link; + + if (p) { + p->x = resx; + p->y = resy; + } + + return true; + } + + return false; +} + int MovGraph::getItemIndexByStaticAni(StaticANIObject *ani) { for (uint i = 0; i < _items.size(); i++) if (_items[i]->ani == ani) @@ -668,6 +1227,209 @@ int MovGraph::getItemIndexByStaticAni(StaticANIObject *ani) { return -1; } +Common::Array<MovArr *> *MovGraph::genMovArr(int x, int y, int *arrSize, int flag1, int flag2) { + if (!_links.size()) { + *arrSize = 0; + + return 0; + } + + Common::Array<MovArr *> *arr = new Common::Array<MovArr *>; + MovArr *movarr; + + for (ObList::iterator i = _links.begin(); i != _links.end(); ++i) { + MovGraphLink *lnk = (MovGraphLink *)*i; + + if (flag1) { + Common::Point point(x, y); + double dist = calcDistance(&point, lnk, 0); + + if (dist >= 0.0 && dist < 2.0) { + movarr = new MovArr; + + movarr->_link = lnk; + movarr->_dist = ((double)(lnk->_movGraphNode1->_y - lnk->_movGraphNode2->_y) * (double)(lnk->_movGraphNode1->_y - point.y) + + (double)(lnk->_movGraphNode2->_x - lnk->_movGraphNode1->_x) * (double)(point.x - lnk->_movGraphNode1->_x)) / + lnk->_distance / lnk->_distance; + movarr->_point = point; + + arr->push_back(movarr); + } + } else { + if (lnk->_movGraphReact) { + if (lnk->_movGraphReact->pointInRegion(x, y)) { + if (!(lnk->_flags & 0x10000000) || lnk->_flags & 0x20000000) { + if (!flag2) { + movarr = new MovArr; + movarr->_link = lnk; + movarr->_dist = 0.0; + movarr->_point.x = lnk->_movGraphNode1->_x; + movarr->_point.y = lnk->_movGraphNode1->_y; + arr->push_back(movarr); + + movarr = new MovArr; + movarr->_link = lnk; + movarr->_dist = 1.0; + movarr->_point.x = lnk->_movGraphNode1->_x; + movarr->_point.y = lnk->_movGraphNode1->_y; + arr->push_back(movarr); + } + } else { + movarr = new MovArr; + movarr->_link = lnk; + movarr->_dist = ((double)(lnk->_movGraphNode1->_y - lnk->_movGraphNode2->_y) * (double)(lnk->_movGraphNode1->_y - y) + + (double)(lnk->_movGraphNode2->_x - lnk->_movGraphNode1->_x) * (double)(x - lnk->_movGraphNode1->_x)) / + lnk->_distance / lnk->_distance; + movarr->_point.x = x; + movarr->_point.y = y; + + calcDistance(&movarr->_point, lnk, 0); + + arr->push_back(movarr); + } + } + } + } + } + + *arrSize = arr->size(); + + return arr; +} + +void MovGraph::shuffleTree(MovGraphLink *lnk, MovGraphLink *lnk2, Common::Array<MovGraphLink *> &tempObList1, Common::Array<MovGraphLink *> &tempObList2) { + if (lnk == lnk2) { + for (uint i = 0; i < tempObList1.size(); i++) + tempObList2.push_back(tempObList1[i]); + + tempObList2.push_back(lnk); + } else { + lnk->_flags |= 0x80000000; + + tempObList1.push_back(lnk); + + for (ObList::iterator i = _links.begin(); i != _links.end(); ++i) { + MovGraphLink *l = (MovGraphLink *)*i; + + if (l->_movGraphNode1 != lnk->_movGraphNode1) { + if (l->_movGraphNode2 != lnk->_movGraphNode1) { + if (l->_movGraphNode1 != lnk->_movGraphNode2 && l->_movGraphNode2 != lnk->_movGraphNode2) + continue; + } + } + + if (!(l->_flags & 0xA0000000)) + shuffleTree(l, lnk2, tempObList1, tempObList2); + } + + lnk->_flags &= 0x7FFFFFFF; + } +} + +Common::Array<MovItem *> *MovGraph::calcMovItems(MovArr *movarr1, MovArr *movarr2, int *listCount) { + Common::Array<MovGraphLink *> tempObList1; + Common::Array<MovGraphLink *> tempObList2; + + shuffleTree(movarr1->_link, movarr2->_link, tempObList1, tempObList2); + + *listCount = 0; + + if (!tempObList2.size()) + return 0; + + *listCount = tempObList2.size(); + + Common::Array<MovItem *> *res = new Common::Array<MovItem *>; + + for (int i = 0; i < *listCount; i++) { + MovItem *r = new MovItem; + + genMovItem(r, tempObList2[i], movarr1, movarr2); + + delete tempObList2[i]; + } + + movarr2->_link = movarr1->_link; + + return res; +} + +void MovGraph::genMovItem(MovItem *movitem, MovGraphLink *grlink, MovArr *movarr1, MovArr *movarr2) { + warning("STUB: MovGraph::genMovItem()"); +} + +bool MovGraph::calcChunk(int idx, int x, int y, MovArr *arr, int a6) { + int staticsId; + + if (_items[idx]->ani->_statics) { + staticsId = _items[idx]->ani->_statics->_staticsId; + } else { + if (!_items[idx]->ani->_movement->_staticsObj2) + return 0; + + staticsId = _items[idx]->ani->_movement->_staticsObj2->_staticsId; + } + + int arrSize; + + Common::Array<MovArr *> *movarr = genMovArr(x, y, &arrSize, 0, 1); + + if (!movarr) + return findClosestLink(idx, 0, arr); + + bool res = false; + + int idxmin = -1; + int offmin = 100; + + for (int i = 0; i < arrSize; i++) { + int off = _mgm.refreshOffsets(_items[idx]->ani->_id, staticsId, (*movarr)[i]->_link->_dwordArray2[_field_44]); + + if (off < offmin) { + offmin = off; + idxmin = i; + } + + off = _mgm.refreshOffsets(_items[idx]->ani->_id, staticsId, (*movarr)[i]->_link->_dwordArray2[_field_44 + 1]); + if (off < offmin) { + offmin = off; + idxmin = i; + } + } + + if (idxmin != -1) { + *arr = *(*movarr)[idxmin]; + + res = true; + } + + delete movarr; + + return res; +} + +void MovGraph::setEnds(MovStep *step1, MovStep *step2) { + if (step1->link->_movGraphNode1 == step2->link->_movGraphNode2) { + step1->sfield_0 = 1; + step2->sfield_0 = 1; + + return; + } + + if (step1->link->_movGraphNode1 == step2->link->_movGraphNode1) { + step1->sfield_0 = 1; + step2->sfield_0 = 0; + } else { + step1->sfield_0 = 0; + + if (step1->link->_movGraphNode2 != step2->link->_movGraphNode1) { + step2->sfield_0 = 1; + } else { + step2->sfield_0 = 0; + } + } +} + int MovGraph2::getItemIndexByGameObjectId(int objectId) { for (uint i = 0; i < _items2.size(); i++) if (_items2[i]->_objectId == objectId) @@ -1089,7 +1851,10 @@ int MovGraph2::removeObject(StaticANIObject *obj) { } void MovGraph2::freeItems() { - warning("STUB: MovGraph2::freeItems()"); + for (uint i = 0; i < _items2.size(); i++) + delete _items2[i]; + + _items2.clear(); } MessageQueue *MovGraph2::method34(StaticANIObject *ani, int xpos, int ypos, int fuzzyMatch, int staticsId) { @@ -1140,6 +1905,8 @@ MessageQueue *MovGraph2::doWalkTo(StaticANIObject *obj, int xpos, int ypos, int PicAniInfo picAniInfo; Common::Point point; + debug(0, "MovGraph2::doWalkTo(%d, %d, %d, %d, %d)", obj->_id, xpos, ypos, fuzzyMatch, staticsId); + int idx = getItemIndexByGameObjectId(obj->_id); if (idx < 0) @@ -2528,7 +3295,10 @@ MovGraphLink::MovGraphLink() { } MovGraphLink::~MovGraphLink() { - warning("STUB: MovGraphLink::~MovGraphLink()"); + delete _movGraphReact; + + _dwordArray1.clear(); + _dwordArray2.clear(); } @@ -2764,26 +3534,26 @@ bool MovGraphReact::pointInRegion(int x, int y) { } } -int startWalkTo(int objId, int objKey, int x, int y, int a5) { - MctlCompound *mc = getSc2MctlCompoundBySceneId(g_fp->_currentScene->_sceneId); +int startWalkTo(int objId, int objKey, int x, int y, int fuzzyMatch) { + MctlCompound *mc = getCurrSceneSc2MotionController(); if (mc) - return (mc->method34(g_fp->_currentScene->getStaticANIObject1ById(objId, objKey), x, y, a5, 0) != 0); + return (mc->method34(g_fp->_currentScene->getStaticANIObject1ById(objId, objKey), x, y, fuzzyMatch, 0) != 0); return 0; } -int doSomeAnimation(int objId, int objKey, int a3) { +bool doSomeAnimation(int objId, int objKey, int a3) { StaticANIObject *ani = g_fp->_currentScene->getStaticANIObject1ById(objId, objKey); MctlCompound *cmp = getCurrSceneSc2MotionController(); if (ani && cmp) return cmp->method3C(ani, a3); - return 0; + return false; } -int doSomeAnimation2(int objId, int objKey) { +bool doSomeAnimation2(int objId, int objKey) { return doSomeAnimation(objId, objKey, 0); } diff --git a/engines/fullpipe/motion.h b/engines/fullpipe/motion.h index 4d92fd7fed..2b40791340 100644 --- a/engines/fullpipe/motion.h +++ b/engines/fullpipe/motion.h @@ -31,10 +31,12 @@ class MctlConnectionPoint; class MovGraphLink; class MessageQueue; class ExCommand2; +struct MovArr; +struct MovItem; int startWalkTo(int objId, int objKey, int x, int y, int a5); -int doSomeAnimation(int objId, int objKey, int a3); -int doSomeAnimation2(int objId, int objKey); +bool doSomeAnimation(int objId, int objKey, int a3); +bool doSomeAnimation2(int objId, int objKey); class MotionController : public CObject { public: @@ -52,14 +54,14 @@ public: virtual void addObject(StaticANIObject *obj) {} virtual int removeObject(StaticANIObject *obj) { return 0; } virtual void freeItems() {} - virtual int method28() { return 0; } - virtual int method2C(StaticANIObject *obj, int x, int y) { return 0; } + virtual Common::Array<MovItem *> *method28(StaticANIObject *ani, int x, int y, int flag1, int *rescount) { return 0; } + virtual bool method2C(StaticANIObject *obj, int x, int y) { return false; } virtual int method30() { return 0; } virtual MessageQueue *method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { return 0; } - virtual int changeCallback() { return 0; } - virtual int method3C(StaticANIObject *ani, int flag) { return 0; } + virtual void changeCallback(MovArr *(*_callback1)(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter)) {} + virtual bool method3C(StaticANIObject *ani, int flag) { return 0; } virtual int method40() { return 0; } - virtual int method44() { return 0; } + virtual bool method44(StaticANIObject *ani, int x, int y) { return false; } virtual int method48() { return -1; } virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { return 0; } @@ -115,7 +117,7 @@ public: virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId); void initMovGraph2(); - MctlConnectionPoint *findClosestConnectionPoint(int ox, int oy, int destIndex, int connectionX, int connectionY, int sourceIndex, int *minDistancePtr); + MctlConnectionPoint *findClosestConnectionPoint(int ox, int oy, int destIndex, int connectionX, int connectionY, int sourceIndex, double *minDistancePtr); void replaceNodeX(int from, int to); uint getMotionControllerCount() { return _motionControllers.size(); } @@ -299,18 +301,32 @@ class MovGraphLink : public CObject { void calcNodeDistanceAndAngle(); }; +struct MovStep { + int sfield_0; + MovGraphLink *link; +}; + +struct MovArr { + Common::Array<MovStep *> _movSteps; + int _movStepCount; + int _afield_8; + MovGraphLink *_link; + double _dist; + Common::Point _point; +}; + +struct MovItem { + MovArr *movarr; + int _mfield_4; + int _mfield_8; + int _mfield_C; +}; + struct MovGraphItem { StaticANIObject *ani; int field_4; - int field_8; - int field_C; - int field_10; - int field_14; - int field_18; - int field_1C; - int field_20; - int field_24; - int items; + MovArr movarr; + Common::Array<MovItem *> *movitems; int count; int field_30; int field_34; @@ -318,6 +334,7 @@ struct MovGraphItem { int field_3C; MovGraphItem(); + void free(); }; class MovGraph : public MotionController { @@ -326,7 +343,7 @@ public: ObList _links; int _field_44; Common::Array<MovGraphItem *> _items; - int (*_callback1)(int, int, int); + MovArr *(*_callback1)(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter); MGM _mgm; public: @@ -338,19 +355,28 @@ public: virtual void addObject(StaticANIObject *obj); virtual int removeObject(StaticANIObject *obj); virtual void freeItems(); - virtual int method28(); - virtual int method2C(StaticANIObject *obj, int x, int y); + virtual Common::Array<MovItem *> *method28(StaticANIObject *ani, int x, int y, int flag1, int *rescount); + virtual bool method2C(StaticANIObject *obj, int x, int y); virtual MessageQueue *method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId); - virtual int changeCallback(); - virtual int method3C(StaticANIObject *ani, int flag); - virtual int method44(); + virtual void changeCallback(MovArr *(*_callback1)(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter)); + virtual bool method3C(StaticANIObject *ani, int flag); + virtual bool method44(StaticANIObject *ani, int x, int y); virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId); - virtual int method50(); + virtual MessageQueue *method50(StaticANIObject *ani, MovArr *movarr, int staticsId); double calcDistance(Common::Point *point, MovGraphLink *link, int fuzzyMatch); void calcNodeDistancesAndAngles(); + bool findClosestLink(int unusedArg, Common::Point *p, MovArr *movarr); MovGraphNode *calcOffset(int ox, int oy); int getItemIndexByStaticAni(StaticANIObject *ani); + Common::Array<MovArr *> *genMovArr(int x, int y, int *arrSize, int flag1, int flag2); + void shuffleTree(MovGraphLink *lnk, MovGraphLink *lnk2, Common::Array<MovGraphLink *> &tempObList1, Common::Array<MovGraphLink *> &tempObList2); + Common::Array<MovItem *> *calcMovItems(MovArr *movarr1, MovArr *movarr2, int *listCount); + void genMovItem(MovItem *movitem, MovGraphLink *grlink, MovArr *movarr1, MovArr *movarr2); + bool calcChunk(int idx, int x, int y, MovArr *arr, int a6); + MessageQueue *sub1(StaticANIObject *ani, int x, int y, int a5, int x1, int y1, int a8, int a9); + MessageQueue *fillMGMinfo(StaticANIObject *ani, MovArr *movarr, int staticsId); + void setEnds(MovStep *step1, MovStep *step2); }; class Movement; diff --git a/engines/fullpipe/scene.cpp b/engines/fullpipe/scene.cpp index 462401b3b2..1247d9380e 100644 --- a/engines/fullpipe/scene.cpp +++ b/engines/fullpipe/scene.cpp @@ -133,7 +133,27 @@ Scene::Scene() { } Scene::~Scene() { - warning("STUB: Scene::~Scene()"); + delete _soundList; + delete _shadows; + delete _palette; + + // _faObjlist is not used + + for (uint i = 0; i < _messageQueueList.size(); i++) + delete _messageQueueList[i]; + + _messageQueueList.clear(); + + for (uint i = 0; i < _staticANIObjectList1.size(); i++) + delete _staticANIObjectList1[i]; + + _staticANIObjectList1.clear(); + + delete _libHandle; + + // delete _field_BC; + + free(_sceneName); } bool Scene::load(MfcArchive &file) { @@ -249,7 +269,7 @@ bool Scene::load(MfcArchive &file) { void Scene::initStaticANIObjects() { for (uint i = 0; i < _staticANIObjectList1.size(); i++) - ((StaticANIObject *)_staticANIObjectList1[i])->initMovements(); + _staticANIObjectList1[i]->initMovements(); } void Scene::init() { @@ -262,13 +282,13 @@ void Scene::init() { ((PictureObject *)_picObjList[i])->clearFlags(); for (uint i = 0; i < _staticANIObjectList1.size(); i++) - ((StaticANIObject *)_staticANIObjectList1[i])->clearFlags(); + _staticANIObjectList1[i]->clearFlags(); if (_staticANIObjectList2.size() != _staticANIObjectList1.size()) { _staticANIObjectList2.clear(); - for (PtrList::iterator s = _staticANIObjectList1.begin(); s != _staticANIObjectList1.end(); ++s) - _staticANIObjectList2.push_back(*s); + for (uint i = 0; i < _staticANIObjectList1.size(); i++) + _staticANIObjectList2.push_back(_staticANIObjectList1[i]); } } @@ -281,35 +301,33 @@ StaticANIObject *Scene::getAniMan() { } StaticANIObject *Scene::getStaticANIObject1ById(int obj, int a3) { - for (PtrList::iterator s = _staticANIObjectList1.begin(); s != _staticANIObjectList1.end(); ++s) { - StaticANIObject *o = (StaticANIObject *)*s; - if (o->_id == obj && (a3 == -1 || o->_okeyCode == a3)) - return o; + for (uint i = 0; i < _staticANIObjectList1.size(); i++) { + if (_staticANIObjectList1[i]->_id == obj && (a3 == -1 || _staticANIObjectList1[i]->_okeyCode == a3)) + return _staticANIObjectList1[i]; } return 0; } StaticANIObject *Scene::getStaticANIObject1ByName(char *name, int a3) { - for (uint n = 0; n < _staticANIObjectList1.size(); n++) { - StaticANIObject *o = (StaticANIObject *)_staticANIObjectList1[n]; - if (!strcmp(o->_objectName, name) && (a3 == -1 || o->_okeyCode == a3)) - return o; + for (uint i = 0; i < _staticANIObjectList1.size(); i++) { + if (!strcmp(_staticANIObjectList1[i]->_objectName, name) && (a3 == -1 || _staticANIObjectList1[i]->_okeyCode == a3)) + return _staticANIObjectList1[i]; } return 0; } void Scene::deleteStaticANIObject(StaticANIObject *obj) { - for (uint n = 0; n < _staticANIObjectList1.size(); n++) - if ((StaticANIObject *)_staticANIObjectList1[n] == obj) { - _staticANIObjectList1.remove_at(n); + for (uint i = 0; i < _staticANIObjectList1.size(); i++) + if (_staticANIObjectList1[i] == obj) { + _staticANIObjectList1.remove_at(i); break; } - for (uint n = 0; n < _staticANIObjectList2.size(); n++) - if ((StaticANIObject *)_staticANIObjectList2[n] == obj) { - _staticANIObjectList2.remove_at(n); + for (uint i = 0; i < _staticANIObjectList2.size(); i++) + if (_staticANIObjectList2[i] == obj) { + _staticANIObjectList2.remove_at(i); break; } } @@ -335,11 +353,12 @@ void Scene::setPictureObjectsFlag4() { } void Scene::stopAllSounds() { - warning("STUB: Scene:stopAllSounds()"); + for (int i = 0; i < _soundList->getCount(); i++) + _soundList->getSoundByIndex(i)->stop(); } PictureObject *Scene::getPictureObjectById(int objId, int flags) { - for (uint i = 0; i < _picObjList.size(); i++) { + for (uint i = 1; i < _picObjList.size(); i++) { if (((PictureObject *)_picObjList[i])->_id == objId && ((PictureObject *)_picObjList[i])->_okeyCode == flags) return (PictureObject *)_picObjList[i]; } @@ -369,16 +388,16 @@ void Scene::deletePictureObject(PictureObject *obj) { MessageQueue *Scene::getMessageQueueById(int messageId) { for (uint i = 0; i < _messageQueueList.size(); i++) - if (((MessageQueue *)_messageQueueList[i])->_dataId == messageId) - return (MessageQueue *)_messageQueueList[i]; + if (_messageQueueList[i]->_dataId == messageId) + return _messageQueueList[i]; return 0; } MessageQueue *Scene::getMessageQueueByName(char *name) { for (uint i = 0; i < _messageQueueList.size(); i++) - if (!strcmp(((MessageQueue *)_messageQueueList[i])->_queueName, name)) - return (MessageQueue *)_messageQueueList[i]; + if (!strcmp(_messageQueueList[i]->_queueName, name)) + return _messageQueueList[i]; return 0; } @@ -447,15 +466,27 @@ void Scene::initObjectCursors(const char *varname) { } bool Scene::compareObjPriority(const void *p1, const void *p2) { - if (((const StaticANIObject *)p1)->_priority > ((const StaticANIObject *)p2)->_priority) + if (((const GameObject *)p1)->_priority > ((const GameObject *)p2)->_priority) return true; return false; } -void Scene::objectList_sortByPriority(PtrList &list, bool skipFirst) { +void Scene::objectList_sortByPriority(Common::Array<StaticANIObject *> &list, bool skipFirst) { if (skipFirst) { - PtrList::iterator s = list.begin(); + Common::Array<StaticANIObject *>::iterator s = list.begin(); + + ++s; + + Common::sort(s, list.end(), Scene::compareObjPriority); + } else { + Common::sort(list.begin(), list.end(), Scene::compareObjPriority); + } +} + +void Scene::objectList_sortByPriority(Common::Array<PictureObject *> &list, bool skipFirst) { + if (skipFirst) { + Common::Array<PictureObject *>::iterator s = list.begin(); ++s; @@ -476,16 +507,15 @@ void Scene::draw() { objectList_sortByPriority(_staticANIObjectList2); - for (PtrList::iterator s = _staticANIObjectList2.begin(); s != _staticANIObjectList2.end(); ++s) { - ((StaticANIObject *)*s)->draw2(); - } + for (uint i = 0; i < _staticANIObjectList2.size(); i++) + _staticANIObjectList2[i]->draw2(); int priority = -1; - for (PtrList::iterator s = _staticANIObjectList2.begin(); s != _staticANIObjectList2.end(); ++s) { - drawContent(((StaticANIObject *)*s)->_priority, priority, false); - ((StaticANIObject *)*s)->draw(); + for (uint i = 0; i < _staticANIObjectList2.size(); i++) { + drawContent(_staticANIObjectList2[i]->_priority, priority, false); + _staticANIObjectList2[i]->draw(); - priority = ((StaticANIObject *)*s)->_priority; + priority = _staticANIObjectList2[i]->_priority; } drawContent(-1, priority, false); @@ -566,7 +596,7 @@ StaticANIObject *Scene::getStaticANIObjectAtPos(int x, int y) { StaticANIObject *res = 0; for (uint i = 0; i < _staticANIObjectList1.size(); i++) { - StaticANIObject *p = (StaticANIObject *)_staticANIObjectList1[i]; + StaticANIObject *p = _staticANIObjectList1[i]; int pixel; if ((p->_field_8 & 0x100) && (p->_flags & 4) && @@ -612,8 +642,8 @@ int Scene::getPictureObjectIdAtPos(int x, int y) { void Scene::update(int counterdiff) { debug(6, "Scene::update(%d)", counterdiff); - for (PtrList::iterator s = _staticANIObjectList2.begin(); s != _staticANIObjectList2.end(); ++s) - ((StaticANIObject *)*s)->update(counterdiff); + for (uint i = 0; i < _staticANIObjectList2.size(); i++) + _staticANIObjectList2[i]->update(counterdiff); } void Scene::drawContent(int minPri, int maxPri, bool drawBg) { diff --git a/engines/fullpipe/scene.h b/engines/fullpipe/scene.h index 8306974f7b..1e2dae81fe 100644 --- a/engines/fullpipe/scene.h +++ b/engines/fullpipe/scene.h @@ -31,10 +31,10 @@ class MessageQueue; class Scene : public Background { public: - PtrList _staticANIObjectList1; - PtrList _staticANIObjectList2; - PtrList _messageQueueList; - PtrList _faObjectList; + Common::Array<StaticANIObject *> _staticANIObjectList1; + Common::Array<StaticANIObject *> _staticANIObjectList2; + Common::Array<MessageQueue *> _messageQueueList; + // PtrList _faObjectList; // not used Shadows *_shadows; SoundList *_soundList; int16 _sceneId; @@ -82,7 +82,8 @@ class Scene : public Background { private: static bool compareObjPriority(const void *p1, const void *p2); - void objectList_sortByPriority(PtrList &list, bool skipFirst = false); + void objectList_sortByPriority(Common::Array<StaticANIObject *> &list, bool skipFirst = false); + void objectList_sortByPriority(Common::Array<PictureObject *> &list, bool skipFirst = false); }; class SceneTag : public CObject { diff --git a/engines/fullpipe/scenes.cpp b/engines/fullpipe/scenes.cpp index 7420c1b1cf..b346bf3a17 100644 --- a/engines/fullpipe/scenes.cpp +++ b/engines/fullpipe/scenes.cpp @@ -590,10 +590,8 @@ bool FullpipeEngine::sceneSwitcher(EntranceInfo *entrance) { scene->setPictureObjectsFlag4(); - for (PtrList::iterator s = scene->_staticANIObjectList1.begin(); s != scene->_staticANIObjectList1.end(); ++s) { - StaticANIObject *o = (StaticANIObject *)*s; - o->setFlags(o->_flags & 0xFE7F); - } + for (uint i = 0; i < scene->_staticANIObjectList1.size(); i++) + scene->_staticANIObjectList1[i]->_flags &= 0xFE7F; PictureObject *p = accessScene(SC_INV)->getPictureObjectById(PIC_INV_MENU, 0); p->setFlags(p->_flags & 0xFFFB); @@ -1456,9 +1454,28 @@ void BallChain::init(Ball **ball) { } Ball *BallChain::sub04(Ball *ballP, Ball *ballN) { - warning("STUB: BallChain::sub04"); + if (!pTail) { + cPlex = (byte *)calloc(cPlexLen, sizeof(Ball)); + + Ball *runPtr = (Ball *)&cPlex[(cPlexLen - 1) * sizeof(Ball)]; + + for (int i = 0; i < cPlexLen; i++) { + runPtr->p0 = pTail; + pTail = runPtr; + + runPtr -= sizeof(Ball); + } + } + + Ball *res = pTail; + + pTail = res->p0; + res->p1 = ballP; + res->p0 = ballN; + numBalls++; + res->ani = 0; - return pTail; + return res; } void BallChain::removeBall(Ball *ball) { diff --git a/engines/fullpipe/sound.cpp b/engines/fullpipe/sound.cpp index 3c13bad854..65c9bf84ca 100644 --- a/engines/fullpipe/sound.cpp +++ b/engines/fullpipe/sound.cpp @@ -27,6 +27,8 @@ #include "fullpipe/sound.h" #include "fullpipe/ngiarchive.h" #include "fullpipe/messages.h" +#include "fullpipe/statics.h" + #include "common/memstream.h" #include "audio/audiostream.h" #include "audio/decoders/vorbis.h" @@ -132,7 +134,75 @@ void Sound::updateVolume() { } void Sound::setPanAndVolumeByStaticAni() { - debug(3, "STUB Sound::setPanAndVolumeByStaticAni()"); + if (!_objectId) + return; + + StaticANIObject *ani = g_fp->_currentScene->getStaticANIObject1ById(_objectId, -1); + if (!ani) + return; + + int a, b; + + if (ani->_ox >= g_fp->_sceneRect.left) { + int par, pan; + + if (ani->_ox <= g_fp->_sceneRect.right) { + int dx; + + if (ani->_oy <= g_fp->_sceneRect.bottom) { + if (ani->_oy >= g_fp->_sceneRect.top) { + setPanAndVolume(g_fp->_sfxVolume, 0); + + return; + } + dx = g_fp->_sceneRect.top - ani->_oy; + } else { + dx = ani->_oy - g_fp->_sceneRect.bottom; + } + + par = 0; + + if (dx > 800) { + setPanAndVolume(-3500, 0); + return; + } + + pan = -3500; + a = g_fp->_sfxVolume - (-3500); + b = 800 - dx; + } else { + int dx = ani->_ox - g_fp->_sceneRect.right; + + if (dx > 800) { + setPanAndVolume(-3500, 0); + return; + } + + pan = -3500; + par = dx * (-3500) / -800; + a = g_fp->_sfxVolume - (-3500); + b = 800 - dx; + } + + int32 pp = b * a; + + setPanAndVolume(pan + pp / 800, par); + + return; + } + + int dx = g_fp->_sceneRect.left - ani->_ox; + if (dx <= 800) { + int32 s = (800 - dx) * (g_fp->_sfxVolume - (-3500)); + int32 p = -3500 + s / 800; + + if (p > g_fp->_sfxVolume) + p = g_fp->_sfxVolume; + + setPanAndVolume(p, dx * (-3500) / 800); + } else { + setPanAndVolume(-3500, 0); + } } void Sound::setPanAndVolume(int vol, int pan) { @@ -298,8 +368,12 @@ void FullpipeEngine::startSoundStream1(char *trackName) { } void FullpipeEngine::stopAllSounds() { - // TODO: Differences from stopAllSoundStreams() - _mixer->stopAll(); + // _mixer->stopAll(); + + for (int i = 0; i < _currSoundListCount; i++) + for (int j = 0; j < _currSoundList1[i]->getCount(); j++) { + _currSoundList1[i]->getSoundByIndex(j)->stop(); + } } void FullpipeEngine::toggleMute() { @@ -447,7 +521,7 @@ void FullpipeEngine::updateSoundVolume() { void FullpipeEngine::setMusicVolume(int vol) { _musicVolume = vol; - debug(3, "STUB FullpipeEngine::setMusicVolume()"); + g_fp->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, vol); } } // End of namespace Fullpipe diff --git a/engines/fullpipe/stateloader.cpp b/engines/fullpipe/stateloader.cpp index e36b196517..41641457d3 100644 --- a/engines/fullpipe/stateloader.cpp +++ b/engines/fullpipe/stateloader.cpp @@ -55,9 +55,8 @@ bool FullpipeEngine::loadGam(const char *fname, int scene) { _inventory->rebuildItemRects(); - for (PtrList::iterator p = _inventory->getScene()->_picObjList.begin(); p != _inventory->getScene()->_picObjList.end(); ++p) { - ((MemoryObject *)((PictureObject *)*p)->_picture)->load(); - } + for (uint i = 0; i < _inventory->getScene()->_picObjList.size(); i++) + ((MemoryObject *)_inventory->getScene()->_picObjList[i]->_picture)->load(); // _sceneSwitcher = sceneSwitcher; // substituted with direct call _gameLoader->_preloadCallback = preloadCallback; diff --git a/engines/fullpipe/statics.cpp b/engines/fullpipe/statics.cpp index f1abac5778..b6b312ab85 100644 --- a/engines/fullpipe/statics.cpp +++ b/engines/fullpipe/statics.cpp @@ -141,7 +141,17 @@ StaticANIObject::StaticANIObject() { } StaticANIObject::~StaticANIObject() { - warning("STUB: StaticANIObject::~StaticANIObject()"); + for (uint i = 0; i < _staticsList.size(); i++) + delete _staticsList[i]; + + _staticsList.clear(); + + for (uint i = 0; i < _movements.size(); i++) + delete _movements[i]; + + _movements.clear(); + + g_fp->_mgm->clear(); } StaticANIObject::StaticANIObject(StaticANIObject *src) : GameObject(src) { @@ -164,22 +174,21 @@ StaticANIObject::StaticANIObject(StaticANIObject *src) : GameObject(src) { _objtype = kObjTypeStaticANIObject; for (uint i = 0; i < src->_staticsList.size(); i++) - _staticsList.push_back(new Statics((Statics *)src->_staticsList[i], 0)); + _staticsList.push_back(new Statics(src->_staticsList[i], 0)); _movement = 0; _statics = 0; for (uint i = 0; i < src->_movements.size(); i++) { Movement *newmov; - Movement *mov = (Movement *)src->_movements[i]; - if (mov->_currMovement) { + if (src->_movements[i]->_currMovement) { // WORKAROUND: Original uses weird construction here: // new Movement(getMovementById(src->getMovementIdById(mov->_id)), this); - newmov = new Movement(src->getMovementById(src->getMovementIdById(mov->_id)), this); - newmov->_id = mov->_id; + newmov = new Movement(src->getMovementById(src->getMovementIdById(src->_movements[i]->_id)), this); + newmov->_id = src->_movements[i]->_id; } else { - newmov = new Movement(mov, 0, -1, this); + newmov = new Movement(src->_movements[i], 0, -1, this); } _movements.push_back(newmov); @@ -224,7 +233,7 @@ bool StaticANIObject::load(MfcArchive &file) { Common::Point pt; if (count) { // We have movements - ((Movement *)_movements[0])->getCurrDynamicPhaseXY(pt); + _movements[0]->getCurrDynamicPhaseXY(pt); } else { pt.x = pt.y = 100; } @@ -392,34 +401,36 @@ bool StaticANIObject::isIdle() { Statics *StaticANIObject::getStaticsById(int itemId) { for (uint i = 0; i < _staticsList.size(); i++) - if (((Statics *)_staticsList[i])->_staticsId == itemId) - return (Statics *)_staticsList[i]; + if (_staticsList[i]->_staticsId == itemId) + return _staticsList[i]; return 0; } Statics *StaticANIObject::getStaticsByName(char *name) { for (uint i = 0; i < _staticsList.size(); i++) - if (!strcmp(((Statics *)_staticsList[i])->_staticsName, name)) - return (Statics *)_staticsList[i]; + if (!strcmp(_staticsList[i]->_staticsName, name)) + return _staticsList[i]; return 0; } Movement *StaticANIObject::getMovementById(int itemId) { for (uint i = 0; i < _movements.size(); i++) - if (((Movement *)_movements[i])->_id == itemId) - return (Movement *)_movements[i]; + if (_movements[i]->_id == itemId) + return _movements[i]; return 0; } int StaticANIObject::getMovementIdById(int itemId) { for (uint i = 0; i < _movements.size(); i++) { - Movement *mov = (Movement *)_movements[i]; + Movement *mov = _movements[i]; + if (mov->_currMovement) { if (mov->_id == itemId) return mov->_id; + if (mov->_currMovement->_id == itemId) return mov->_id; } @@ -430,8 +441,8 @@ int StaticANIObject::getMovementIdById(int itemId) { Movement *StaticANIObject::getMovementByName(char *name) { for (uint i = 0; i < _movements.size(); i++) - if (!strcmp(((Movement *)_movements[i])->_objectName, name)) - return (Movement *)_movements[i]; + if (!strcmp(_movements[i]->_objectName, name)) + return _movements[i]; return 0; } @@ -551,12 +562,12 @@ void Movement::draw(bool flipFlag, int angle) { void StaticANIObject::loadMovementsPixelData() { for (uint i = 0; i < _movements.size(); i++) - ((Movement *)_movements[i])->loadPixelData(); + _movements[i]->loadPixelData(); } void StaticANIObject::freeMovementsPixelData() { for (uint i = 0; i < _movements.size(); i++) - ((Movement *)_movements[i])->freePixelData(); + _movements[i]->freePixelData(); } Statics *StaticANIObject::addReverseStatics(Statics *st) { @@ -665,11 +676,10 @@ MovTable *StaticANIObject::countMovements() { movTable->movs = (int16 *)calloc(_movements.size(), sizeof(int16)); for (uint i = 0; i < _movements.size(); i++) { - GameObject *obj = (GameObject *)_movements[i]; movTable->movs[i] = 2; for (GameVar *sub = preloadSubVar->_subVars; sub; sub = sub->_nextVarObj) { - if (scumm_stricmp(obj->getName(), sub->_varName) == 0) { + if (scumm_stricmp(_movements[i]->getName(), sub->_varName) == 0) { movTable->movs[i] = 1; break; } @@ -702,21 +712,21 @@ void StaticANIObject::setSpeed(int speed) { void StaticANIObject::setAlpha(int alpha) { for (uint i = 0; i < _movements.size(); i++) - ((Movement *)_movements[i])->setAlpha(alpha); + _movements[i]->setAlpha(alpha); for (uint i = 0; i < _staticsList.size(); i++) - ((Statics *)_staticsList[i])->setAlpha(alpha); + _staticsList[i]->setAlpha(alpha); } void StaticANIObject::initMovements() { for (uint i = 0; i < _movements.size(); i++) - ((Movement *)_movements[i])->removeFirstPhase(); + _movements[i]->removeFirstPhase(); } void StaticANIObject::preloadMovements(MovTable *mt) { - if ( mt ) { + if (mt) { for (uint i = 0; i < _movements.size(); i++) { - Movement *mov = (Movement *)_movements[i]; + Movement *mov = _movements[i]; if (mt->movs[i] == 1) mov->loadPixelData(); @@ -1177,8 +1187,8 @@ void StaticANIObject::startAnimSteps(int movementId, int messageQueueId, int x, if (!(_flags & 0x80)) { if (!_messageQueueId) for (uint i = 0; i < _movements.size(); i++) { - if (((Movement *)_movements[i])->_id == movementId) { - mov = (Movement *)_movements[i]; + if (_movements[i]->_id == movementId) { + mov = _movements[i]; break; } } @@ -1266,7 +1276,7 @@ bool StaticANIObject::startAnim(int movementId, int messageQueueId, int dynPhase if (_flags & 0x80) return false; - debug(0, "StaticANIObject::startAnim(%d, %d, %d) (%s [%d]) [%d, %d]", movementId, messageQueueId, dynPhaseIdx, transCyrillic((byte *)_objectName), _id, _ox, _oy); + debug(4, "StaticANIObject::startAnim(%d, %d, %d) (%s [%d]) [%d, %d]", movementId, messageQueueId, dynPhaseIdx, transCyrillic((byte *)_objectName), _id, _ox, _oy); if (_messageQueueId) { updateGlobalMessageQueue(messageQueueId, _id); @@ -1276,9 +1286,8 @@ bool StaticANIObject::startAnim(int movementId, int messageQueueId, int dynPhase Movement *mov = 0; for (uint i = 0; i < _movements.size(); i++) { - - if (((Movement *)_movements[i])->_id == movementId) { - mov = (Movement *)_movements[i]; + if (_movements[i]->_id == movementId) { + mov = _movements[i]; break; } } @@ -1441,6 +1450,19 @@ bool Statics::load(MfcArchive &file) { return true; } +void Statics::init() { + Picture::init(); + + if (_staticsId & 0x4000) { + Bitmap *bmp = _bitmap->reverseImage(); + + freePixelData(); + + _bitmap = bmp; + _data = bmp->_pixels; + } +} + Common::Point *Statics::getSomeXY(Common::Point &p) { p.x = _someX; p.y = _someY; @@ -1493,7 +1515,17 @@ Movement::Movement() { } Movement::~Movement() { - warning("STUB: Movement::~Movement()"); + for (uint i = 0; i < _dynamicPhases.size(); i++) + delete _framePosOffsets[i]; + + if (!_currMovement ) { + if (_updateFlag1) + _dynamicPhases.remove_at(0); + + _dynamicPhases.clear(); + } + + free(_framePosOffsets); } Movement::Movement(Movement *src, StaticANIObject *ani) { @@ -1748,11 +1780,11 @@ Common::Point *Movement::calcSomeXY(Common::Point &p, int idx) { void Movement::setAlpha(int alpha) { if (_currMovement) for (uint i = 0; i < _currMovement->_dynamicPhases.size(); i++) { - ((DynamicPhase *)_currMovement->_dynamicPhases[i])->setAlpha(alpha); + _currMovement->_dynamicPhases[i]->setAlpha(alpha); } else for (uint i = 0; i < _dynamicPhases.size(); i++) { - ((DynamicPhase *)_dynamicPhases[i])->setAlpha(alpha); + _dynamicPhases[i]->setAlpha(alpha); } } @@ -1765,9 +1797,9 @@ Common::Point *Movement::getDimensionsOfPhase(Common::Point *p, int phaseIndex) DynamicPhase *dyn; if (_currMovement) - dyn = (DynamicPhase *)_currMovement->_dynamicPhases[idx]; + dyn = _currMovement->_dynamicPhases[idx]; else - dyn = (DynamicPhase *)_dynamicPhases[idx]; + dyn = _dynamicPhases[idx]; Common::Point point; @@ -1816,13 +1848,13 @@ void Movement::updateCurrDynamicPhase() { return; if (_currMovement->_dynamicPhases[_currDynamicPhaseIndex]) - _currDynamicPhase = (DynamicPhase *)_currMovement->_dynamicPhases[_currDynamicPhaseIndex]; + _currDynamicPhase = _currMovement->_dynamicPhases[_currDynamicPhaseIndex]; } else { if (_dynamicPhases.size() == 0 || (uint)_currDynamicPhaseIndex >= _dynamicPhases.size()) return; if (_dynamicPhases[_currDynamicPhaseIndex]) - _currDynamicPhase = (DynamicPhase *)_dynamicPhases[_currDynamicPhaseIndex]; + _currDynamicPhase = _dynamicPhases[_currDynamicPhaseIndex]; } } @@ -1831,11 +1863,11 @@ int Movement::calcDuration() { if (_currMovement) for (uint i = 0; i < _currMovement->_dynamicPhases.size(); i++) { - res += ((DynamicPhase *)_currMovement->_dynamicPhases[i])->_initialCountdown; + res += _currMovement->_dynamicPhases[i]->_initialCountdown; } else for (uint i = 0; i < _dynamicPhases.size(); i++) { - res += ((DynamicPhase *)_dynamicPhases[i])->_initialCountdown; + res += _dynamicPhases[i]->_initialCountdown; } return res; @@ -1876,12 +1908,12 @@ DynamicPhase *Movement::getDynamicPhaseByIndex(int idx) { if (_currMovement->_dynamicPhases.size() == 0 || (uint)idx >= _currMovement->_dynamicPhases.size()) return 0; - return (DynamicPhase *)_currMovement->_dynamicPhases[idx]; + return _currMovement->_dynamicPhases[idx]; } else { if (_dynamicPhases.size() == 0 || (uint)idx >= _dynamicPhases.size()) return 0; - return (DynamicPhase *)_dynamicPhases[idx]; + return _dynamicPhases[idx]; } } @@ -1892,7 +1924,7 @@ void Movement::loadPixelData() { for (uint i = 0; i < _dynamicPhases.size(); i++) { if ((Statics *)_dynamicPhases[i] != mov->_staticsObj2 || !(mov->_staticsObj2->_staticsId & 0x4000)) - ((Statics *)_dynamicPhases[i])->getPixelData(); + _dynamicPhases[i]->getPixelData(); } if (!(mov->_staticsObj1->_staticsId & 0x4000)) @@ -1902,7 +1934,7 @@ void Movement::loadPixelData() { void Movement::freePixelData() { if (!_currMovement) for (uint i = 0; i < _dynamicPhases.size(); i++) - ((DynamicPhase *)_dynamicPhases[i])->freePixelData(); + _dynamicPhases[i]->freePixelData(); if (_staticsObj1) _staticsObj1->freePixelData(); @@ -1934,11 +1966,11 @@ bool Movement::gotoNextFrame(void (*callback1)(int, Common::Point *point, int, i if (!callback2) { if (_currMovement) { if ((uint)_currDynamicPhaseIndex == _currMovement->_dynamicPhases.size() - 1 - && !(((DynamicPhase *)(_currMovement->_dynamicPhases.back()))->_countdown)) { + && !(_currMovement->_dynamicPhases.back()->_countdown)) { return false; } } else if ((uint)_currDynamicPhaseIndex == _dynamicPhases.size() - 1 - && !(((DynamicPhase *)(_dynamicPhases.back()))->_countdown)) { + && !(_dynamicPhases.back()->_countdown)) { return false; } } diff --git a/engines/fullpipe/statics.h b/engines/fullpipe/statics.h index d678957163..63661157b2 100644 --- a/engines/fullpipe/statics.h +++ b/engines/fullpipe/statics.h @@ -98,6 +98,7 @@ class Statics : public DynamicPhase { virtual ~Statics(); virtual bool load(MfcArchive &file); + virtual void init(); Statics *getStaticsById(int itemId); Common::Point *getSomeXY(Common::Point &p); @@ -121,7 +122,7 @@ class Movement : public GameObject { int _field_50; int _counterMax; int _counter; - PtrList _dynamicPhases; + Common::Array<DynamicPhase *> _dynamicPhases; int _field_78; Common::Point **_framePosOffsets; Movement *_currMovement; @@ -181,8 +182,8 @@ class StaticANIObject : public GameObject { int _initialCounter; void (*_callback1)(int, Common::Point *point, int, int); void (*_callback2)(int *); - PtrList _movements; - PtrList _staticsList; + Common::Array<Movement *> _movements; + Common::Array<Statics *> _staticsList; StepArray _stepArray; int16 _field_96; int _messageQueueId; diff --git a/engines/fullpipe/utils.h b/engines/fullpipe/utils.h index 72e746cd03..da3ab7ee4f 100644 --- a/engines/fullpipe/utils.h +++ b/engines/fullpipe/utils.h @@ -68,6 +68,7 @@ enum ObjType { kObjTypeDefault, kObjTypeExCommand, kObjTypeExCommand2, + kObjTypeModalSaveGame, kObjTypeMovGraph, kObjTypeMovGraphLink, kObjTypeMovGraphNode, @@ -148,8 +149,6 @@ class DWordArray : public Common::Array<int32>, public CObject { virtual bool load(MfcArchive &file); }; -typedef Common::Array<void *> PtrList; - char *genFileName(int superId, int sceneId, const char *ext); byte *transCyrillic(byte *s); diff --git a/engines/gob/cheater_geisha.cpp b/engines/gob/cheater_geisha.cpp index 8c4deec370..ec6fe09d59 100644 --- a/engines/gob/cheater_geisha.cpp +++ b/engines/gob/cheater_geisha.cpp @@ -61,7 +61,7 @@ bool Cheater_Geisha::cheat(GUI::Debugger &console) { uint32 digit5 = READ_VARO_UINT32(0x778); if (digit1 && digit2 && digit3 && digit4 && digit5) - console.DebugPrintf("Mastermind solution: %d %d %d %d %d\n", + console.debugPrintf("Mastermind solution: %d %d %d %d %d\n", digit1, digit2, digit3, digit4, digit5); return true; diff --git a/engines/gob/console.cpp b/engines/gob/console.cpp index b0f6006284..2252606243 100644 --- a/engines/gob/console.cpp +++ b/engines/gob/console.cpp @@ -29,14 +29,14 @@ namespace Gob { GobConsole::GobConsole(GobEngine *vm) : GUI::Debugger(), _vm(vm), _cheater(0) { - DCmd_Register("varSize", WRAP_METHOD(GobConsole, cmd_varSize)); - DCmd_Register("dumpVars", WRAP_METHOD(GobConsole, cmd_dumpVars)); - DCmd_Register("var8", WRAP_METHOD(GobConsole, cmd_var8)); - DCmd_Register("var16", WRAP_METHOD(GobConsole, cmd_var16)); - DCmd_Register("var32", WRAP_METHOD(GobConsole, cmd_var32)); - DCmd_Register("varString", WRAP_METHOD(GobConsole, cmd_varString)); - DCmd_Register("cheat", WRAP_METHOD(GobConsole, cmd_cheat)); - DCmd_Register("listArchives", WRAP_METHOD(GobConsole, cmd_listArchives)); + registerCmd("varSize", WRAP_METHOD(GobConsole, cmd_varSize)); + registerCmd("dumpVars", WRAP_METHOD(GobConsole, cmd_dumpVars)); + registerCmd("var8", WRAP_METHOD(GobConsole, cmd_var8)); + registerCmd("var16", WRAP_METHOD(GobConsole, cmd_var16)); + registerCmd("var32", WRAP_METHOD(GobConsole, cmd_var32)); + registerCmd("varString", WRAP_METHOD(GobConsole, cmd_varString)); + registerCmd("cheat", WRAP_METHOD(GobConsole, cmd_cheat)); + registerCmd("listArchives", WRAP_METHOD(GobConsole, cmd_listArchives)); } GobConsole::~GobConsole() { @@ -51,7 +51,7 @@ void GobConsole::unregisterCheater() { } bool GobConsole::cmd_varSize(int argc, const char **argv) { - DebugPrintf("Size of the variable space: %d bytes\n", _vm->_inter->_variables->getSize()); + debugPrintf("Size of the variable space: %d bytes\n", _vm->_inter->_variables->getSize()); return true; } @@ -74,14 +74,14 @@ bool GobConsole::cmd_dumpVars(int argc, const char **argv) { bool GobConsole::cmd_var8(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: var8 <var offset> (<value>)\n"); + debugPrintf("Usage: var8 <var offset> (<value>)\n"); return true; } uint32 varNum = atoi(argv[1]); if (varNum >= _vm->_inter->_variables->getSize()) { - DebugPrintf("Variable offset out of range\n"); + debugPrintf("Variable offset out of range\n"); return true; } @@ -90,21 +90,21 @@ bool GobConsole::cmd_var8(int argc, const char **argv) { _vm->_inter->_variables->writeOff8(varNum, varVal); } - DebugPrintf("var8_%d = %d\n", varNum, _vm->_inter->_variables->readOff8(varNum)); + debugPrintf("var8_%d = %d\n", varNum, _vm->_inter->_variables->readOff8(varNum)); return true; } bool GobConsole::cmd_var16(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: var16 <var offset> (<value>)\n"); + debugPrintf("Usage: var16 <var offset> (<value>)\n"); return true; } uint32 varNum = atoi(argv[1]); if ((varNum + 1) >= _vm->_inter->_variables->getSize()) { - DebugPrintf("Variable offset out of range\n"); + debugPrintf("Variable offset out of range\n"); return true; } @@ -113,21 +113,21 @@ bool GobConsole::cmd_var16(int argc, const char **argv) { _vm->_inter->_variables->writeOff16(varNum, varVal); } - DebugPrintf("var16_%d = %d\n", varNum, _vm->_inter->_variables->readOff16(varNum)); + debugPrintf("var16_%d = %d\n", varNum, _vm->_inter->_variables->readOff16(varNum)); return true; } bool GobConsole::cmd_var32(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: var32 <var offset> (<value>)\n"); + debugPrintf("Usage: var32 <var offset> (<value>)\n"); return true; } uint32 varNum = atoi(argv[1]); if ((varNum + 3) >= _vm->_inter->_variables->getSize()) { - DebugPrintf("Variable offset out of range\n"); + debugPrintf("Variable offset out of range\n"); return true; } @@ -136,21 +136,21 @@ bool GobConsole::cmd_var32(int argc, const char **argv) { _vm->_inter->_variables->writeOff32(varNum, varVal); } - DebugPrintf("var8_%d = %d\n", varNum, _vm->_inter->_variables->readOff32(varNum)); + debugPrintf("var8_%d = %d\n", varNum, _vm->_inter->_variables->readOff32(varNum)); return true; } bool GobConsole::cmd_varString(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: varString <var offset> (<value>)\n"); + debugPrintf("Usage: varString <var offset> (<value>)\n"); return true; } uint32 varNum = atoi(argv[1]); if (varNum >= _vm->_inter->_variables->getSize()) { - DebugPrintf("Variable offset out of range\n"); + debugPrintf("Variable offset out of range\n"); return true; } @@ -160,7 +160,7 @@ bool GobConsole::cmd_varString(int argc, const char **argv) { Common::strlcpy(_vm->_inter->_variables->getAddressOffString(varNum), argv[2], maxLength); } - DebugPrintf("varString_%d = \"%s\"\n", varNum, _vm->_inter->_variables->getAddressOffString(varNum)); + debugPrintf("varString_%d = \"%s\"\n", varNum, _vm->_inter->_variables->getAddressOffString(varNum)); return true; } @@ -177,11 +177,11 @@ bool GobConsole::cmd_listArchives(int argc, const char **argv) { _vm->_dataIO->getArchiveInfo(info); - DebugPrintf(" Archive | Base | FileCount\n"); - DebugPrintf("--------------------------------\n"); + debugPrintf(" Archive | Base | FileCount\n"); + debugPrintf("--------------------------------\n"); for (Common::Array<ArchiveInfo>::const_iterator it = info.begin(); it != info.end(); ++it) if (!it->name.empty()) - DebugPrintf("%13s | %d | %d\n", it->name.c_str(), it->base, it->fileCount); + debugPrintf("%13s | %d | %d\n", it->name.c_str(), it->base, it->fileCount); return true; } diff --git a/engines/groovie/debug.cpp b/engines/groovie/debug.cpp index 8103e4f4c6..16db20413f 100644 --- a/engines/groovie/debug.cpp +++ b/engines/groovie/debug.cpp @@ -36,16 +36,16 @@ Debugger::Debugger(GroovieEngine *vm) : _vm(vm), _script(_vm->_script) { // Register the debugger comands - DCmd_Register("step", WRAP_METHOD(Debugger, cmd_step)); - DCmd_Register("go", WRAP_METHOD(Debugger, cmd_go)); - DCmd_Register("pc", WRAP_METHOD(Debugger, cmd_pc)); - DCmd_Register("fg", WRAP_METHOD(Debugger, cmd_fg)); - DCmd_Register("bg", WRAP_METHOD(Debugger, cmd_bg)); - DCmd_Register("mem", WRAP_METHOD(Debugger, cmd_mem)); - DCmd_Register("load", WRAP_METHOD(Debugger, cmd_loadgame)); - DCmd_Register("save", WRAP_METHOD(Debugger, cmd_savegame)); - DCmd_Register("playref", WRAP_METHOD(Debugger, cmd_playref)); - DCmd_Register("dumppal", WRAP_METHOD(Debugger, cmd_dumppal)); + registerCmd("step", WRAP_METHOD(Debugger, cmd_step)); + registerCmd("go", WRAP_METHOD(Debugger, cmd_go)); + registerCmd("pc", WRAP_METHOD(Debugger, cmd_pc)); + registerCmd("fg", WRAP_METHOD(Debugger, cmd_fg)); + registerCmd("bg", WRAP_METHOD(Debugger, cmd_bg)); + registerCmd("mem", WRAP_METHOD(Debugger, cmd_mem)); + registerCmd("load", WRAP_METHOD(Debugger, cmd_loadgame)); + registerCmd("save", WRAP_METHOD(Debugger, cmd_savegame)); + registerCmd("playref", WRAP_METHOD(Debugger, cmd_playref)); + registerCmd("dumppal", WRAP_METHOD(Debugger, cmd_dumppal)); } Debugger::~Debugger() { @@ -81,7 +81,7 @@ bool Debugger::cmd_pc(int argc, const char **argv) { int val = getNumber(argv[1]); _script->_currentInstruction = val; } - DebugPrintf("pc = 0x%04X (%d)\n", _script->_currentInstruction, _script->_currentInstruction); + debugPrintf("pc = 0x%04X (%d)\n", _script->_currentInstruction, _script->_currentInstruction); return true; } @@ -97,9 +97,9 @@ bool Debugger::cmd_mem(int argc, const char **argv) { // Get val = _script->_variables[pos]; } - DebugPrintf("mem[0x%04X] = 0x%02X\n", pos, val); + debugPrintf("mem[0x%04X] = 0x%02X\n", pos, val); } else { - DebugPrintf("Syntax: mem <addr> [<val>]\n"); + debugPrintf("Syntax: mem <addr> [<val>]\n"); } return true; } @@ -109,7 +109,7 @@ bool Debugger::cmd_loadgame(int argc, const char **argv) { int slot = getNumber(argv[1]); _script->loadgame(slot); } else { - DebugPrintf("Syntax: load <slot>\n"); + debugPrintf("Syntax: load <slot>\n"); } return true; } @@ -119,7 +119,7 @@ bool Debugger::cmd_savegame(int argc, const char **argv) { int slot = getNumber(argv[1]); _script->savegame(slot); } else { - DebugPrintf("Syntax: save <slot>\n"); + debugPrintf("Syntax: save <slot>\n"); } return true; } @@ -129,7 +129,7 @@ bool Debugger::cmd_playref(int argc, const char **argv) { int ref = getNumber(argv[1]); _script->playvideofromref(ref); } else { - DebugPrintf("Syntax: playref <videorefnum>\n"); + debugPrintf("Syntax: playref <videorefnum>\n"); } return true; } @@ -140,7 +140,7 @@ bool Debugger::cmd_dumppal(int argc, const char **argv) { _vm->_system->getPaletteManager()->grabPalette(palettedump, 0, 256); for (i = 0; i < 256; i++) { - DebugPrintf("%3d: %3d,%3d,%3d\n", i, palettedump[(i * 3)], palettedump[(i * 3) + 1], palettedump[(i * 3) + 2]); + debugPrintf("%3d: %3d,%3d,%3d\n", i, palettedump[(i * 3)], palettedump[(i * 3) + 1], palettedump[(i * 3) + 2]); } return true; } diff --git a/engines/hopkins/computer.cpp b/engines/hopkins/computer.cpp index 1307cd5796..84d5c631c7 100644 --- a/engines/hopkins/computer.cpp +++ b/engines/hopkins/computer.cpp @@ -38,10 +38,9 @@ namespace Hopkins { ComputerManager::ComputerManager(HopkinsEngine *vm) { _vm = vm; - for (int i = 0; i < 50; i++) { - _menuText[i]._actvFl = false; + for (int i = 0; i < ARRAYSIZE(_menuText); i++) { _menuText[i]._lineSize = 0; - memset(_menuText[i]._line, 0, 90); + memset(_menuText[i]._line, 0, ARRAYSIZE(_menuText[0]._line)); } Common::fill(&_inputBuf[0], &_inputBuf[200], '\0'); _breakoutSpr = NULL; @@ -346,6 +345,7 @@ static const char _spanishText[] = * Load Menu data */ void ComputerManager::loadMenu() { + debug(9, "ComputerManager::loadMenu()"); char *ptr; if (_vm->_fileIO->fileExists("COMPUTAN.TXT")) { ptr = (char *)_vm->_fileIO->loadFile("COMPUTAN.TXT"); @@ -353,46 +353,52 @@ void ComputerManager::loadMenu() { switch (_vm->_globals->_language) { case LANG_FR: ptr = (char *)_vm->_globals->allocMemory(sizeof(_frenchText)); - strcpy(ptr, _frenchText); + Common::strlcpy(ptr, _frenchText, sizeof(_frenchText)); break; case LANG_SP: ptr = (char *)_vm->_globals->allocMemory(sizeof(_spanishText)); - strcpy(ptr, _spanishText); + Common::strlcpy(ptr, _spanishText, sizeof(_spanishText)); break; default: ptr = (char *)_vm->_globals->allocMemory(sizeof(_englishText)); - strcpy(ptr, _englishText); + Common::strlcpy(ptr, _englishText, sizeof(_englishText)); break; } } char *tmpPtr = ptr; int lineNum = 0; - int strPos; - bool loopCond = false; - do { - if (tmpPtr[0] == '%') { - if (tmpPtr[1] == '%') { - loopCond = true; - break; - } - _menuText[lineNum]._actvFl = 1; - strPos = 0; - while (strPos <= 89) { + const char lineSep = tmpPtr[0]; + + while (tmpPtr[0] != '\0' && lineNum < ARRAYSIZE(_menuText)) { + if (tmpPtr[0] == '%' && tmpPtr[1] == '%') { + // End of file marker found - Break out of parse loop + break; + } + + if (tmpPtr[0] == lineSep) { + int strPos = 0; + while (strPos < ARRAYSIZE(_menuText[0]._line)) { char curChar = tmpPtr[strPos + 2]; - if (curChar == '%' || curChar == 10) + if (curChar == '\0' || curChar == lineSep || curChar == 0x0a) // Line Feed break; _menuText[lineNum]._line[strPos++] = curChar; } - if (strPos <= 89) { + + if (strPos < ARRAYSIZE(_menuText[0]._line)) { _menuText[lineNum]._line[strPos] = 0; _menuText[lineNum]._lineSize = strPos - 1; } - ++lineNum; + + if (strPos != 0) { + debug(9, "_menuText[%d]._line (size: %d): \"%s\"", lineNum, _menuText[lineNum]._lineSize, _menuText[lineNum]._line); + ++lineNum; + } } ++tmpPtr; - } while (!loopCond); + } + _vm->_globals->freeMemory((byte *)ptr); } diff --git a/engines/hopkins/computer.h b/engines/hopkins/computer.h index e8857a234b..ba50dca4cf 100644 --- a/engines/hopkins/computer.h +++ b/engines/hopkins/computer.h @@ -31,22 +31,22 @@ namespace Hopkins { class HopkinsEngine; -struct MenuItem { - bool _actvFl; - int _lineSize; - char _line[90]; -}; - -struct ScoreItem { - Common::String _name; - Common::String _score; -}; - enum ComputerEnum { COMPUTER_HOPKINS = 1, COMPUTER_SAMANTHA = 2, COMPUTER_PUBLIC = 3 }; class ComputerManager { private: HopkinsEngine *_vm; + + struct MenuItem { + int _lineSize; + char _line[90]; + }; + + struct ScoreItem { + Common::String _name; + Common::String _score; + }; + MenuItem _menuText[50]; char _inputBuf[200]; ScoreItem _score[6]; @@ -84,14 +84,14 @@ private: void displayLives(); void displayBricks(); void displayGamesSubMenu(); - int displayHiscores(); + int displayHiscores(); void displayHiscoreLine(const byte *objectData, int x, int y, int curChar); void displayMessage(int xp, int yp, int textIdx); void displayScore(); void displayScoreChar(int charPos, int charDisp); void getScoreName(); void playBreakout(); - int moveBall(); + int moveBall(); void saveScore(); void checkBallCollisions(); diff --git a/engines/hopkins/debugger.cpp b/engines/hopkins/debugger.cpp index 14b1c183a8..3dcfdfea7b 100644 --- a/engines/hopkins/debugger.cpp +++ b/engines/hopkins/debugger.cpp @@ -30,18 +30,18 @@ namespace Hopkins { Debugger::Debugger(HopkinsEngine *vm) : GUI::Debugger() { _vm = vm; - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("rects", WRAP_METHOD(Debugger, cmd_DirtyRects)); - DCmd_Register("teleport", WRAP_METHOD(Debugger, cmd_Teleport)); - DCmd_Register("show_room", WRAP_METHOD(Debugger, cmd_ShowCurrentRoom)); - DCmd_Register("zones", WRAP_METHOD(Debugger, cmd_Zones)); - DCmd_Register("lines", WRAP_METHOD(Debugger, cmd_Lines)); + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("rects", WRAP_METHOD(Debugger, cmd_DirtyRects)); + registerCmd("teleport", WRAP_METHOD(Debugger, cmd_Teleport)); + registerCmd("show_room", WRAP_METHOD(Debugger, cmd_ShowCurrentRoom)); + registerCmd("zones", WRAP_METHOD(Debugger, cmd_Zones)); + registerCmd("lines", WRAP_METHOD(Debugger, cmd_Lines)); } // Turns dirty rects on or off bool Debugger::cmd_DirtyRects(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("%s: [on | off]\n", argv[0]); + debugPrintf("%s: [on | off]\n", argv[0]); return true; } else { _vm->_graphicsMan->_showDirtyRects = !strcmp(argv[1], "on"); @@ -52,7 +52,7 @@ bool Debugger::cmd_DirtyRects(int argc, const char **argv) { // Change room number bool Debugger::cmd_Teleport(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("%s: [Room number]\n", argv[0]); + debugPrintf("%s: [Room number]\n", argv[0]); return true; } else { _vm->_globals->_exitId = atoi(argv[1]); @@ -62,13 +62,13 @@ bool Debugger::cmd_Teleport(int argc, const char **argv) { // Display room number bool Debugger::cmd_ShowCurrentRoom(int argc, const char **argv) { - DebugPrintf("Current room: %d\n", _vm->_globals->_curRoomNum); + debugPrintf("Current room: %d\n", _vm->_globals->_curRoomNum); return true; } bool Debugger::cmd_Zones(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("%s: [on | off]\n", argv[0]); + debugPrintf("%s: [on | off]\n", argv[0]); return true; } else { _vm->_graphicsMan->_showZones = !strcmp(argv[1], "on"); @@ -78,7 +78,7 @@ if (argc != 2) { bool Debugger::cmd_Lines(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("%s: [on | off]\n", argv[0]); + debugPrintf("%s: [on | off]\n", argv[0]); return true; } else { _vm->_graphicsMan->_showLines = !strcmp(argv[1], "on"); diff --git a/engines/hopkins/files.cpp b/engines/hopkins/files.cpp index 75f429f860..6620f2878c 100644 --- a/engines/hopkins/files.cpp +++ b/engines/hopkins/files.cpp @@ -51,12 +51,13 @@ byte *FileManager::loadFile(const Common::String &file) { // Allocate space for the file contents size_t filesize = f.size(); - byte *data = _vm->_globals->allocMemory(filesize); + byte *data = _vm->_globals->allocMemory(filesize+1); if (!data) error("Error allocating space for file being loaded - %s", file.c_str()); readStream(f, data, filesize); f.close(); + data[filesize] = '\0'; return data; } diff --git a/engines/hugo/console.cpp b/engines/hugo/console.cpp index 56025bfbfd..d02c42658f 100644 --- a/engines/hugo/console.cpp +++ b/engines/hugo/console.cpp @@ -30,12 +30,12 @@ namespace Hugo { HugoConsole::HugoConsole(HugoEngine *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("listscreens", WRAP_METHOD(HugoConsole, Cmd_listScreens)); - DCmd_Register("listobjects", WRAP_METHOD(HugoConsole, Cmd_listObjects)); - DCmd_Register("getobject", WRAP_METHOD(HugoConsole, Cmd_getObject)); - DCmd_Register("getallobjects", WRAP_METHOD(HugoConsole, Cmd_getAllObjects)); - DCmd_Register("gotoscreen", WRAP_METHOD(HugoConsole, Cmd_gotoScreen)); - DCmd_Register("Boundaries", WRAP_METHOD(HugoConsole, Cmd_boundaries)); + registerCmd("listscreens", WRAP_METHOD(HugoConsole, Cmd_listScreens)); + registerCmd("listobjects", WRAP_METHOD(HugoConsole, Cmd_listObjects)); + registerCmd("getobject", WRAP_METHOD(HugoConsole, Cmd_getObject)); + registerCmd("getallobjects", WRAP_METHOD(HugoConsole, Cmd_getAllObjects)); + registerCmd("gotoscreen", WRAP_METHOD(HugoConsole, Cmd_gotoScreen)); + registerCmd("Boundaries", WRAP_METHOD(HugoConsole, Cmd_boundaries)); } HugoConsole::~HugoConsole() { @@ -62,7 +62,7 @@ static int strToInt(const char *s) { */ bool HugoConsole::Cmd_gotoScreen(int argc, const char **argv) { if ((argc != 2) || (strToInt(argv[1]) > _vm->_numScreens)){ - DebugPrintf("Usage: %s <screen number>\n", argv[0]); + debugPrintf("Usage: %s <screen number>\n", argv[0]); return true; } @@ -75,13 +75,13 @@ bool HugoConsole::Cmd_gotoScreen(int argc, const char **argv) { */ bool HugoConsole::Cmd_listScreens(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Usage: %s\n", argv[0]); return true; } - DebugPrintf("Available screens for this game are:\n"); + debugPrintf("Available screens for this game are:\n"); for (int i = 0; i < _vm->_numScreens; i++) - DebugPrintf("%2d - %s\n", i, _vm->_text->getScreenNames(i)); + debugPrintf("%2d - %s\n", i, _vm->_text->getScreenNames(i)); return true; } @@ -90,14 +90,14 @@ bool HugoConsole::Cmd_listScreens(int argc, const char **argv) { */ bool HugoConsole::Cmd_listObjects(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Usage: %s\n", argv[0]); return true; } - DebugPrintf("Available objects for this game are:\n"); + debugPrintf("Available objects for this game are:\n"); for (int i = 0; i < _vm->_object->_numObj; i++) { if (_vm->_object->_objects[i]._genericCmd & TAKE) - DebugPrintf("%2d - %s\n", i, _vm->_text->getNoun(_vm->_object->_objects[i]._nounIndex, 2)); + debugPrintf("%2d - %s\n", i, _vm->_text->getNoun(_vm->_object->_objects[i]._nounIndex, 2)); } return true; } @@ -107,14 +107,14 @@ bool HugoConsole::Cmd_listObjects(int argc, const char **argv) { */ bool HugoConsole::Cmd_getObject(int argc, const char **argv) { if ((argc != 2) || (strToInt(argv[1]) > _vm->_object->_numObj)) { - DebugPrintf("Usage: %s <object number>\n", argv[0]); + debugPrintf("Usage: %s <object number>\n", argv[0]); return true; } if (_vm->_object->_objects[strToInt(argv[1])]._genericCmd & TAKE) _vm->_parser->takeObject(&_vm->_object->_objects[strToInt(argv[1])]); else - DebugPrintf("Object not available\n"); + debugPrintf("Object not available\n"); return true; } @@ -124,7 +124,7 @@ bool HugoConsole::Cmd_getObject(int argc, const char **argv) { */ bool HugoConsole::Cmd_getAllObjects(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Usage: %s\n", argv[0]); return true; } @@ -141,7 +141,7 @@ bool HugoConsole::Cmd_getAllObjects(int argc, const char **argv) { */ bool HugoConsole::Cmd_boundaries(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Usage: %s\n", argv[0]); return true; } diff --git a/engines/kyra/debugger.cpp b/engines/kyra/debugger.cpp index e4806afb70..4a90722a35 100644 --- a/engines/kyra/debugger.cpp +++ b/engines/kyra/debugger.cpp @@ -40,45 +40,45 @@ Debugger::Debugger(KyraEngine_v1 *vm) } void Debugger::initialize() { - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("screen_debug_mode", WRAP_METHOD(Debugger, cmd_setScreenDebug)); - DCmd_Register("load_palette", WRAP_METHOD(Debugger, cmd_loadPalette)); - DCmd_Register("facings", WRAP_METHOD(Debugger, cmd_showFacings)); - DCmd_Register("gamespeed", WRAP_METHOD(Debugger, cmd_gameSpeed)); - DCmd_Register("flags", WRAP_METHOD(Debugger, cmd_listFlags)); - DCmd_Register("toggleflag", WRAP_METHOD(Debugger, cmd_toggleFlag)); - DCmd_Register("queryflag", WRAP_METHOD(Debugger, cmd_queryFlag)); - DCmd_Register("timers", WRAP_METHOD(Debugger, cmd_listTimers)); - DCmd_Register("settimercountdown", WRAP_METHOD(Debugger, cmd_setTimerCountdown)); -} - -bool Debugger::cmd_setScreenDebug(int argc, const char **argv) { + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("screen_debug_mode", WRAP_METHOD(Debugger, cmdSetScreenDebug)); + registerCmd("load_palette", WRAP_METHOD(Debugger, cmdLoadPalette)); + registerCmd("facings", WRAP_METHOD(Debugger, cmdShowFacings)); + registerCmd("gamespeed", WRAP_METHOD(Debugger, cmdGameSpeed)); + registerCmd("flags", WRAP_METHOD(Debugger, cmdListFlags)); + registerCmd("toggleflag", WRAP_METHOD(Debugger, cmdToggleFlag)); + registerCmd("queryflag", WRAP_METHOD(Debugger, cmdQueryFlag)); + registerCmd("timers", WRAP_METHOD(Debugger, cmdListTimers)); + registerCmd("settimercountdown", WRAP_METHOD(Debugger, cmdSetTimerCountdown)); +} + +bool Debugger::cmdSetScreenDebug(int argc, const char **argv) { if (argc > 1) { if (scumm_stricmp(argv[1], "enable") == 0) _vm->screen()->enableScreenDebug(true); else if (scumm_stricmp(argv[1], "disable") == 0) _vm->screen()->enableScreenDebug(false); else - DebugPrintf("Use screen_debug_mode <enable/disable> to enable or disable it.\n"); + debugPrintf("Use screen_debug_mode <enable/disable> to enable or disable it.\n"); } else { - DebugPrintf("Screen debug mode is %s.\n", (_vm->screen()->queryScreenDebug() ? "enabled" : "disabled")); - DebugPrintf("Use screen_debug_mode <enable/disable> to enable or disable it.\n"); + debugPrintf("Screen debug mode is %s.\n", (_vm->screen()->queryScreenDebug() ? "enabled" : "disabled")); + debugPrintf("Use screen_debug_mode <enable/disable> to enable or disable it.\n"); } return true; } -bool Debugger::cmd_loadPalette(int argc, const char **argv) { +bool Debugger::cmdLoadPalette(int argc, const char **argv) { Palette palette(_vm->screen()->getPalette(0).getNumColors()); if (argc <= 1) { - DebugPrintf("Use load_palette <file> [start_col] [end_col]\n"); + debugPrintf("Use load_palette <file> [start_col] [end_col]\n"); return true; } if (_vm->game() != GI_KYRA1 && _vm->resource()->getFileSize(argv[1]) != 768) { uint8 *buffer = new uint8[320 * 200 * sizeof(uint8)]; if (!buffer) { - DebugPrintf("ERROR: Cannot allocate buffer for screen region!\n"); + debugPrintf("ERROR: Cannot allocate buffer for screen region!\n"); return true; } @@ -89,7 +89,7 @@ bool Debugger::cmd_loadPalette(int argc, const char **argv) { delete[] buffer; } else if (!_vm->screen()->loadPalette(argv[1], palette)) { - DebugPrintf("ERROR: Palette '%s' not found!\n", argv[1]); + debugPrintf("ERROR: Palette '%s' not found!\n", argv[1]); return true; } @@ -111,87 +111,87 @@ bool Debugger::cmd_loadPalette(int argc, const char **argv) { return true; } -bool Debugger::cmd_showFacings(int argc, const char **argv) { - DebugPrintf("Facing directions:\n"); - DebugPrintf("7 0 1\n"); - DebugPrintf(" \\ | / \n"); - DebugPrintf("6--*--2\n"); - DebugPrintf(" / | \\\n"); - DebugPrintf("5 4 3\n"); +bool Debugger::cmdShowFacings(int argc, const char **argv) { + debugPrintf("Facing directions:\n"); + debugPrintf("7 0 1\n"); + debugPrintf(" \\ | / \n"); + debugPrintf("6--*--2\n"); + debugPrintf(" / | \\\n"); + debugPrintf("5 4 3\n"); return true; } -bool Debugger::cmd_gameSpeed(int argc, const char **argv) { +bool Debugger::cmdGameSpeed(int argc, const char **argv) { if (argc == 2) { int val = atoi(argv[1]); if (val < 1 || val > 1000) { - DebugPrintf("speed must lie between 1 and 1000 (default: 60)\n"); + debugPrintf("speed must lie between 1 and 1000 (default: 60)\n"); return true; } _vm->_tickLength = (uint8)(1000.0 / val); } else { - DebugPrintf("Syntax: gamespeed <value>\n"); + debugPrintf("Syntax: gamespeed <value>\n"); } return true; } -bool Debugger::cmd_listFlags(int argc, const char **argv) { +bool Debugger::cmdListFlags(int argc, const char **argv) { for (int i = 0, p = 0; i < (int)sizeof(_vm->_flagsTable) * 8; i++, ++p) { - DebugPrintf("(%-3i): %-2i", i, _vm->queryGameFlag(i)); + debugPrintf("(%-3i): %-2i", i, _vm->queryGameFlag(i)); if (p == 5) { - DebugPrintf("\n"); + debugPrintf("\n"); p -= 6; } } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } -bool Debugger::cmd_toggleFlag(int argc, const char **argv) { +bool Debugger::cmdToggleFlag(int argc, const char **argv) { if (argc > 1) { uint flag = atoi(argv[1]); if (_vm->queryGameFlag(flag)) _vm->resetGameFlag(flag); else _vm->setGameFlag(flag); - DebugPrintf("Flag %i is now %i\n", flag, _vm->queryGameFlag(flag)); + debugPrintf("Flag %i is now %i\n", flag, _vm->queryGameFlag(flag)); } else { - DebugPrintf("Syntax: toggleflag <flag>\n"); + debugPrintf("Syntax: toggleflag <flag>\n"); } return true; } -bool Debugger::cmd_queryFlag(int argc, const char **argv) { +bool Debugger::cmdQueryFlag(int argc, const char **argv) { if (argc > 1) { uint flag = atoi(argv[1]); - DebugPrintf("Flag %i is %i\n", flag, _vm->queryGameFlag(flag)); + debugPrintf("Flag %i is %i\n", flag, _vm->queryGameFlag(flag)); } else { - DebugPrintf("Syntax: queryflag <flag>\n"); + debugPrintf("Syntax: queryflag <flag>\n"); } return true; } -bool Debugger::cmd_listTimers(int argc, const char **argv) { - DebugPrintf("Current time: %-8u\n", g_system->getMillis()); +bool Debugger::cmdListTimers(int argc, const char **argv) { + debugPrintf("Current time: %-8u\n", g_system->getMillis()); for (int i = 0; i < _vm->timer()->count(); i++) - DebugPrintf("Timer %-2i: Active: %-3s Countdown: %-6i %-8u\n", i, _vm->timer()->isEnabled(i) ? "Yes" : "No", _vm->timer()->getDelay(i), _vm->timer()->getNextRun(i)); + debugPrintf("Timer %-2i: Active: %-3s Countdown: %-6i %-8u\n", i, _vm->timer()->isEnabled(i) ? "Yes" : "No", _vm->timer()->getDelay(i), _vm->timer()->getNextRun(i)); return true; } -bool Debugger::cmd_setTimerCountdown(int argc, const char **argv) { +bool Debugger::cmdSetTimerCountdown(int argc, const char **argv) { if (argc > 2) { uint timer = atoi(argv[1]); uint countdown = atoi(argv[2]); _vm->timer()->setCountdown(timer, countdown); - DebugPrintf("Timer %i now has countdown %i\n", timer, _vm->timer()->getDelay(timer)); + debugPrintf("Timer %i now has countdown %i\n", timer, _vm->timer()->getDelay(timer)); } else { - DebugPrintf("Syntax: settimercountdown <timer> <countdown>\n"); + debugPrintf("Syntax: settimercountdown <timer> <countdown>\n"); } return true; @@ -204,21 +204,21 @@ Debugger_LoK::Debugger_LoK(KyraEngine_LoK *vm) } void Debugger_LoK::initialize() { - DCmd_Register("enter", WRAP_METHOD(Debugger_LoK, cmd_enterRoom)); - DCmd_Register("scenes", WRAP_METHOD(Debugger_LoK, cmd_listScenes)); - DCmd_Register("give", WRAP_METHOD(Debugger_LoK, cmd_giveItem)); - DCmd_Register("birthstones", WRAP_METHOD(Debugger_LoK, cmd_listBirthstones)); + registerCmd("enter", WRAP_METHOD(Debugger_LoK, cmdEnterRoom)); + registerCmd("scenes", WRAP_METHOD(Debugger_LoK, cmdListScenes)); + registerCmd("give", WRAP_METHOD(Debugger_LoK, cmdGiveItem)); + registerCmd("birthstones", WRAP_METHOD(Debugger_LoK, cmdListBirthstones)); Debugger::initialize(); } -bool Debugger_LoK::cmd_enterRoom(int argc, const char **argv) { +bool Debugger_LoK::cmdEnterRoom(int argc, const char **argv) { uint direction = 0; if (argc > 1) { int room = atoi(argv[1]); // game will crash if entering a non-existent room if (room >= _vm->_roomTableSize) { - DebugPrintf("room number must be any value between (including) 0 and %d\n", _vm->_roomTableSize - 1); + debugPrintf("room number must be any value between (including) 0 and %d\n", _vm->_roomTableSize - 1); return true; } @@ -246,44 +246,44 @@ bool Debugger_LoK::cmd_enterRoom(int argc, const char **argv) { return false; } - DebugPrintf("Syntax: room <roomnum> <direction>\n"); + debugPrintf("Syntax: room <roomnum> <direction>\n"); return true; } -bool Debugger_LoK::cmd_listScenes(int argc, const char **argv) { +bool Debugger_LoK::cmdListScenes(int argc, const char **argv) { for (int i = 0; i < _vm->_roomTableSize; i++) { - DebugPrintf("%-3i: %-10s", i, _vm->_roomFilenameTable[_vm->_roomTable[i].nameIndex]); + debugPrintf("%-3i: %-10s", i, _vm->_roomFilenameTable[_vm->_roomTable[i].nameIndex]); if (!(i % 8)) - DebugPrintf("\n"); + debugPrintf("\n"); } - DebugPrintf("\n"); - DebugPrintf("Current room: %i\n", _vm->_currentRoom); + debugPrintf("\n"); + debugPrintf("Current room: %i\n", _vm->_currentRoom); return true; } -bool Debugger_LoK::cmd_giveItem(int argc, const char **argv) { +bool Debugger_LoK::cmdGiveItem(int argc, const char **argv) { if (argc == 2) { int item = atoi(argv[1]); // Kyrandia 1 has only 108 items (-1 to 106), otherwise it will crash if (item < -1 || item > 106) { - DebugPrintf("'itemid' must be any value between (including) -1 and 106\n"); + debugPrintf("'itemid' must be any value between (including) -1 and 106\n"); return true; } _vm->setMouseItem(item); _vm->_itemInHand = item; } else { - DebugPrintf("Syntax: give <itemid>\n"); + debugPrintf("Syntax: give <itemid>\n"); } return true; } -bool Debugger_LoK::cmd_listBirthstones(int argc, const char **argv) { - DebugPrintf("Needed birthstone gems:\n"); +bool Debugger_LoK::cmdListBirthstones(int argc, const char **argv) { + debugPrintf("Needed birthstone gems:\n"); for (int i = 0; i < ARRAYSIZE(_vm->_birthstoneGemTable); ++i) - DebugPrintf("%-3d '%s'\n", _vm->_birthstoneGemTable[i], _vm->_itemList[_vm->_birthstoneGemTable[i]]); + debugPrintf("%-3d '%s'\n", _vm->_birthstoneGemTable[i], _vm->_itemList[_vm->_birthstoneGemTable[i]]); return true; } @@ -293,23 +293,23 @@ Debugger_v2::Debugger_v2(KyraEngine_v2 *vm) : Debugger(vm), _vm(vm) { } void Debugger_v2::initialize() { - DCmd_Register("character_info", WRAP_METHOD(Debugger_v2, cmd_characterInfo)); - DCmd_Register("enter", WRAP_METHOD(Debugger_v2, cmd_enterScene)); - DCmd_Register("scenes", WRAP_METHOD(Debugger_v2, cmd_listScenes)); - DCmd_Register("scene_info", WRAP_METHOD(Debugger_v2, cmd_sceneInfo)); - DCmd_Register("scene_to_facing", WRAP_METHOD(Debugger_v2, cmd_sceneToFacing)); - DCmd_Register("give", WRAP_METHOD(Debugger_v2, cmd_giveItem)); + registerCmd("character_info", WRAP_METHOD(Debugger_v2, cmdCharacterInfo)); + registerCmd("enter", WRAP_METHOD(Debugger_v2, cmdEnterScene)); + registerCmd("scenes", WRAP_METHOD(Debugger_v2, cmdListScenes)); + registerCmd("scene_info", WRAP_METHOD(Debugger_v2, cmdSceneInfo)); + registerCmd("scene_to_facing", WRAP_METHOD(Debugger_v2, cmdSceneToFacing)); + registerCmd("give", WRAP_METHOD(Debugger_v2, cmdGiveItem)); Debugger::initialize(); } -bool Debugger_v2::cmd_enterScene(int argc, const char **argv) { +bool Debugger_v2::cmdEnterScene(int argc, const char **argv) { uint direction = 0; if (argc > 1) { int scene = atoi(argv[1]); // game will crash if entering a non-existent scene if (scene >= _vm->_sceneListSize) { - DebugPrintf("scene number must be any value between (including) 0 and %d\n", _vm->_sceneListSize - 1); + debugPrintf("scene number must be any value between (including) 0 and %d\n", _vm->_sceneListSize - 1); return true; } @@ -337,40 +337,40 @@ bool Debugger_v2::cmd_enterScene(int argc, const char **argv) { return false; } - DebugPrintf("Syntax: %s <scenenum> <direction>\n", argv[0]); + debugPrintf("Syntax: %s <scenenum> <direction>\n", argv[0]); return true; } -bool Debugger_v2::cmd_listScenes(int argc, const char **argv) { +bool Debugger_v2::cmdListScenes(int argc, const char **argv) { int shown = 1; for (int i = 0; i < _vm->_sceneListSize; ++i) { if (_vm->_sceneList[i].filename1[0]) { - DebugPrintf("%-2i: %-10s", i, _vm->_sceneList[i].filename1); + debugPrintf("%-2i: %-10s", i, _vm->_sceneList[i].filename1); if (!(shown % 5)) - DebugPrintf("\n"); + debugPrintf("\n"); ++shown; } } - DebugPrintf("\n"); - DebugPrintf("Current scene: %i\n", _vm->_currentScene); + debugPrintf("\n"); + debugPrintf("Current scene: %i\n", _vm->_currentScene); return true; } -bool Debugger_v2::cmd_sceneInfo(int argc, const char **argv) { - DebugPrintf("Current scene: %d '%s'\n", _vm->_currentScene, _vm->_sceneList[_vm->_currentScene].filename1); - DebugPrintf("\n"); - DebugPrintf("Exit information:\n"); - DebugPrintf("Exit1: leads to %d, position %dx%d\n", int16(_vm->_sceneExit1), _vm->_sceneEnterX1, _vm->_sceneEnterY1); - DebugPrintf("Exit2: leads to %d, position %dx%d\n", int16(_vm->_sceneExit2), _vm->_sceneEnterX2, _vm->_sceneEnterY2); - DebugPrintf("Exit3: leads to %d, position %dx%d\n", int16(_vm->_sceneExit3), _vm->_sceneEnterX3, _vm->_sceneEnterY3); - DebugPrintf("Exit4: leads to %d, position %dx%d\n", int16(_vm->_sceneExit4), _vm->_sceneEnterX4, _vm->_sceneEnterY4); - DebugPrintf("Special exit information:\n"); +bool Debugger_v2::cmdSceneInfo(int argc, const char **argv) { + debugPrintf("Current scene: %d '%s'\n", _vm->_currentScene, _vm->_sceneList[_vm->_currentScene].filename1); + debugPrintf("\n"); + debugPrintf("Exit information:\n"); + debugPrintf("Exit1: leads to %d, position %dx%d\n", int16(_vm->_sceneExit1), _vm->_sceneEnterX1, _vm->_sceneEnterY1); + debugPrintf("Exit2: leads to %d, position %dx%d\n", int16(_vm->_sceneExit2), _vm->_sceneEnterX2, _vm->_sceneEnterY2); + debugPrintf("Exit3: leads to %d, position %dx%d\n", int16(_vm->_sceneExit3), _vm->_sceneEnterX3, _vm->_sceneEnterY3); + debugPrintf("Exit4: leads to %d, position %dx%d\n", int16(_vm->_sceneExit4), _vm->_sceneEnterX4, _vm->_sceneEnterY4); + debugPrintf("Special exit information:\n"); if (!_vm->_specialExitCount) { - DebugPrintf("No special exits.\n"); + debugPrintf("No special exits.\n"); } else { - DebugPrintf("This scene has %d special exits.\n", _vm->_specialExitCount); + debugPrintf("This scene has %d special exits.\n", _vm->_specialExitCount); for (int i = 0; i < _vm->_specialExitCount; ++i) { - DebugPrintf("SpecialExit%d: facing %d, position (x1/y1/x2/y2): %d/%d/%d/%d\n", i, + debugPrintf("SpecialExit%d: facing %d, position (x1/y1/x2/y2): %d/%d/%d/%d\n", i, _vm->_specialExitTable[20 + i], _vm->_specialExitTable[0 + i], _vm->_specialExitTable[5 + i], _vm->_specialExitTable[10 + i], _vm->_specialExitTable[15 + i]); } @@ -379,20 +379,20 @@ bool Debugger_v2::cmd_sceneInfo(int argc, const char **argv) { return true; } -bool Debugger_v2::cmd_characterInfo(int argc, const char **argv) { - DebugPrintf("Main character is in scene: %d '%s'\n", _vm->_mainCharacter.sceneId, _vm->_sceneList[_vm->_mainCharacter.sceneId].filename1); - DebugPrintf("Position: %dx%d\n", _vm->_mainCharacter.x1, _vm->_mainCharacter.y1); - DebugPrintf("Facing: %d\n", _vm->_mainCharacter.facing); - DebugPrintf("Inventory:\n"); +bool Debugger_v2::cmdCharacterInfo(int argc, const char **argv) { + debugPrintf("Main character is in scene: %d '%s'\n", _vm->_mainCharacter.sceneId, _vm->_sceneList[_vm->_mainCharacter.sceneId].filename1); + debugPrintf("Position: %dx%d\n", _vm->_mainCharacter.x1, _vm->_mainCharacter.y1); + debugPrintf("Facing: %d\n", _vm->_mainCharacter.facing); + debugPrintf("Inventory:\n"); for (int i = 0; i < 20; ++i) { - DebugPrintf("%-2d ", int8(_vm->_mainCharacter.inventory[i])); + debugPrintf("%-2d ", int8(_vm->_mainCharacter.inventory[i])); if (i == 9 || i == 19) - DebugPrintf("\n"); + debugPrintf("\n"); } return true; } -bool Debugger_v2::cmd_sceneToFacing(int argc, const char **argv) { +bool Debugger_v2::cmdSceneToFacing(int argc, const char **argv) { if (argc == 2) { int facing = atoi(argv[1]); int16 exit = -1; @@ -418,26 +418,26 @@ bool Debugger_v2::cmd_sceneToFacing(int argc, const char **argv) { break; } - DebugPrintf("Exit to facing %d leads to room %d.\n", facing, exit); + debugPrintf("Exit to facing %d leads to room %d.\n", facing, exit); } else { - DebugPrintf("Usage: %s <facing>\n", argv[0]); + debugPrintf("Usage: %s <facing>\n", argv[0]); } return true; } -bool Debugger_v2::cmd_giveItem(int argc, const char **argv) { +bool Debugger_v2::cmdGiveItem(int argc, const char **argv) { if (argc == 2) { int item = atoi(argv[1]); if (item < -1 || item > _vm->engineDesc().maxItemId) { - DebugPrintf("itemid must be any value between (including) -1 and %d\n", _vm->engineDesc().maxItemId); + debugPrintf("itemid must be any value between (including) -1 and %d\n", _vm->engineDesc().maxItemId); return true; } _vm->setHandItem(item); } else { - DebugPrintf("Syntax: give <itemid>\n"); + debugPrintf("Syntax: give <itemid>\n"); } return true; @@ -449,22 +449,22 @@ Debugger_HoF::Debugger_HoF(KyraEngine_HoF *vm) : Debugger_v2(vm), _vm(vm) { } void Debugger_HoF::initialize() { - DCmd_Register("pass_codes", WRAP_METHOD(Debugger_HoF, cmd_passcodes)); + registerCmd("pass_codes", WRAP_METHOD(Debugger_HoF, cmdPasscodes)); Debugger_v2::initialize(); } -bool Debugger_HoF::cmd_passcodes(int argc, const char **argv) { +bool Debugger_HoF::cmdPasscodes(int argc, const char **argv) { if (argc == 2) { int val = atoi(argv[1]); if (val < 0 || val > 1) { - DebugPrintf("value must be either 1 (on) or 0 (off)\n"); + debugPrintf("value must be either 1 (on) or 0 (off)\n"); return true; } _vm->_dbgPass = val; } else { - DebugPrintf("Syntax: pass_codes <0/1>\n"); + debugPrintf("Syntax: pass_codes <0/1>\n"); } return true; @@ -482,43 +482,43 @@ Debugger_EoB::Debugger_EoB(EoBCoreEngine *vm) : Debugger(vm), _vm(vm) { } void Debugger_EoB::initialize() { - DCmd_Register("import_savefile", WRAP_METHOD(Debugger_EoB, cmd_importSaveFile)); - DCmd_Register("save_original", WRAP_METHOD(Debugger_EoB, cmd_saveOriginal)); - DCmd_Register("list_monsters", WRAP_METHOD(Debugger_EoB, cmd_listMonsters)); - DCmd_Register("show_position", WRAP_METHOD(Debugger_EoB, cmd_showPosition)); - DCmd_Register("set_position", WRAP_METHOD(Debugger_EoB, cmd_setPosition)); - DCmd_Register("open_door", WRAP_METHOD(Debugger_EoB, cmd_openDoor)); - DCmd_Register("close_door", WRAP_METHOD(Debugger_EoB, cmd_closeDoor)); - DCmd_Register("list_flags", WRAP_METHOD(Debugger_EoB, cmd_listFlags)); - DCmd_Register("set_flag", WRAP_METHOD(Debugger_EoB, cmd_setFlag)); - DCmd_Register("clear_flag", WRAP_METHOD(Debugger_EoB, cmd_clearFlag)); -} - -bool Debugger_EoB::cmd_importSaveFile(int argc, const char **argv) { + registerCmd("import_savefile", WRAP_METHOD(Debugger_EoB, cmdImportSaveFile)); + registerCmd("save_original", WRAP_METHOD(Debugger_EoB, cmdSaveOriginal)); + registerCmd("list_monsters", WRAP_METHOD(Debugger_EoB, cmdListMonsters)); + registerCmd("show_position", WRAP_METHOD(Debugger_EoB, cmdShowPosition)); + registerCmd("set_position", WRAP_METHOD(Debugger_EoB, cmdSetPosition)); + registerCmd("open_door", WRAP_METHOD(Debugger_EoB, cmdOpenDoor)); + registerCmd("close_door", WRAP_METHOD(Debugger_EoB, cmdCloseDoor)); + registerCmd("list_flags", WRAP_METHOD(Debugger_EoB, cmdListFlags)); + registerCmd("set_flag", WRAP_METHOD(Debugger_EoB, cmdSetFlag)); + registerCmd("clear_flag", WRAP_METHOD(Debugger_EoB, cmdClearFlag)); +} + +bool Debugger_EoB::cmdImportSaveFile(int argc, const char **argv) { if (!_vm->_allowImport) { - DebugPrintf("This command only works from the main menu.\n"); + debugPrintf("This command only works from the main menu.\n"); return true; } if (argc == 3) { int slot = atoi(argv[1]); if (slot < -1 || slot > 989) { - DebugPrintf("slot must be between (including) -1 and 989 \n"); + debugPrintf("slot must be between (including) -1 and 989 \n"); return true; } - DebugPrintf(_vm->importOriginalSaveFile(slot, argv[2]) ? "Success.\n" : "Failure.\n"); + debugPrintf(_vm->importOriginalSaveFile(slot, argv[2]) ? "Success.\n" : "Failure.\n"); _vm->loadItemDefs(); } else { - DebugPrintf("Syntax: import_savefile <dest slot> <source file>\n (Imports source save game file to dest slot.)\n import_savefile -1\n (Imports all original save game files found and puts them into the first available slots.)\n\n"); + debugPrintf("Syntax: import_savefile <dest slot> <source file>\n (Imports source save game file to dest slot.)\n import_savefile -1\n (Imports all original save game files found and puts them into the first available slots.)\n\n"); } return true; } -bool Debugger_EoB::cmd_saveOriginal(int argc, const char **argv) { +bool Debugger_EoB::cmdSaveOriginal(int argc, const char **argv) { if (!_vm->_runFlag) { - DebugPrintf("This command doesn't work during intro or outro sequences,\nfrom the main menu or from the character generation.\n"); + debugPrintf("This command doesn't work during intro or outro sequences,\nfrom the main menu or from the character generation.\n"); return true; } @@ -535,57 +535,57 @@ bool Debugger_EoB::cmd_saveOriginal(int argc, const char **argv) { if (_vm->saveAsOriginalSaveFile()) { Common::FSNode nf = nd.getChild(Common::String::format("EOBDATA.SAV")); if (nf.isReadable()) - DebugPrintf("Saved to file: %s\n\n", nf.getPath().c_str()); + debugPrintf("Saved to file: %s\n\n", nf.getPath().c_str()); else - DebugPrintf("Failure.\n"); + debugPrintf("Failure.\n"); } else { - DebugPrintf("Failure.\n"); + debugPrintf("Failure.\n"); } } else { - DebugPrintf("Syntax: save_original\n (Saves game in original file format to a file which can be used with the orginal game executable.)\n\n"); + debugPrintf("Syntax: save_original\n (Saves game in original file format to a file which can be used with the orginal game executable.)\n\n"); } return true; } else if (argc == 2) { int slot = atoi(argv[1]); if (slot < 0 || slot > 5) { - DebugPrintf("Slot must be between (including) 0 and 5.\n"); + debugPrintf("Slot must be between (including) 0 and 5.\n"); } else if (_vm->saveAsOriginalSaveFile(slot)) { Common::FSNode nf = nd.getChild(Common::String::format("EOBDATA%d.SAV", slot)); if (nf.isReadable()) - DebugPrintf("Saved to file: %s\n\n", nf.getPath().c_str()); + debugPrintf("Saved to file: %s\n\n", nf.getPath().c_str()); else - DebugPrintf("Failure.\n"); + debugPrintf("Failure.\n"); } else { - DebugPrintf("Failure.\n"); + debugPrintf("Failure.\n"); } return true; } - DebugPrintf("Syntax: save_original <slot>\n (Saves game in original file format to a file which can be used with the orginal game executable.\n A save slot between 0 and 5 must be specified.)\n\n"); + debugPrintf("Syntax: save_original <slot>\n (Saves game in original file format to a file which can be used with the orginal game executable.\n A save slot between 0 and 5 must be specified.)\n\n"); return true; } -bool Debugger_EoB::cmd_listMonsters(int, const char **) { - DebugPrintf("\nCurrent level: %d\n----------------------\n\n", _vm->_currentLevel); - DebugPrintf("Id Type Unit Block Position Direction Sub Level Mode Dst.block HP Flags\n--------------------------------------------------------------------------------------------------------------\n"); +bool Debugger_EoB::cmdListMonsters(int, const char **) { + debugPrintf("\nCurrent level: %d\n----------------------\n\n", _vm->_currentLevel); + debugPrintf("Id Type Unit Block Position Direction Sub Level Mode Dst.block HP Flags\n--------------------------------------------------------------------------------------------------------------\n"); for (int i = 0; i < 30; i++) { EoBMonsterInPlay *m = &_vm->_monsters[i]; - DebugPrintf("%.02d %.02d %.02d 0x%.04x %d %d %d %.02d 0x%.04x %.03d/%.03d 0x%.02x\n", i, m->type, m->unit, m->block, m->pos, m->dir, m->sub, m->mode, m->dest, m->hitPointsCur, m->hitPointsMax, m->flags); + debugPrintf("%.02d %.02d %.02d 0x%.04x %d %d %d %.02d 0x%.04x %.03d/%.03d 0x%.02x\n", i, m->type, m->unit, m->block, m->pos, m->dir, m->sub, m->mode, m->dest, m->hitPointsCur, m->hitPointsMax, m->flags); } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } -bool Debugger_EoB::cmd_showPosition(int, const char **) { - DebugPrintf("\nCurrent level: %d\nCurrent Sub Level: %d\nCurrent block: %d (0x%.04x)\nNext block: %d (0x%.04x)\nCurrent direction: %d\n\n", _vm->_currentLevel, _vm->_currentSub, _vm->_currentBlock, _vm->_currentBlock, _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection), _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection), _vm->_currentDirection); +bool Debugger_EoB::cmdShowPosition(int, const char **) { + debugPrintf("\nCurrent level: %d\nCurrent Sub Level: %d\nCurrent block: %d (0x%.04x)\nNext block: %d (0x%.04x)\nCurrent direction: %d\n\n", _vm->_currentLevel, _vm->_currentSub, _vm->_currentBlock, _vm->_currentBlock, _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection), _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection), _vm->_currentDirection); return true; } -bool Debugger_EoB::cmd_setPosition(int argc, const char **argv) { +bool Debugger_EoB::cmdSetPosition(int argc, const char **argv) { if (argc == 4) { _vm->_currentBlock = atoi(argv[3]); int sub = atoi(argv[2]); @@ -593,7 +593,7 @@ bool Debugger_EoB::cmd_setPosition(int argc, const char **argv) { int maxLevel = (_vm->game() == GI_EOB1) ? 12 : 16; if (level < 1 || level > maxLevel) { - DebugPrintf("<level> must be a value from 1 to %d.\n\n", maxLevel); + debugPrintf("<level> must be a value from 1 to %d.\n\n", maxLevel); return true; } @@ -613,83 +613,83 @@ bool Debugger_EoB::cmd_setPosition(int argc, const char **argv) { _vm->_sceneUpdateRequired = true; _vm->gui_drawAllCharPortraitsWithStats(); - DebugPrintf("Success.\n\n"); + debugPrintf("Success.\n\n"); } else { - DebugPrintf("Syntax: set_position <level>, <sub level>, <block>\n"); - DebugPrintf(" (Warning: The sub level and block position parameters will not be checked. Invalid parameters may cause problems.)\n\n"); + debugPrintf("Syntax: set_position <level>, <sub level>, <block>\n"); + debugPrintf(" (Warning: The sub level and block position parameters will not be checked. Invalid parameters may cause problems.)\n\n"); } return true; } -bool Debugger_EoB::cmd_openDoor(int, const char **) { - DebugPrintf("Warning: Using this command may cause glitches.\n"); +bool Debugger_EoB::cmdOpenDoor(int, const char **) { + debugPrintf("Warning: Using this command may cause glitches.\n"); uint16 block = _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection); int c = (_vm->_wllWallFlags[_vm->_levelBlockProperties[block].walls[0]] & 8) ? 0 : 1; int v = _vm->_levelBlockProperties[block].walls[c]; int flg = (_vm->_flags.gameID == GI_EOB1) ? 1 : 0x10; if (_vm->_wllWallFlags[v] & flg) { - DebugPrintf("Couldn't open any door. Make sure you're facing the door you wish to open and standing right in front of it.\n\n"); + debugPrintf("Couldn't open any door. Make sure you're facing the door you wish to open and standing right in front of it.\n\n"); } else { _vm->openDoor(block); - DebugPrintf("Trying to open door at block %d.\n\n", block); + debugPrintf("Trying to open door at block %d.\n\n", block); } return true; } -bool Debugger_EoB::cmd_closeDoor(int, const char **) { - DebugPrintf("Warning: Using this command may cause glitches.\n"); +bool Debugger_EoB::cmdCloseDoor(int, const char **) { + debugPrintf("Warning: Using this command may cause glitches.\n"); uint16 block = _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection); int c = (_vm->_wllWallFlags[_vm->_levelBlockProperties[block].walls[0]] & 8) ? 0 : 1; int v = _vm->_levelBlockProperties[block].walls[c]; if ((_vm->_flags.gameID == GI_EOB1 && !(_vm->_wllWallFlags[v] & 1)) || (_vm->_flags.gameID == GI_EOB2 && (_vm->_wllWallFlags[v] & 0x20))) { - DebugPrintf("Couldn't close any door. Make sure you're facing the door you wish to close and standing right in front of it.\n\n"); + debugPrintf("Couldn't close any door. Make sure you're facing the door you wish to close and standing right in front of it.\n\n"); } else { _vm->closeDoor(block); - DebugPrintf("Trying to close door at block %d.\n\n", block); + debugPrintf("Trying to close door at block %d.\n\n", block); } return true; } -bool Debugger_EoB::cmd_listFlags(int, const char **) { - DebugPrintf("Flag Status\n----------------------\n\n"); +bool Debugger_EoB::cmdListFlags(int, const char **) { + debugPrintf("Flag Status\n----------------------\n\n"); for (int i = 0; i < 32; i++) { uint32 flag = 1 << i; - DebugPrintf("%.2d %s\n", i, _vm->checkScriptFlags(flag) ? "TRUE" : "FALSE"); + debugPrintf("%.2d %s\n", i, _vm->checkScriptFlags(flag) ? "TRUE" : "FALSE"); } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } -bool Debugger_EoB::cmd_setFlag(int argc, const char **argv) { +bool Debugger_EoB::cmdSetFlag(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Syntax: set_flag <flag>\n\n"); + debugPrintf("Syntax: set_flag <flag>\n\n"); return true; } int flag = atoi(argv[1]); if (flag < 0 || flag > 31) { - DebugPrintf("<flag> must be a value from 0 to 31.\n\n"); + debugPrintf("<flag> must be a value from 0 to 31.\n\n"); } else { _vm->setScriptFlags(1 << flag); - DebugPrintf("Flag '%.2d' has been set.\n\n", flag); + debugPrintf("Flag '%.2d' has been set.\n\n", flag); } return true; } -bool Debugger_EoB::cmd_clearFlag(int argc, const char **argv) { +bool Debugger_EoB::cmdClearFlag(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Syntax: clear_flag <flag>\n\n"); + debugPrintf("Syntax: clear_flag <flag>\n\n"); return true; } int flag = atoi(argv[1]); if (flag < 0 || flag > 31) { - DebugPrintf("<flag> must be a value from 0 to 31.\n\n"); + debugPrintf("<flag> must be a value from 0 to 31.\n\n"); } else { _vm->clearScriptFlags(1 << flag); - DebugPrintf("Flag '%.2d' has been cleared.\n\n", flag); + debugPrintf("Flag '%.2d' has been cleared.\n\n", flag); } return true; diff --git a/engines/kyra/debugger.h b/engines/kyra/debugger.h index aaf7c51c18..15cee2d592 100644 --- a/engines/kyra/debugger.h +++ b/engines/kyra/debugger.h @@ -42,15 +42,15 @@ public: protected: KyraEngine_v1 *_vm; - bool cmd_setScreenDebug(int argc, const char **argv); - bool cmd_loadPalette(int argc, const char **argv); - bool cmd_showFacings(int argc, const char **argv); - bool cmd_gameSpeed(int argc, const char **argv); - bool cmd_listFlags(int argc, const char **argv); - bool cmd_toggleFlag(int argc, const char **argv); - bool cmd_queryFlag(int argc, const char **argv); - bool cmd_listTimers(int argc, const char **argv); - bool cmd_setTimerCountdown(int argc, const char **argv); + bool cmdSetScreenDebug(int argc, const char **argv); + bool cmdLoadPalette(int argc, const char **argv); + bool cmdShowFacings(int argc, const char **argv); + bool cmdGameSpeed(int argc, const char **argv); + bool cmdListFlags(int argc, const char **argv); + bool cmdToggleFlag(int argc, const char **argv); + bool cmdQueryFlag(int argc, const char **argv); + bool cmdListTimers(int argc, const char **argv); + bool cmdSetTimerCountdown(int argc, const char **argv); }; class Debugger_LoK : public Debugger { @@ -62,10 +62,10 @@ public: protected: KyraEngine_LoK *_vm; - bool cmd_enterRoom(int argc, const char **argv); - bool cmd_listScenes(int argc, const char **argv); - bool cmd_giveItem(int argc, const char **argv); - bool cmd_listBirthstones(int argc, const char **argv); + bool cmdEnterRoom(int argc, const char **argv); + bool cmdListScenes(int argc, const char **argv); + bool cmdGiveItem(int argc, const char **argv); + bool cmdListBirthstones(int argc, const char **argv); }; class Debugger_v2 : public Debugger { @@ -77,12 +77,12 @@ public: protected: KyraEngine_v2 *_vm; - bool cmd_enterScene(int argc, const char **argv); - bool cmd_listScenes(int argc, const char **argv); - bool cmd_sceneInfo(int argc, const char **argv); - bool cmd_characterInfo(int argc, const char **argv); - bool cmd_sceneToFacing(int argc, const char **argv); - bool cmd_giveItem(int argc, const char **argv); + bool cmdEnterScene(int argc, const char **argv); + bool cmdListScenes(int argc, const char **argv); + bool cmdSceneInfo(int argc, const char **argv); + bool cmdCharacterInfo(int argc, const char **argv); + bool cmdSceneToFacing(int argc, const char **argv); + bool cmdGiveItem(int argc, const char **argv); }; class Debugger_HoF : public Debugger_v2 { @@ -93,7 +93,7 @@ public: protected: KyraEngine_HoF *_vm; - bool cmd_passcodes(int argc, const char **argv); + bool cmdPasscodes(int argc, const char **argv); }; #ifdef ENABLE_LOL @@ -119,16 +119,16 @@ public: protected: EoBCoreEngine *_vm; - bool cmd_importSaveFile(int argc, const char **argv); - bool cmd_saveOriginal(int argc, const char **argv); - bool cmd_listMonsters(int argc, const char **argv); - bool cmd_showPosition(int argc, const char **argv); - bool cmd_setPosition(int argc, const char **argv); - bool cmd_openDoor(int argc, const char **argv); - bool cmd_closeDoor(int argc, const char **argv); - bool cmd_listFlags(int argc, const char **argv); - bool cmd_setFlag(int argc, const char **argv); - bool cmd_clearFlag(int argc, const char **argv); + bool cmdImportSaveFile(int argc, const char **argv); + bool cmdSaveOriginal(int argc, const char **argv); + bool cmdListMonsters(int argc, const char **argv); + bool cmdShowPosition(int argc, const char **argv); + bool cmdSetPosition(int argc, const char **argv); + bool cmdOpenDoor(int argc, const char **argv); + bool cmdCloseDoor(int argc, const char **argv); + bool cmdListFlags(int argc, const char **argv); + bool cmdSetFlag(int argc, const char **argv); + bool cmdClearFlag(int argc, const char **argv); }; #endif // ENABLE_EOB diff --git a/engines/lastexpress/debug.cpp b/engines/lastexpress/debug.cpp index 6c2d833271..57943f9a8d 100644 --- a/engines/lastexpress/debug.cpp +++ b/engines/lastexpress/debug.cpp @@ -60,33 +60,33 @@ Debugger::Debugger(LastExpressEngine *engine) : _engine(engine), _command(NULL), // Register the debugger commands // General - DCmd_Register("help", WRAP_METHOD(Debugger, cmdHelp)); + registerCmd("help", WRAP_METHOD(Debugger, cmdHelp)); // Data - DCmd_Register("ls", WRAP_METHOD(Debugger, cmdListFiles)); - DCmd_Register("dump", WRAP_METHOD(Debugger, cmdDumpFiles)); + registerCmd("ls", WRAP_METHOD(Debugger, cmdListFiles)); + registerCmd("dump", WRAP_METHOD(Debugger, cmdDumpFiles)); - DCmd_Register("showframe", WRAP_METHOD(Debugger, cmdShowFrame)); - DCmd_Register("showbg", WRAP_METHOD(Debugger, cmdShowBg)); - DCmd_Register("playseq", WRAP_METHOD(Debugger, cmdPlaySeq)); - DCmd_Register("playsnd", WRAP_METHOD(Debugger, cmdPlaySnd)); - DCmd_Register("playsbe", WRAP_METHOD(Debugger, cmdPlaySbe)); - DCmd_Register("playnis", WRAP_METHOD(Debugger, cmdPlayNis)); + registerCmd("showframe", WRAP_METHOD(Debugger, cmdShowFrame)); + registerCmd("showbg", WRAP_METHOD(Debugger, cmdShowBg)); + registerCmd("playseq", WRAP_METHOD(Debugger, cmdPlaySeq)); + registerCmd("playsnd", WRAP_METHOD(Debugger, cmdPlaySnd)); + registerCmd("playsbe", WRAP_METHOD(Debugger, cmdPlaySbe)); + registerCmd("playnis", WRAP_METHOD(Debugger, cmdPlayNis)); // Scene & interaction - DCmd_Register("loadscene", WRAP_METHOD(Debugger, cmdLoadScene)); - DCmd_Register("fight", WRAP_METHOD(Debugger, cmdFight)); - DCmd_Register("beetle", WRAP_METHOD(Debugger, cmdBeetle)); + registerCmd("loadscene", WRAP_METHOD(Debugger, cmdLoadScene)); + registerCmd("fight", WRAP_METHOD(Debugger, cmdFight)); + registerCmd("beetle", WRAP_METHOD(Debugger, cmdBeetle)); // Game - DCmd_Register("delta", WRAP_METHOD(Debugger, cmdTimeDelta)); - DCmd_Register("time", WRAP_METHOD(Debugger, cmdTime)); - DCmd_Register("show", WRAP_METHOD(Debugger, cmdShow)); - DCmd_Register("entity", WRAP_METHOD(Debugger, cmdEntity)); + registerCmd("delta", WRAP_METHOD(Debugger, cmdTimeDelta)); + registerCmd("time", WRAP_METHOD(Debugger, cmdTime)); + registerCmd("show", WRAP_METHOD(Debugger, cmdShow)); + registerCmd("entity", WRAP_METHOD(Debugger, cmdEntity)); // Misc - DCmd_Register("chapter", WRAP_METHOD(Debugger, cmdSwitchChapter)); - DCmd_Register("clear", WRAP_METHOD(Debugger, cmdClear)); + registerCmd("chapter", WRAP_METHOD(Debugger, cmdSwitchChapter)); + registerCmd("clear", WRAP_METHOD(Debugger, cmdClear)); resetCommand(); @@ -146,7 +146,7 @@ void Debugger::copyCommand(int argc, const char **argv) { } // Exit the debugger! - Cmd_Exit(0, 0); + cmdExit(0, 0); } void Debugger::callCommand() { @@ -156,7 +156,7 @@ void Debugger::callCommand() { bool Debugger::loadArchive(int index) { if (index < 1 || index > 3) { - DebugPrintf("Invalid cd number (was: %d, valid: [1-3])\n", index); + debugPrintf("Invalid cd number (was: %d, valid: [1-3])\n", index); return false; } @@ -198,36 +198,36 @@ void Debugger::restoreArchive() const { // Debugger commands ////////////////////////////////////////////////////////////////////////// bool Debugger::cmdHelp(int, const char **) { - DebugPrintf("Debug flags\n"); - DebugPrintf("-----------\n"); - DebugPrintf(" debugflag_list - Lists the available debug flags and their status\n"); - DebugPrintf(" debugflag_enable - Enables a debug flag\n"); - DebugPrintf(" debugflag_disable - Disables a debug flag\n"); - DebugPrintf("\n"); - DebugPrintf("Commands\n"); - DebugPrintf("--------\n"); - DebugPrintf(" ls - list files in the archive\n"); - DebugPrintf(" dump - dump a list of files in all archives\n"); - DebugPrintf("\n"); - DebugPrintf(" showframe - show a frame from a sequence\n"); - DebugPrintf(" showbg - show a background\n"); - DebugPrintf(" playseq - play a sequence\n"); - DebugPrintf(" playsnd - play a sound\n"); - DebugPrintf(" playsbe - play a subtitle\n"); - DebugPrintf(" playnis - play an animation\n"); - DebugPrintf("\n"); - DebugPrintf(" loadscene - load a scene\n"); - DebugPrintf(" fight - start a fight\n"); - DebugPrintf(" beetle - start the beetle game\n"); - DebugPrintf("\n"); - DebugPrintf(" delta - Adjust the time delta\n"); - DebugPrintf(" show - show game data\n"); - DebugPrintf(" entity - show entity data\n"); - DebugPrintf("\n"); - DebugPrintf(" loadgame - load a saved game\n"); - DebugPrintf(" chapter - switch to a specific chapter\n"); - DebugPrintf(" clear - clear the screen\n"); - DebugPrintf("\n"); + debugPrintf("Debug flags\n"); + debugPrintf("-----------\n"); + debugPrintf(" debugflag_list - Lists the available debug flags and their status\n"); + debugPrintf(" debugflag_enable - Enables a debug flag\n"); + debugPrintf(" debugflag_disable - Disables a debug flag\n"); + debugPrintf("\n"); + debugPrintf("Commands\n"); + debugPrintf("--------\n"); + debugPrintf(" ls - list files in the archive\n"); + debugPrintf(" dump - dump a list of files in all archives\n"); + debugPrintf("\n"); + debugPrintf(" showframe - show a frame from a sequence\n"); + debugPrintf(" showbg - show a background\n"); + debugPrintf(" playseq - play a sequence\n"); + debugPrintf(" playsnd - play a sound\n"); + debugPrintf(" playsbe - play a subtitle\n"); + debugPrintf(" playnis - play an animation\n"); + debugPrintf("\n"); + debugPrintf(" loadscene - load a scene\n"); + debugPrintf(" fight - start a fight\n"); + debugPrintf(" beetle - start the beetle game\n"); + debugPrintf("\n"); + debugPrintf(" delta - Adjust the time delta\n"); + debugPrintf(" show - show game data\n"); + debugPrintf(" entity - show entity data\n"); + debugPrintf("\n"); + debugPrintf(" loadgame - load a saved game\n"); + debugPrintf(" chapter - switch to a specific chapter\n"); + debugPrintf(" clear - clear the screen\n"); + debugPrintf("\n"); return true; } @@ -252,15 +252,15 @@ bool Debugger::cmdListFiles(int argc, const char **argv) { Common::ArchiveMemberList list; int count = _engine->getResourceManager()->listMatchingMembers(list, filter); - DebugPrintf("Number of matches: %d\n", count); + debugPrintf("Number of matches: %d\n", count); for (Common::ArchiveMemberList::iterator it = list.begin(); it != list.end(); ++it) - DebugPrintf(" %s\n", (*it)->getName().c_str()); + debugPrintf(" %s\n", (*it)->getName().c_str()); // Restore archive if (argc == 3) restoreArchive(); } else { - DebugPrintf("Syntax: ls <filter> (use * for all) (<cd number>)\n"); + debugPrintf("Syntax: ls <filter> (use * for all) (<cd number>)\n"); } return true; @@ -287,7 +287,7 @@ bool Debugger::cmdDumpFiles(int argc, const char **) { for (Common::ArchiveMemberList::iterator it = list.begin(); it != list.end(); ++it) { \ Common::SeekableReadStream *stream = getArchive((*it)->getName()); \ if (!stream) { \ - DebugPrintf("ERROR: Cannot create stream for file: %s\n", (*it)->getName().c_str()); \ + debugPrintf("ERROR: Cannot create stream for file: %s\n", (*it)->getName().c_str()); \ restoreArchive(); \ return true; \ } \ @@ -311,7 +311,7 @@ bool Debugger::cmdDumpFiles(int argc, const char **) { // Restore current loaded archive restoreArchive(); } else { - DebugPrintf("Syntax: dump"); + debugPrintf("Syntax: dump"); } return true; @@ -336,7 +336,7 @@ bool Debugger::cmdShowFrame(int argc, const char **argv) { } if (!_engine->getResourceManager()->hasFile(filename)) { - DebugPrintf("Cannot find file: %s\n", filename.c_str()); + debugPrintf("Cannot find file: %s\n", filename.c_str()); return true; } @@ -345,7 +345,7 @@ bool Debugger::cmdShowFrame(int argc, const char **argv) { _command = WRAP_METHOD(Debugger, cmdShowFrame); copyCommand(argc, argv); - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } else { Sequence sequence(filename); if (sequence.load(getArchive(filename))) { @@ -354,7 +354,7 @@ bool Debugger::cmdShowFrame(int argc, const char **argv) { AnimFrame *frame = sequence.getFrame((uint16)getNumber(argv[2])); if (!frame) { - DebugPrintf("Invalid frame index '%s'\n", argv[2]); + debugPrintf("Invalid frame index '%s'\n", argv[2]); resetCommand(); return true; } @@ -375,7 +375,7 @@ bool Debugger::cmdShowFrame(int argc, const char **argv) { restoreArchive(); } } else { - DebugPrintf("Syntax: cmd_showframe <seqname> <index> (<cd number>)\n"); + debugPrintf("Syntax: cmd_showframe <seqname> <index> (<cd number>)\n"); } return true; } @@ -398,7 +398,7 @@ bool Debugger::cmdShowBg(int argc, const char **argv) { } if (!_engine->getResourceManager()->hasFile(filename + ".BG")) { - DebugPrintf("Cannot find file: %s\n", (filename + ".BG").c_str()); + debugPrintf("Cannot find file: %s\n", (filename + ".BG").c_str()); return true; } @@ -407,7 +407,7 @@ bool Debugger::cmdShowBg(int argc, const char **argv) { _command = WRAP_METHOD(Debugger, cmdShowBg); copyCommand(argc, argv); - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } else { clearBg(GraphicsManager::kBackgroundC); @@ -429,7 +429,7 @@ bool Debugger::cmdShowBg(int argc, const char **argv) { resetCommand(); } } else { - DebugPrintf("Syntax: showbg <bgname> (<cd number>)\n"); + debugPrintf("Syntax: showbg <bgname> (<cd number>)\n"); } return true; } @@ -453,7 +453,7 @@ bool Debugger::cmdPlaySeq(int argc, const char **argv) { } if (!_engine->getResourceManager()->hasFile(filename)) { - DebugPrintf("Cannot find file: %s\n", filename.c_str()); + debugPrintf("Cannot find file: %s\n", filename.c_str()); return true; } @@ -462,7 +462,7 @@ bool Debugger::cmdPlaySeq(int argc, const char **argv) { _command = WRAP_METHOD(Debugger, cmdPlaySeq); copyCommand(argc, argv); - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } else { Sequence *sequence = new Sequence(filename); if (sequence->load(getArchive(filename))) { @@ -510,7 +510,7 @@ bool Debugger::cmdPlaySeq(int argc, const char **argv) { restoreArchive(); } } else { - DebugPrintf("Syntax: playseq <seqname> (<cd number>)\n"); + debugPrintf("Syntax: playseq <seqname> (<cd number>)\n"); } return true; } @@ -537,7 +537,7 @@ bool Debugger::cmdPlaySnd(int argc, const char **argv) { name += ".SND"; if (!_engine->getResourceManager()->hasFile(name)) { - DebugPrintf("Cannot find file: %s\n", name.c_str()); + debugPrintf("Cannot find file: %s\n", name.c_str()); return true; } @@ -548,7 +548,7 @@ bool Debugger::cmdPlaySnd(int argc, const char **argv) { if (argc == 3) restoreArchive(); } else { - DebugPrintf("Syntax: playsnd <sndname> (<cd number>)\n"); + debugPrintf("Syntax: playsnd <sndname> (<cd number>)\n"); } return true; } @@ -573,7 +573,7 @@ bool Debugger::cmdPlaySbe(int argc, const char **argv) { filename += ".sbe"; if (!_engine->getResourceManager()->hasFile(filename)) { - DebugPrintf("Cannot find file: %s\n", filename.c_str()); + debugPrintf("Cannot find file: %s\n", filename.c_str()); return true; } @@ -582,7 +582,7 @@ bool Debugger::cmdPlaySbe(int argc, const char **argv) { _command = WRAP_METHOD(Debugger, cmdPlaySbe); copyCommand(argc, argv); - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } else { SubtitleManager subtitle(_engine->getFont()); if (subtitle.load(getArchive(filename))) { @@ -615,7 +615,7 @@ bool Debugger::cmdPlaySbe(int argc, const char **argv) { resetCommand(); } } else { - DebugPrintf("Syntax: playsbe <sbename> (<cd number>)\n"); + debugPrintf("Syntax: playsbe <sbename> (<cd number>)\n"); } return true; } @@ -639,7 +639,7 @@ bool Debugger::cmdPlayNis(int argc, const char **argv) { // If we got a nis filename, check that the file exists if (name.contains('.') && !_engine->getResourceManager()->hasFile(name)) { - DebugPrintf("Cannot find file: %s\n", name.c_str()); + debugPrintf("Cannot find file: %s\n", name.c_str()); return true; } @@ -648,7 +648,7 @@ bool Debugger::cmdPlayNis(int argc, const char **argv) { _command = WRAP_METHOD(Debugger, cmdPlayNis); copyCommand(argc, argv); - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } else { // Make sure we are not called in a loop _numParams = 0; @@ -672,7 +672,7 @@ bool Debugger::cmdPlayNis(int argc, const char **argv) { resetCommand(); } } else { - DebugPrintf("Syntax: playnis <nisname.nis or animation index> (<cd number>)\n"); + debugPrintf("Syntax: playnis <nisname.nis or animation index> (<cd number>)\n"); } return true; } @@ -697,7 +697,7 @@ bool Debugger::cmdLoadScene(int argc, const char **argv) { } if (index > 2500) { - DebugPrintf("Error: invalid index value (0-2500)"); + debugPrintf("Error: invalid index value (0-2500)"); return true; } @@ -706,7 +706,7 @@ bool Debugger::cmdLoadScene(int argc, const char **argv) { _command = WRAP_METHOD(Debugger, cmdLoadScene); copyCommand(argc, argv); - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } else { clearBg(GraphicsManager::kBackgroundAll); @@ -718,7 +718,7 @@ bool Debugger::cmdLoadScene(int argc, const char **argv) { // loadSceneObject(scene, i); // if (scene.getHeader() && scene.getHeader()->car == 5 && scene.getHeader()->position == 81) { - // DebugPrintf("Found scene: %d", i); + // debugPrintf("Found scene: %d", i); // // Draw scene found // _engine->getGraphicsManager()->draw(&scene, GraphicsManager::kBackgroundC); @@ -738,7 +738,7 @@ bool Debugger::cmdLoadScene(int argc, const char **argv) { /*********************************************/ Scene *scene = getScenes()->get(index); if (!scene) { - DebugPrintf("Cannot load scene %i from CD %i", index, cd); + debugPrintf("Cannot load scene %i from CD %i", index, cd); resetCommand(); return true; @@ -758,7 +758,7 @@ bool Debugger::cmdLoadScene(int argc, const char **argv) { resetCommand(); } } else { - DebugPrintf("Syntax: loadscene <scene index> (<cd number>)\n"); + debugPrintf("Syntax: loadscene <scene index> (<cd number>)\n"); } return true; } @@ -814,7 +814,7 @@ bool Debugger::cmdFight(int argc, const char **argv) { SceneIndex lastScene = getState()->scene; - getFight()->setup(type) ? DebugPrintf("Lost fight!\n") : DebugPrintf("Won fight!\n"); + getFight()->setup(type) ? debugPrintf("Lost fight!\n") : debugPrintf("Won fight!\n"); // Pause for a second to be able to see the final scene _engine->_system->delayMillis(1000); @@ -837,7 +837,7 @@ bool Debugger::cmdFight(int argc, const char **argv) { } } else { error: - DebugPrintf("Syntax: fight <id> (id=2001-2005)\n"); + debugPrintf("Syntax: fight <id> (id=2001-2005)\n"); } return true; @@ -968,7 +968,7 @@ bool Debugger::cmdBeetle(int argc, const char **argv) { resetCommand(); } } else { - DebugPrintf("Syntax: beetle\n"); + debugPrintf("Syntax: beetle\n"); } return true; @@ -992,7 +992,7 @@ bool Debugger::cmdTimeDelta(int argc, const char **argv) { getState()->timeDelta = (uint)delta; } else { label_error: - DebugPrintf("Syntax: delta <time delta> (delta=1-500)\n"); + debugPrintf("Syntax: delta <time delta> (delta=1-500)\n"); } return true; @@ -1018,10 +1018,10 @@ bool Debugger::cmdTime(int argc, const char **argv) { uint8 minutes = 0; State::getHourMinutes((uint32)time, &hours, &minutes); - DebugPrintf("%02d:%02d\n", hours, minutes); + debugPrintf("%02d:%02d\n", hours, minutes); } else { label_error: - DebugPrintf("Syntax: time <time to convert> (time=0-INT_MAX)\n"); + debugPrintf("Syntax: time <time to convert> (time=0-INT_MAX)\n"); } return true; @@ -1037,10 +1037,10 @@ label_error: */ bool Debugger::cmdShow(int argc, const char **argv) { #define OUTPUT_DUMP(name, text) \ - DebugPrintf(#name "\n"); \ - DebugPrintf("--------------------------------------------------------------------\n\n"); \ - DebugPrintf("%s", text); \ - DebugPrintf("\n"); + debugPrintf(#name "\n"); \ + debugPrintf("--------------------------------------------------------------------\n\n"); \ + debugPrintf("%s", text); \ + debugPrintf("\n"); if (argc == 2) { @@ -1066,14 +1066,14 @@ bool Debugger::cmdShow(int argc, const char **argv) { } else { label_error: - DebugPrintf("Syntax: state <option>\n"); - DebugPrintf(" state / st\n"); - DebugPrintf(" progress / pr\n"); - DebugPrintf(" flags / fl\n"); - DebugPrintf(" inventory / inv\n"); - DebugPrintf(" objects / obj\n"); - DebugPrintf(" savepoints / pt\n"); - DebugPrintf(" scene / sc\n"); + debugPrintf("Syntax: state <option>\n"); + debugPrintf(" state / st\n"); + debugPrintf(" progress / pr\n"); + debugPrintf(" flags / fl\n"); + debugPrintf(" inventory / inv\n"); + debugPrintf(" objects / obj\n"); + debugPrintf(" savepoints / pt\n"); + debugPrintf(" scene / sc\n"); } return true; @@ -1096,26 +1096,26 @@ bool Debugger::cmdEntity(int argc, const char **argv) { if (index > 39) goto label_error; - DebugPrintf("Entity %s\n", ENTITY_NAME(index)); - DebugPrintf("--------------------------------------------------------------------\n\n"); - DebugPrintf("%s", getEntities()->getData(index)->toString().c_str()); + debugPrintf("Entity %s\n", ENTITY_NAME(index)); + debugPrintf("--------------------------------------------------------------------\n\n"); + debugPrintf("%s", getEntities()->getData(index)->toString().c_str()); // The Player entity does not have any callback data if (index != kEntityPlayer) { EntityData *data = getEntities()->get(index)->getParamData(); for (uint callback = 0; callback < 9; callback++) { - DebugPrintf("Call parameters %d:\n", callback); + debugPrintf("Call parameters %d:\n", callback); for (byte ix = 0; ix < 4; ix++) - DebugPrintf(" %s", data->getParameters(callback, ix)->toString().c_str()); + debugPrintf(" %s", data->getParameters(callback, ix)->toString().c_str()); } } - DebugPrintf("\n"); + debugPrintf("\n"); } else { label_error: - DebugPrintf("Syntax: entity <index>\n"); + debugPrintf("Syntax: entity <index>\n"); for (int i = 0; i < 40; i += 4) - DebugPrintf(" %s - %d %s - %d %s - %d %s - %d\n", ENTITY_NAME(i), i, ENTITY_NAME(i+1), i+1, ENTITY_NAME(i+2), i+2, ENTITY_NAME(i+3), i+3); + debugPrintf(" %s - %d %s - %d %s - %d %s - %d\n", ENTITY_NAME(i), i, ENTITY_NAME(i+1), i+1, ENTITY_NAME(i+2), i+2, ENTITY_NAME(i+3), i+3); } return true; @@ -1152,7 +1152,7 @@ bool Debugger::cmdSwitchChapter(int argc, const char **argv) { } } else { error: - DebugPrintf("Syntax: chapter <id> (id=2-6)\n"); + debugPrintf("Syntax: chapter <id> (id=2-6)\n"); } return true; @@ -1172,7 +1172,7 @@ bool Debugger::cmdClear(int argc, const char **) { askForRedraw(); redrawScreen(); } else { - DebugPrintf("Syntax: clear - clear the screen\n"); + debugPrintf("Syntax: clear - clear the screen\n"); } return true; diff --git a/engines/lure/debugger.cpp b/engines/lure/debugger.cpp index bbaa68befa..032186717d 100644 --- a/engines/lure/debugger.cpp +++ b/engines/lure/debugger.cpp @@ -35,20 +35,20 @@ namespace Lure { Debugger::Debugger(): GUI::Debugger() { - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("enter", WRAP_METHOD(Debugger, cmd_enterRoom)); - DCmd_Register("rooms", WRAP_METHOD(Debugger, cmd_listRooms)); - DCmd_Register("fields", WRAP_METHOD(Debugger, cmd_listFields)); - DCmd_Register("setfield", WRAP_METHOD(Debugger, cmd_setField)); - DCmd_Register("queryfield", WRAP_METHOD(Debugger, cmd_queryField)); - DCmd_Register("give", WRAP_METHOD(Debugger, cmd_giveItem)); - DCmd_Register("hotspots", WRAP_METHOD(Debugger, cmd_hotspots)); - DCmd_Register("hotspot", WRAP_METHOD(Debugger, cmd_hotspot)); - DCmd_Register("room", WRAP_METHOD(Debugger, cmd_room)); - DCmd_Register("showanim", WRAP_METHOD(Debugger, cmd_showAnim)); - DCmd_Register("strings", WRAP_METHOD(Debugger, cmd_saveStrings)); - DCmd_Register("debug", WRAP_METHOD(Debugger, cmd_debug)); - DCmd_Register("script", WRAP_METHOD(Debugger, cmd_script)); + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("enter", WRAP_METHOD(Debugger, cmd_enterRoom)); + registerCmd("rooms", WRAP_METHOD(Debugger, cmd_listRooms)); + registerCmd("fields", WRAP_METHOD(Debugger, cmd_listFields)); + registerCmd("setfield", WRAP_METHOD(Debugger, cmd_setField)); + registerCmd("queryfield", WRAP_METHOD(Debugger, cmd_queryField)); + registerCmd("give", WRAP_METHOD(Debugger, cmd_giveItem)); + registerCmd("hotspots", WRAP_METHOD(Debugger, cmd_hotspots)); + registerCmd("hotspot", WRAP_METHOD(Debugger, cmd_hotspot)); + registerCmd("room", WRAP_METHOD(Debugger, cmd_room)); + registerCmd("showanim", WRAP_METHOD(Debugger, cmd_showAnim)); + registerCmd("strings", WRAP_METHOD(Debugger, cmd_saveStrings)); + registerCmd("debug", WRAP_METHOD(Debugger, cmd_debug)); + registerCmd("script", WRAP_METHOD(Debugger, cmd_script)); } static int strToInt(const char *s) { @@ -88,7 +88,7 @@ bool Debugger::cmd_enterRoom(int argc, const char **argv) { // Validate that it's an existing room if (res.getRoom(roomNumber) == NULL) { - DebugPrintf("specified number was not a valid room\n"); + debugPrintf("specified number was not a valid room\n"); return true; } @@ -105,9 +105,9 @@ bool Debugger::cmd_enterRoom(int argc, const char **argv) { return false; } - DebugPrintf("Syntax: room <roomnum> [<remoteview>]\n"); - DebugPrintf("A non-zero value for reomteview will change the room without "); - DebugPrintf("moving the player.\n"); + debugPrintf("Syntax: room <roomnum> [<remoteview>]\n"); + debugPrintf("A non-zero value for reomteview will change the room without "); + debugPrintf("moving the player.\n"); return true; } @@ -117,7 +117,7 @@ bool Debugger::cmd_listRooms(int argc, const char **argv) { char buffer[MAX_DESC_SIZE]; int ctr = 0; - DebugPrintf("Available rooms are:\n"); + debugPrintf("Available rooms are:\n"); for (RoomDataList::iterator i = rooms.begin(); i != rooms.end(); ++i) { RoomData const &room = **i; // Explictly note the second drawbridge room as "Alt" @@ -128,20 +128,20 @@ bool Debugger::cmd_listRooms(int argc, const char **argv) { strings.getString(room.roomNumber, buffer); } - DebugPrintf("#%d - %s", room.roomNumber, buffer); + debugPrintf("#%d - %s", room.roomNumber, buffer); - if (++ctr % 3 == 0) DebugPrintf("\n"); + if (++ctr % 3 == 0) debugPrintf("\n"); else { // Write out spaces between columns int numSpaces = 25 - strlen(buffer) - (room.roomNumber >= 10 ? 2 : 1); char *s = buffer; while (numSpaces-- > 0) *s++ = ' '; *s = '\0'; - DebugPrintf("%s", buffer); + debugPrintf("%s", buffer); } } - DebugPrintf("\n"); - DebugPrintf("Current room: %d\n", Room::getReference().roomNumber()); + debugPrintf("\n"); + debugPrintf("Current room: %d\n", Room::getReference().roomNumber()); return true; } @@ -150,11 +150,11 @@ bool Debugger::cmd_listFields(int argc, const char **argv) { ValueTableData &fields = Resources::getReference().fieldList(); for (int ctr = 0; ctr < fields.size(); ++ctr) { - DebugPrintf("(%-2d): %-5d", ctr, fields.getField(ctr)); + debugPrintf("(%-2d): %-5d", ctr, fields.getField(ctr)); if (!((ctr + 1) % 7)) - DebugPrintf("\n"); + debugPrintf("\n"); } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } @@ -167,13 +167,13 @@ bool Debugger::cmd_setField(int argc, const char **argv) { if ((fieldNum < 0) || (fieldNum >= fields.size())) { // Invalid field number - DebugPrintf("Invalid field number specified\n"); + debugPrintf("Invalid field number specified\n"); } else { // Set the field value fields.setField(fieldNum, value); } } else { - DebugPrintf("Syntax: setfield <field_number> <value>\n"); + debugPrintf("Syntax: setfield <field_number> <value>\n"); } return true; @@ -186,14 +186,14 @@ bool Debugger::cmd_queryField(int argc, const char **argv) { int fieldNum = strToInt(argv[1]); if ((fieldNum < 0) || (fieldNum >= fields.size())) { // Invalid field number - DebugPrintf("Invalid field number specified\n"); + debugPrintf("Invalid field number specified\n"); } else { // Get the field value - DebugPrintf("Field %d is %d (%xh)\n", fieldNum, + debugPrintf("Field %d is %d (%xh)\n", fieldNum, fields.getField(fieldNum), fields.getField(fieldNum)); } } else { - DebugPrintf("Syntax: queryfield <field_num>\n"); + debugPrintf("Syntax: queryfield <field_num>\n"); } return true; @@ -215,18 +215,18 @@ bool Debugger::cmd_giveItem(int argc, const char **argv) { charHotspot = res.getHotspot(charNum); if (itemHotspot == NULL) { - DebugPrintf("The specified item does not exist\n"); + debugPrintf("The specified item does not exist\n"); } else if (itemNum < 0x408) { - DebugPrintf("The specified item number is not an object\n"); + debugPrintf("The specified item number is not an object\n"); } else if ((charNum < PLAYER_ID) || (charNum >= 0x408) || (charHotspot == NULL)) { - DebugPrintf("The specified character does not exist"); + debugPrintf("The specified character does not exist"); } else { // Set the item's room number to be the destination character itemHotspot->roomNumber = charNum; } } else { - DebugPrintf("Syntax: give <item_id> [<character_id>]\n"); + debugPrintf("Syntax: give <item_id> [<character_id>]\n"); } return true; @@ -248,7 +248,7 @@ bool Debugger::cmd_hotspots(int argc, const char **argv) { if (hotspot.nameId() == 0) strcpy(buffer, "none"); else strings.getString(hotspot.nameId(), buffer); - DebugPrintf("%4xh - %s pos=(%d,%d,%d)\n", hotspot.hotspotId(), buffer, + debugPrintf("%4xh - %s pos=(%d,%d,%d)\n", hotspot.hotspotId(), buffer, hotspot.x(), hotspot.y(), hotspot.roomNumber()); } } else { @@ -263,16 +263,16 @@ bool Debugger::cmd_hotspots(int argc, const char **argv) { if (hotspot.nameId == 0) strcpy(buffer, "none"); else strings.getString(hotspot.nameId, buffer); - DebugPrintf("%4xh - %s pos=(%d,%d,%d)\n", hotspot.hotspotId, buffer, + debugPrintf("%4xh - %s pos=(%d,%d,%d)\n", hotspot.hotspotId, buffer, hotspot.startX, hotspot.startY, hotspot.roomNumber); } } } } else { - DebugPrintf("Syntax: hotspots ['active' | ['room' | 'room' '<room_number>']]\n"); - DebugPrintf("Gives a list of all the currently active hotspots, or the hotspots\n"); - DebugPrintf("present in either the current room or a designated one\n"); + debugPrintf("Syntax: hotspots ['active' | ['room' | 'room' '<room_number>']]\n"); + debugPrintf("Gives a list of all the currently active hotspots, or the hotspots\n"); + debugPrintf("present in either the current room or a designated one\n"); } return true; @@ -287,12 +287,12 @@ bool Debugger::cmd_hotspot(int argc, const char **argv) { Hotspot *h; if (argc < 2) { - DebugPrintf("hotspot <hotspot_id> ['paths' | 'schedule' | 'actions' | 'activate' | 'deactivate' | 'setpos']\n"); + debugPrintf("hotspot <hotspot_id> ['paths' | 'schedule' | 'actions' | 'activate' | 'deactivate' | 'setpos']\n"); return true; } hs = res.getHotspot(strToInt(argv[1])); if (!hs) { - DebugPrintf("Unknown hotspot specified\n"); + debugPrintf("Unknown hotspot specified\n"); return true; } @@ -300,26 +300,26 @@ bool Debugger::cmd_hotspot(int argc, const char **argv) { if (argc == 2) { // Show the hotspot properties strings.getString(hs->nameId, buffer); - DebugPrintf("name = %d - %s, descs = (%d,%d)\n", hs->nameId, buffer, + debugPrintf("name = %d - %s, descs = (%d,%d)\n", hs->nameId, buffer, hs->descId, hs->descId2); - DebugPrintf("actions = %xh, offset = %xh\n", hs->actions, hs->actionsOffset); - DebugPrintf("flags = %xh, layer = %d\n", hs->flags, hs->layer); - DebugPrintf("position = %d,%d,%d\n", hs->startX, hs->startY, hs->roomNumber); - DebugPrintf("size = %d,%d, alt = %d,%d, yCorrection = %d\n", + debugPrintf("actions = %xh, offset = %xh\n", hs->actions, hs->actionsOffset); + debugPrintf("flags = %xh, layer = %d\n", hs->flags, hs->layer); + debugPrintf("position = %d,%d,%d\n", hs->startX, hs->startY, hs->roomNumber); + debugPrintf("size = %d,%d, alt = %d,%d, yCorrection = %d\n", hs->width, hs->height, hs->widthCopy, hs->heightCopy, hs->yCorrection); - DebugPrintf("Talk bubble offset = %d,%d\n", hs->talkX, hs->talkY); - DebugPrintf("load offset = %xh, script load = %d\n", hs->loadOffset, hs->scriptLoadFlag); - DebugPrintf("Animation Id = %xh, Color offset = %d\n", hs->animRecordId, hs->colorOffset); - DebugPrintf("Talk Script offset = %xh, Tick Script offset = %xh\n", + debugPrintf("Talk bubble offset = %d,%d\n", hs->talkX, hs->talkY); + debugPrintf("load offset = %xh, script load = %d\n", hs->loadOffset, hs->scriptLoadFlag); + debugPrintf("Animation Id = %xh, Color offset = %d\n", hs->animRecordId, hs->colorOffset); + debugPrintf("Talk Script offset = %xh, Tick Script offset = %xh\n", hs->talkScriptOffset, hs->tickScriptOffset); - DebugPrintf("Tick Proc offset = %xh\n", hs->tickProcId); - DebugPrintf("Tick timeout = %d\n", hs->tickTimeout); - DebugPrintf("Character mode = %d, delay ctr = %d, pause ctr = %d\n", + debugPrintf("Tick Proc offset = %xh\n", hs->tickProcId); + debugPrintf("Tick timeout = %d\n", hs->tickTimeout); + debugPrintf("Character mode = %d, delay ctr = %d, pause ctr = %d\n", hs->characterMode, hs->delayCtr, hs->pauseCtr); if (h != NULL) { - DebugPrintf("Frame Number = %d of %d\n", h->frameNumber(), h->numFrames()); - DebugPrintf("Persistent = %s\n", h->persistant() ? "true" : "false"); + debugPrintf("Frame Number = %d of %d\n", h->frameNumber(), h->numFrames()); + debugPrintf("Persistent = %s\n", h->persistant() ? "true" : "false"); } } else if (strcmp(argv[2], "actions") == 0) { @@ -329,42 +329,42 @@ bool Debugger::cmd_hotspot(int argc, const char **argv) { const char *actionStr = stringList.getString(action); if (offset >= 0x8000) { - DebugPrintf("%s - Message %xh\n", actionStr, offset & 0x7ff); + debugPrintf("%s - Message %xh\n", actionStr, offset & 0x7ff); } else if (offset != 0) { - DebugPrintf("%s - Script %xh\n", actionStr, offset); + debugPrintf("%s - Script %xh\n", actionStr, offset); } } } else if (strcmp(argv[2], "activate") == 0) { // Activate the hotspot res.activateHotspot(hs->hotspotId); hs->flags &= ~HOTSPOTFLAG_MENU_EXCLUSION; - DebugPrintf("Activated\n"); + debugPrintf("Activated\n"); } else if (strcmp(argv[2], "deactivate") == 0) { // Deactivate the hotspot res.deactivateHotspot(hs->hotspotId); hs->flags |= HOTSPOTFLAG_MENU_EXCLUSION; - DebugPrintf("Deactivated\n"); + debugPrintf("Deactivated\n"); } else { if (strcmp(argv[2], "schedule") == 0) { // List any current schedule for the character - DebugPrintf("%s", hs->npcSchedule.getDebugInfo().c_str()); + debugPrintf("%s", hs->npcSchedule.getDebugInfo().c_str()); } if (!h) - DebugPrintf("The specified hotspot is not currently active\n"); + debugPrintf("The specified hotspot is not currently active\n"); else if (strcmp(argv[2], "paths") == 0) { // List any paths for a charcter - DebugPrintf("%s", h->pathFinder().getDebugInfo().c_str()); + debugPrintf("%s", h->pathFinder().getDebugInfo().c_str()); } else if (strcmp(argv[2], "pixels") == 0) { // List the pixel data for the hotspot HotspotAnimData &pData = h->anim(); - DebugPrintf("Record Id = %xh\n", pData.animRecordId); - DebugPrintf("Flags = %d\n", pData.flags); - DebugPrintf("Frames: up=%d down=%d left=%d right=%d\n", + debugPrintf("Record Id = %xh\n", pData.animRecordId); + debugPrintf("Flags = %d\n", pData.flags); + debugPrintf("Frames: up=%d down=%d left=%d right=%d\n", pData.upFrame, pData.downFrame, pData.leftFrame, pData.rightFrame); - DebugPrintf("Current frame = %d of %d\n", h->frameNumber(), h->numFrames()); + debugPrintf("Current frame = %d of %d\n", h->frameNumber(), h->numFrames()); } else if (strcmp(argv[2], "setpos") == 0) { // Set the hotspot position @@ -372,11 +372,11 @@ bool Debugger::cmd_hotspot(int argc, const char **argv) { h->setPosition(strToInt(argv[3]), strToInt(argv[4])); if (argc >= 6) h->setRoomNumber(strToInt(argv[5])); - DebugPrintf("Done.\n"); + debugPrintf("Done.\n"); } } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } @@ -388,56 +388,56 @@ bool Debugger::cmd_room(int argc, const char **argv) { char buffer[MAX_DESC_SIZE]; if (argc < 2) { - DebugPrintf("room <room_number>\n"); + debugPrintf("room <room_number>\n"); return true; } int roomNumber = strToInt(argv[1]); RoomData *room = res.getRoom(roomNumber); if (!room) { - DebugPrintf("Unknown room specified\n"); + debugPrintf("Unknown room specified\n"); return true; } // Show the room details strings.getString(roomNumber, buffer); - DebugPrintf("room #%d - %s\n", roomNumber, buffer); + debugPrintf("room #%d - %s\n", roomNumber, buffer); strings.getString(room->descId, buffer); - DebugPrintf("%s\n", buffer); - DebugPrintf("Horizontal clipping = %d->%d walk area=(%d,%d)-(%d,%d)\n", + debugPrintf("%s\n", buffer); + debugPrintf("Horizontal clipping = %d->%d walk area=(%d,%d)-(%d,%d)\n", room->clippingXStart, room->clippingXEnd, room->walkBounds.left, room->walkBounds.top, room->walkBounds.right, room->walkBounds.bottom); - DebugPrintf("Exit hotspots:"); + debugPrintf("Exit hotspots:"); RoomExitHotspotList &exits = room->exitHotspots; if (exits.empty()) - DebugPrintf(" none\n"); + debugPrintf(" none\n"); else { RoomExitHotspotList::iterator i; for (i = exits.begin(); i != exits.end(); ++i) { RoomExitHotspotData const &rec = **i; - DebugPrintf("\nArea - (%d,%d)-(%d,%d) Room=%d Cursor=%d Hotspot=%xh", + debugPrintf("\nArea - (%d,%d)-(%d,%d) Room=%d Cursor=%d Hotspot=%xh", rec.xs, rec.ys, rec.xe, rec.ye, rec.destRoomNumber, rec.cursorNum, rec.hotspotId); } - DebugPrintf("\n"); + debugPrintf("\n"); } - DebugPrintf("Room exits:"); + debugPrintf("Room exits:"); if (room->exits.empty()) - DebugPrintf(" none\n"); + debugPrintf(" none\n"); else { RoomExitList::iterator i2; for (i2 = room->exits.begin(); i2 != room->exits.end(); ++i2) { RoomExitData const &rec2 = **i2; - DebugPrintf("\nExit - (%d,%d)-(%d,%d) Dest=%d,(%d,%d) Dir=%s Sequence=%xh", + debugPrintf("\nExit - (%d,%d)-(%d,%d) Dest=%d,(%d,%d) Dir=%s Sequence=%xh", rec2.xs, rec2.ys, rec2.xe, rec2.ye, rec2.roomNumber, rec2.x, rec2.y, directionList[rec2.direction], rec2.sequenceOffset); } - DebugPrintf("\n"); + debugPrintf("\n"); } return true; @@ -446,7 +446,7 @@ bool Debugger::cmd_room(int argc, const char **argv) { bool Debugger::cmd_showAnim(int argc, const char **argv) { Resources &res = Resources::getReference(); if (argc < 2) { - DebugPrintf("showAnim animId [[frame_width frame_height] | list]\n"); + debugPrintf("showAnim animId [[frame_width frame_height] | list]\n"); return true; } @@ -454,7 +454,7 @@ bool Debugger::cmd_showAnim(int argc, const char **argv) { int animId = strToInt(argv[1]); HotspotAnimData *data = res.getAnimation(animId); if (data == NULL) { - DebugPrintf("No such animation Id exists\n"); + debugPrintf("No such animation Id exists\n"); return true; } @@ -500,7 +500,7 @@ bool Debugger::cmd_showAnim(int argc, const char **argv) { height = strToInt(argv[3]); if ((width * height) != (frameSize * 2)) { - DebugPrintf("Warning: Total size = %d, Frame size (%d,%d) * %d frames = %d bytes\n", + debugPrintf("Warning: Total size = %d, Frame size (%d,%d) * %d frames = %d bytes\n", destSize, width, height, numFrames, width * height * numFrames / 2); } } else { @@ -511,25 +511,25 @@ bool Debugger::cmd_showAnim(int argc, const char **argv) { width = frameSize * 3 / 4; bool descFlag = (argc == 3); - if (descFlag) DebugPrintf("Target size = %d\n", frameSize * 2); + if (descFlag) debugPrintf("Target size = %d\n", frameSize * 2); while ((width > 0) && (descFlag || (((frameSize * 2) % width) != 0))) { if (((frameSize * 2) % width) == 0) - DebugPrintf("Frame size (%d,%d) found\n", width, frameSize * 2 / width); + debugPrintf("Frame size (%d,%d) found\n", width, frameSize * 2 / width); --width; } if (argc == 3) { - DebugPrintf("Done\n"); + debugPrintf("Done\n"); return true; } else if (width == 0) { - DebugPrintf("Total size = %d, # frames = %d, frame Size = %d - No valid frame dimensions\n", + debugPrintf("Total size = %d, # frames = %d, frame Size = %d - No valid frame dimensions\n", destSize, numFrames, frameSize); return true; } height = (frameSize * 2) / width; - DebugPrintf("# frames = %d, guestimated frame size = (%d,%d)\n", + debugPrintf("# frames = %d, guestimated frame size = (%d,%d)\n", numFrames, width, height); } @@ -544,13 +544,13 @@ bool Debugger::cmd_showAnim(int argc, const char **argv) { hotspot->setAnimation(animId); - DebugPrintf("Done\n"); + debugPrintf("Done\n"); return true; } bool Debugger::cmd_saveStrings(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("strings <stringId>\n"); + debugPrintf("strings <stringId>\n"); return true; } @@ -558,13 +558,13 @@ bool Debugger::cmd_saveStrings(int argc, const char **argv) { char *buffer = (char *)malloc(32768); if (!buffer) { - DebugPrintf("Cannot allocate strings buffer\n"); + debugPrintf("Cannot allocate strings buffer\n"); return true; } uint16 id = strToInt(argv[1]); - strings.getString(id, buffer, NULL, NULL); - DebugPrintf("%s\n", buffer); + strings.getString(id, buffer); + debugPrintf("%s\n", buffer); /* Commented out code for saving all text strings - note that 0x1000 is chosen * arbitrarily, so there'll be a bunch of garbage at the end, or the game will crash @@ -580,7 +580,7 @@ bool Debugger::cmd_saveStrings(int argc, const char **argv) { fclose(f); - DebugPrintf("Done\n"); + debugPrintf("Done\n"); */ free(buffer); @@ -593,16 +593,16 @@ bool Debugger::cmd_debug(int argc, const char **argv) { Room &room = Room::getReference(); if ((argc == 2) && (strcmp(argv[1], "on") == 0)) { - DebugPrintf("debug keys are on\n"); + debugPrintf("debug keys are on\n"); game.debugFlag() = true; } else if ((argc == 2) && (strcmp(argv[1], "off") == 0)) { - DebugPrintf("debug keys are off\n"); + debugPrintf("debug keys are off\n"); game.debugFlag() = false; room.setShowInfo(false); } else { - DebugPrintf("debug [on | off]]\n"); + debugPrintf("debug [on | off]]\n"); } return true; @@ -610,13 +610,13 @@ bool Debugger::cmd_debug(int argc, const char **argv) { bool Debugger::cmd_script(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("script <script number> [param 1] [param 2] [param 3] [exit flag]\n"); + debugPrintf("script <script number> [param 1] [param 2] [param 3] [exit flag]\n"); return true; } int scriptNumber = strToInt(argv[1]); if ((scriptNumber < 0) || (scriptNumber > 66)) { - DebugPrintf("An invalid script number was specified\n"); + debugPrintf("An invalid script number was specified\n"); return true; } @@ -629,7 +629,7 @@ bool Debugger::cmd_script(int argc, const char **argv) { param3 = strToInt(argv[4]); Script::executeMethod(scriptNumber, param1, param2, param3); - DebugPrintf("Script executed\n"); + debugPrintf("Script executed\n"); return true; } diff --git a/engines/mads/action.cpp b/engines/mads/action.cpp new file mode 100644 index 0000000000..80480cbdfd --- /dev/null +++ b/engines/mads/action.cpp @@ -0,0 +1,708 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "mads/mads.h" +#include "mads/action.h" +#include "mads/inventory.h" +#include "mads/resources.h" +#include "mads/scene.h" +#include "mads/staticres.h" + +namespace MADS { + +void ActionDetails::synchronize(Common::Serializer &s) { + s.syncAsUint16LE(_verbId); + s.syncAsUint16LE(_objectNameId); + s.syncAsUint16LE(_indirectObjectId); +} + +void ActionSavedFields::synchronize(Common::Serializer &s) { + s.syncAsByte(_commandError); + s.syncAsSint16LE(_commandSource); + s.syncAsSint16LE(_command); + s.syncAsSint16LE(_mainObject); + s.syncAsSint16LE(_secondObject); + s.syncAsSint16LE(_mainObjectSource); + s.syncAsSint16LE(_secondObjectSource); + s.syncAsSint16LE(_articleNumber); + s.syncAsSint16LE(_lookFlag); +} + +/*------------------------------------------------------------------------*/ + +MADSAction::MADSAction(MADSEngine *vm) : _vm(vm) { + clear(); + _statusTextIndex = -1; + _selectedAction = 0; + _inProgress = false; + _pickedWord = -1; + + _savedFields._commandSource = 0; + _savedFields._mainObjectSource = 0; + _savedFields._command = -1; + _savedFields._mainObject = 0; + _savedFields._secondObject = 0; + _savedFields._secondObjectSource = 0; + _savedFields._articleNumber = PREP_NONE; + _savedFields._lookFlag = false; + + _activeAction._verbId = VERB_NONE; + _activeAction._objectNameId = -1; + _activeAction._indirectObjectId = -1; + _savedFields._commandError = false; + _verbType = VERB_INIT; + _prepType = PREP_NONE; +} + +void MADSAction::clear() { + _interAwaiting = AWAITING_COMMAND; + _commandSource = CAT_NONE; + _mainObjectSource = CAT_NONE; + _secondObjectSource = CAT_NONE; + _recentCommandSource = CAT_NONE; + _articleNumber = 0; + _lookFlag = false; + _pointEstablished = 0; + _statusText.clear(); + _selectedRow = -1; + _hotspotId = -1; + _secondObject = -1; + _recentCommand = -1; + _action._verbId = VERB_NONE; + _action._objectNameId = -1; + _action._indirectObjectId = -1; + _textChanged = true; +} + +void MADSAction::appendVocab(int vocabId, bool capitalize) { + Common::String vocabStr = _vm->_game->_scene.getVocab(vocabId); + if (capitalize) + vocabStr.setChar(toupper(vocabStr[0]), 0); + + _statusText += vocabStr; + _statusText += " "; +} + +void MADSAction::startWalkingDirectly(int walkType) { + Scene &scene = _vm->_game->_scene; + Player &player = _vm->_game->_player; + + if (_pointEstablished && (walkType == -3 || _savedFields._command < 0)) { + player._needToWalk = true; + player._prepareWalkPos = scene._customDest; + } +} + +void MADSAction::set() { + Scene &scene = _vm->_game->_scene; + UserInterface &userInterface = scene._userInterface; + _statusText = ""; + + _action._verbId = VERB_NONE; + _action._objectNameId = -1; + _action._indirectObjectId = -1; + + if (_commandSource == CAT_TALK_ENTRY) { + // Handle showing the conversation selection. Rex at least doesn't actually seem to use this + if (_selectedRow >= 0) { + _action._verbId = userInterface._talkIds[_selectedRow]; + Common::String desc = userInterface._talkStrings[_selectedRow]; + if (!desc.empty()) + _statusText = desc; + } + } else if (_lookFlag && (_selectedRow == 0)) { + // Two 'look' actions in succession, so the action becomes 'Look around' + _statusText = kLookAroundStr; + } else { + bool flag = false; + if ((_commandSource == CAT_INV_VOCAB) && (_selectedRow >= 0) + && (_verbType == VERB_THAT) && (_prepType == PREP_NONE)) { + // Use/to action + int invIndex = userInterface._selectedInvIndex; + InventoryObject &objEntry = _vm->_game->_objects.getItem(invIndex); + + _action._objectNameId = objEntry._descId; + _action._verbId = objEntry._vocabList[_selectedRow]._vocabId; + + // Set up the status text string + _statusText = kUseStr; + appendVocab(_action._objectNameId); + _statusText += kToStr; + appendVocab(_action._verbId); + } else { + // Handling for if an action has been selected + if (_selectedRow >= 0) { + if (_commandSource == CAT_COMMAND) { + // Standard verb action + _action._verbId = scene._verbList[_selectedRow]._id; + } else { + // Selected action on an inventory object + int invIndex = userInterface._selectedInvIndex; + InventoryObject &objEntry = _vm->_game->_objects.getItem(invIndex); + + _action._verbId = objEntry._vocabList[_selectedRow]._vocabId; + } + + appendVocab(_action._verbId, true); + + if (_action._verbId == VERB_LOOK) { + // Add in the word 'add' + _statusText += kArticleList[PREP_AT]; + _statusText += " "; + } + } + + // Add in any necessary article if necessary + if ((_hotspotId >= 0) && (_selectedRow >= 0) && (_articleNumber > 0) && (_verbType == VERB_THAT)) { + flag = true; + + _statusText += kArticleList[_articleNumber]; + _statusText += " "; + } + + // Handling for hotspot + if (_hotspotId >= 0) { + if (_selectedRow < 0) { + int verbId; + + if (_hotspotId < (int)scene._hotspots.size()) { + // Get the verb Id from the hotspot + verbId = scene._hotspots[_hotspotId]._verbId; + } else { + // Get the verb Id from the scene object + verbId = scene._dynamicHotspots[_hotspotId - scene._hotspots.size()]._verbId; + } + + if (verbId > 0) { + // Set the specified action + _action._verbId = verbId; + appendVocab(_action._verbId, true); + } else { + // Default to a standard 'walk to' + _action._verbId = VERB_WALKTO; + _statusText += kWalkToStr; + } + } + + if ((_mainObjectSource == CAT_INV_LIST) || (_mainObjectSource == CAT_INV_ANIM)) { + // Get name from given inventory object + InventoryObject &invObject = _vm->_game->_objects.getItem(_hotspotId); + _action._objectNameId = invObject._descId; + } else if (_hotspotId < (int)scene._hotspots.size()) { + // Get name from scene hotspot + _action._objectNameId = scene._hotspots[_hotspotId]._vocabId; + } else { + // Get name from temporary scene hotspot + _action._objectNameId = scene._dynamicHotspots[_hotspotId - scene._hotspots.size()]._descId; + } + appendVocab(_action._objectNameId); + } + } + + if (_secondObject >= 0) { + if (_secondObjectSource == CAT_INV_LIST || _secondObjectSource == CAT_INV_ANIM) { + InventoryObject &invObject = _vm->_game->_objects.getItem(_secondObject); + _action._indirectObjectId = invObject._descId; + } else if (_secondObject < (int)scene._hotspots.size()) { + _action._indirectObjectId = scene._hotspots[_secondObject]._vocabId; + } else { + _action._indirectObjectId = scene._dynamicHotspots[_secondObject - scene._hotspots.size()]._descId; + } + } + + if ((_hotspotId >= 0) && (_articleNumber > 0) && !flag) { + if (_articleNumber == PREP_RELATIONAL) { + if (_secondObject >= 0) { + int articleNum = 0; + + if ((_secondObjectSource == 2) || (_secondObjectSource == 5)) { + InventoryObject &invObject = _vm->_game->_objects.getItem(_hotspotId); + articleNum = invObject._article; + } else if (_hotspotId < (int)scene._hotspots.size()) { + articleNum = scene._hotspots[_hotspotId]._articleNumber; + } else { + articleNum = scene._dynamicHotspots[_hotspotId - scene._hotspots.size()]._articleNumber; + } + + _statusText += kArticleList[articleNum]; + } + } else if ((_articleNumber == VERB_LOOK) || (_vm->getGameID() != GType_RexNebular) || + (_action._indirectObjectId >= 0 && scene._vocabStrings[_action._indirectObjectId] != kFenceStr)) { + // Write out the article + _statusText += kArticleList[_articleNumber]; + } else { + // Special case for a 'fence' entry in Rex Nebular + _statusText += kOverStr; + } + + _statusText += " "; + } + + // Append object description if necessary + if (_secondObject >= 0) + appendVocab(_action._indirectObjectId); + + // Remove any trailing space character + if (_statusText.hasSuffix(" ")) + _statusText.deleteLastChar(); + } + + _textChanged = true; +} + +void MADSAction::refresh() { + Scene &scene = _vm->_game->_scene; + + // Exit immediately if nothing has changed + if (!_textChanged) + return; + + // Remove any old copy of the status text + if (_statusTextIndex >= 0) { + scene._textDisplay.expire(_statusTextIndex); + _statusTextIndex = -1; + } + + if (!_statusText.empty()) { + if ((_vm->_game->_screenObjects._inputMode == kInputBuildingSentences) || + (_vm->_game->_screenObjects._inputMode == kInputLimitedSentences)) { + Font *font = _vm->_font->getFont(FONT_MAIN); + int textSpacing = -1; + + int strWidth = font->getWidth(_statusText); + if (strWidth > MADS_SCREEN_WIDTH) { + // Too large to fit, so fall back on interface font + font = _vm->_font->getFont(FONT_INTERFACE); + strWidth = font->getWidth(_statusText, 0); + textSpacing = 0; + } + + // Add a new text display entry to display the status text at the bottom of the screen area + _statusTextIndex = scene._textDisplay.add(160 - (strWidth / 2), + MADS_SCENE_HEIGHT + scene._posAdjust.y - 13, 3, textSpacing, _statusText, font); + } + } + + _textChanged = false; +} + +void MADSAction::startAction() { + Game &game = *_vm->_game; + Player &player = game._player; + Scene &scene = _vm->_game->_scene; + DynamicHotspots &dynHotspots = scene._dynamicHotspots; + Hotspots &hotspots = scene._hotspots; + + player.cancelCommand(); + + _inProgress = true; + _savedFields._commandError = false; + _savedFields._command = _selectedRow; + _savedFields._mainObject = _hotspotId; + _savedFields._secondObject = _secondObject; + _savedFields._articleNumber = _articleNumber; + _savedFields._commandSource = _commandSource; + _savedFields._mainObjectSource = _mainObjectSource; + _savedFields._secondObjectSource = _secondObjectSource; + _savedFields._lookFlag = _lookFlag; + _activeAction = _action; + + // Copy the action to be active + _activeAction = _action; + _sentence = _statusText; + + if ((_mainObjectSource == CAT_HOTSPOT) && (_secondObjectSource == 4)) + _savedFields._commandError = true; + + player._needToWalk = false; + int hotspotId = -1; + + if (!_savedFields._lookFlag && (_vm->_game->_screenObjects._inputMode != kInputConversation)) { + if (_savedFields._mainObjectSource == CAT_HOTSPOT) + hotspotId = _savedFields._mainObject; + else if (_secondObjectSource == 4) + hotspotId = _savedFields._secondObject; + + if (hotspotId >= (int)hotspots.size()) { + DynamicHotspot &hs = dynHotspots[hotspotId - hotspots.size()]; + if ((hs._feetPos.x == -1) || (hs._feetPos.x == -3)) { + startWalkingDirectly(hs._feetPos.x); + } else if (hs._feetPos.x == 0) { + player._prepareWalkFacing = hs._facing; + } else if (_savedFields._commandSource == CAT_NONE || hs._cursor < CURSOR_WAIT) { + player._needToWalk = true; + player._prepareWalkPos = hs._feetPos; + } + + player._prepareWalkFacing = hs._facing; + hotspotId = -1; + } + } + + if (hotspotId >= 0) { + Hotspot &hs = hotspots[hotspotId]; + + if (hs._feetPos.x == -1 || hs._feetPos.x == -3) { + startWalkingDirectly(hs._feetPos.x); + } else if (hs._feetPos.x >= 0) { + if (_savedFields._commandSource == CAT_NONE || hs._cursor < CURSOR_WAIT) { + player._needToWalk = true; + player._prepareWalkPos = hs._feetPos; + } + } + + player._prepareWalkFacing = hs._facing; + } + + player._readyToWalk = player._needToWalk; +} + +void MADSAction::checkAction() { + if (isAction(VERB_LOOK) || isAction(VERB_THROW)) + _vm->_game->_player._needToWalk = false; +} + +bool MADSAction::isAction(int verbId, int objectNameId, int indirectObjectId) { + if (_activeAction._verbId != verbId) + return false; + if ((objectNameId != 0) && (_activeAction._objectNameId != objectNameId)) + return false; + if ((indirectObjectId != 0) && (_activeAction._indirectObjectId != indirectObjectId)) + return false; + + return true; +} + +bool MADSAction::isObject(int objectNameId) { + return _activeAction._objectNameId == objectNameId; +} + +bool MADSAction::isTarget(int objectNameId) { + return _activeAction._indirectObjectId == objectNameId; +} + +void MADSAction::checkActionAtMousePos() { + Scene &scene = _vm->_game->_scene; + UserInterface &userInterface = scene._userInterface; + + if ((userInterface._category == CAT_COMMAND || userInterface._category == CAT_INV_VOCAB) && + _interAwaiting != AWAITING_COMMAND && _pickedWord >= 0) { + if (_recentCommandSource == userInterface._category || _recentCommand != _pickedWord || + (_interAwaiting != AWAITING_THIS && _interAwaiting != 3)) + clear(); + else if (_selectedRow != 0 || userInterface._category != CAT_COMMAND) + scene._lookFlag = false; + else + scene._lookFlag = true; + } + + if (_vm->_events->_rightMousePressed && _vm->_events->_mouseButtons) { + switch (userInterface._category) { + case CAT_COMMAND: + case CAT_INV_VOCAB: + return; + + case CAT_INV_LIST: + case CAT_HOTSPOT: + case CAT_INV_ANIM: + if (_interAwaiting != AWAITING_THAT) { + if (userInterface._selectedActionIndex >= 0) { + _commandSource = CAT_COMMAND; + _selectedRow = userInterface._selectedActionIndex; + _verbType = scene._verbList[_selectedRow]._verbType; + _prepType = scene._verbList[_selectedRow]._prepType; + _interAwaiting = AWAITING_THIS; + } else if (userInterface._selectedItemVocabIdx >= 0) { + _commandSource = CAT_INV_VOCAB; + _selectedRow = userInterface._selectedItemVocabIdx; + int objectId = _vm->_game->_objects._inventoryList[_selectedRow]; + InventoryObject &invObject = _vm->_game->_objects[objectId]; + + _verbType = invObject._vocabList[_selectedRow - 1]._verbType; + _prepType = invObject._vocabList[_selectedRow - 1]._prepType; + _mainObjectSource = CAT_INV_LIST; + _hotspotId = userInterface._selectedInvIndex; + _articleNumber = _prepType; + + if ((_verbType == VERB_THIS && _prepType == PREP_NONE) || + (_verbType == VERB_THAT && _prepType != PREP_NONE)) + _interAwaiting = AWAITING_RIGHT_MOUSE; + else + _interAwaiting = AWAITING_THAT; + } + } + break; + + default: + break; + } + } + + switch (_interAwaiting) { + case AWAITING_COMMAND: + _articleNumber = 0; + switch (userInterface._category) { + case CAT_COMMAND: + _commandSource = CAT_COMMAND; + _selectedRow = _pickedWord; + if (_selectedRow >= 0) { + _verbType = scene._verbList[_selectedRow]._verbType; + _prepType = scene._verbList[_selectedRow]._prepType; + } + break; + + case CAT_INV_VOCAB: + _commandSource = CAT_INV_VOCAB; + _selectedRow = _pickedWord; + if (_selectedRow < 0) { + _hotspotId = -1; + _mainObjectSource = CAT_NONE; + } else { + InventoryObject &invObject = _vm->_game->_objects.getItem(userInterface._selectedInvIndex); + _verbType = invObject._vocabList[_selectedRow]._verbType; + _prepType = invObject._vocabList[_selectedRow]._prepType; + _hotspotId = userInterface._selectedInvIndex; + _mainObjectSource = CAT_INV_LIST; + + if (_verbType == VERB_THAT) + _articleNumber = _prepType; + } + break; + + case CAT_HOTSPOT: + _selectedRow = -1; + _commandSource = CAT_NONE; + _mainObjectSource = CAT_HOTSPOT; + _hotspotId = _pickedWord; + break; + + case CAT_TALK_ENTRY: + _commandSource = CAT_TALK_ENTRY; + _selectedRow = _pickedWord; + break; + + default: + break; + } + break; + + case AWAITING_THIS: + _articleNumber = 0; + switch (userInterface._category) { + case CAT_INV_LIST: + case CAT_HOTSPOT: + case CAT_INV_ANIM: + _mainObjectSource = userInterface._category; + _hotspotId = _pickedWord; + break; + default: + break; + } + break; + + case AWAITING_THAT: + switch (userInterface._category) { + case CAT_INV_LIST: + case CAT_HOTSPOT: + case CAT_INV_ANIM: + _secondObjectSource = userInterface._category; + _secondObject = _pickedWord; + break; + default: + break; + } + break; + + default: + break; + } +} + +void MADSAction::leftClick() { + Scene &scene = _vm->_game->_scene; + UserInterface &userInterface = scene._userInterface; + bool abortFlag = false; + + if ((userInterface._category == CAT_COMMAND || userInterface._category == CAT_INV_VOCAB) && + _interAwaiting != 1 && _pickedWord >= 0 && + _recentCommandSource == userInterface._category && _recentCommand == _pickedWord && + (_interAwaiting == 2 || userInterface._category == CAT_INV_VOCAB)) { + abortFlag = true; + if (_selectedRow == 0 && userInterface._category == CAT_COMMAND) { + _selectedAction = CAT_COMMAND; + scene._lookFlag = true; + } else { + _selectedAction = CAT_NONE; + scene._lookFlag = false; + clear(); + } + } + + if (abortFlag || (_vm->_events->_rightMousePressed && (userInterface._category == CAT_COMMAND || + userInterface._category == CAT_INV_VOCAB))) + return; + + switch (_interAwaiting) { + case AWAITING_COMMAND: + switch (userInterface._category) { + case CAT_COMMAND: + if (_selectedRow >= 0) { + if (_verbType == VERB_ONLY) { + _selectedAction = -1; + } + else { + _recentCommand = _selectedRow; + _recentCommandSource = _commandSource; + _interAwaiting = AWAITING_THIS; + } + } + break; + + case CAT_INV_LIST: + if (_pickedWord >= 0) { + userInterface.selectObject(_pickedWord); + } + break; + + case CAT_INV_VOCAB: + if (_selectedRow >= 0) { + if (_verbType != VERB_THIS || _prepType != PREP_NONE) { + if (_verbType != VERB_THAT || _prepType == PREP_NONE) { + _interAwaiting = AWAITING_THAT; + _articleNumber = _prepType; + } else { + _articleNumber = _prepType; + _selectedAction = -1; + } + } else { + _selectedAction = -1; + } + + _recentCommand = _selectedRow; + _recentCommandSource = _commandSource; + } + break; + + case CAT_HOTSPOT: + _recentCommand = -1; + _recentCommandSource = CAT_NONE; + + if (_vm->_events->currentPos().y < MADS_SCENE_HEIGHT) { + scene._customDest = _vm->_events->currentPos() + scene._posAdjust; + _selectedAction = -1; + _pointEstablished = true; + } + break; + + case CAT_TALK_ENTRY: + if (_selectedRow >= 0) + _selectedAction = -1; + break; + + default: + break; + } + break; + + case AWAITING_THIS: + switch (userInterface._category) { + case CAT_INV_LIST: + case CAT_HOTSPOT: + case CAT_INV_ANIM: + if (_hotspotId >= 0) { + if (_prepType) { + _articleNumber = _prepType; + _interAwaiting = AWAITING_THAT; + } else { + _selectedAction = -1; + } + + if (userInterface._category == CAT_HOTSPOT) { + scene._customDest = _vm->_events->mousePos() + scene._posAdjust; + _pointEstablished = true; + } + } + break; + default: + break; + } + break; + + case AWAITING_THAT: + switch (userInterface._category) { + case CAT_INV_LIST: + case CAT_HOTSPOT: + case CAT_INV_ANIM: + if (_secondObject >= 0) { + _selectedAction = -1; + + if (userInterface._category == CAT_HOTSPOT) { + if (!_pointEstablished) { + scene._customDest = _vm->_events->mousePos() + scene._posAdjust; + _pointEstablished = true; + } + } + } + break; + default: + break; + } + break; + + default: + break; + } +} + +void MADSAction::synchronize(Common::Serializer &s) { + _action.synchronize(s); + _activeAction.synchronize(s); + s.syncAsSint16LE(_articleNumber); + s.syncAsByte(_lookFlag); + s.syncAsByte(_textChanged); + s.syncAsSint16LE(_selectedRow); + s.syncAsSint16LE(_selectedAction); + s.syncAsSint16LE(_statusTextIndex); + s.syncAsSint16LE(_hotspotId); + _savedFields.synchronize(s); + + // TODO: When saving in Rex Village Hut, _senetence size() doesn't match + // string length. Find out why not + _sentence = Common::String(_sentence.c_str()); + s.syncString(_sentence); + + s.syncAsSint16LE(_verbType); + s.syncAsSint16LE(_prepType); + s.syncAsSint16LE(_commandSource); + s.syncAsSint16LE(_mainObjectSource); + s.syncAsSint16LE(_secondObject); + s.syncAsSint16LE(_secondObjectSource); + s.syncAsSint16LE(_recentCommandSource); + s.syncAsSint16LE(_recentCommand); + s.syncAsSint16LE(_interAwaiting); + s.syncAsSint16LE(_pickedWord); + s.syncAsByte(_pointEstablished); + s.syncAsByte(_inProgress); +} + +} // End of namespace MADS diff --git a/engines/mads/action.h b/engines/mads/action.h new file mode 100644 index 0000000000..cfd5a3be3f --- /dev/null +++ b/engines/mads/action.h @@ -0,0 +1,176 @@ +/* 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. + * + */ + +#ifndef MADS_ACTION_H +#define MADS_ACTION_H + +#include "common/scummsys.h" +#include "common/serializer.h" +#include "common/str.h" + +namespace MADS { + +enum TriggerMode { + SEQUENCE_TRIGGER_PARSER = 0, // Triggers parser + SEQUENCE_TRIGGER_DAEMON = 1, // Triggers step/daemon code + SEQUENCE_TRIGGER_PREPARE = 2 // Triggers preparser +}; + +enum InterAwaiting { + AWAITING_NONE = 0, + AWAITING_COMMAND = 1, // Initial state: waiting for a command verb + AWAITING_THIS = 2, // Waiting for object + AWAITING_THAT = 3, // Waiting for a second object + AWAITING_RIGHT_MOUSE = 4 // Waiting for mouse button release +}; + +enum { + VERB_NONE = 0, + VERB_LOOK = 3, + VERB_TAKE = 4, + VERB_PUSH = 5, + VERB_OPEN = 6, + VERB_PUT = 7, + VERB_TALKTO = 8, + VERB_GIVE = 9, + VERB_PULL = 10, + VERB_CLOSE = 11, + VERB_THROW = 12, + VERB_WALKTO = 13 +}; + +enum VerbType { VERB_ONLY, VERB_THIS, VERB_THAT, VERB_INIT }; + +enum PrepType { + PREP_NONE, PREP_WITH, PREP_TO, PREP_AT, PREP_FROM, PREP_ON, PREP_IN, + PREP_UNDER, PREP_BEHIND, PREP_RELATIONAL = 0xff +}; + +enum ScrCategory { + CAT_NONE = 0, CAT_COMMAND = 1, CAT_INV_LIST = 2, CAT_INV_VOCAB = 3, + CAT_HOTSPOT = 4, CAT_INV_ANIM = 5, CAT_TALK_ENTRY = 6, CAT_INV_SCROLLER = 7, + CAT_12 = 12 +}; + +class MADSEngine; + +struct ActionDetails { + int _verbId; + int _objectNameId; + int _indirectObjectId; + + /** + * Synchronize the action details + */ + void synchronize(Common::Serializer &s); +}; + +struct ActionSavedFields { + bool _commandError; + int _commandSource; + int _command; + int _mainObject; + int _secondObject; + int _mainObjectSource; + int _secondObjectSource; + int _articleNumber; + int _lookFlag; + + /** + * Synchronize the saved action details + */ + void synchronize(Common::Serializer &s); +}; + +class MADSAction { +private: + MADSEngine *_vm; + Common::String _statusText; + + void appendVocab(int vocabId, bool capitalize = false); + + void startWalkingDirectly(int walkType); +public: + ActionDetails _action, _activeAction; + int _articleNumber; + bool _lookFlag; + int _selectedRow; + bool _textChanged; + int _selectedAction; + int _statusTextIndex; + int _hotspotId; + ActionSavedFields _savedFields; + Common::String _sentence; + + VerbType _verbType; + PrepType _prepType; + ScrCategory _commandSource; + ScrCategory _mainObjectSource; + int _secondObject; + ScrCategory _secondObjectSource; + ScrCategory _recentCommandSource; + bool _pointEstablished; + int _recentCommand; + InterAwaiting _interAwaiting; + bool _inProgress; + int _pickedWord; + +public: + MADSAction(MADSEngine *vm); + + void clear(); + void set(); + const Common::String &statusText() const { return _statusText; } + void refresh(); + + /** + * Accepts the currently defined sentence from the ScreenObjects parser. + * Copies the data, and checks to see if the action requires the player + * to walk to the given hotspot. + */ + void startAction(); + + void checkAction(); + bool isAction(int verbId, int objectNameId = 0, int indirectObjectId = 0); + bool isObject(int objectNameId); + bool isTarget(int objectNameId); + + /** + * Check the result of the current action on the sentence + * with the provision that the action is not yet complete. + */ + void checkActionAtMousePos(); + + /** + * Execute a click within the scene + */ + void leftClick(); + + /** + * Synchronize the saved action details + */ + void synchronize(Common::Serializer &s); +}; + +} // End of namespace MADS + +#endif /* MADS_ACTION_H */ diff --git a/engines/mads/animation.cpp b/engines/mads/animation.cpp new file mode 100644 index 0000000000..6af8a9ae5f --- /dev/null +++ b/engines/mads/animation.cpp @@ -0,0 +1,591 @@ +/* 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. + * + */ + +#include "mads/animation.h" +#include "mads/compression.h" + +#define FILENAME_SIZE 13 + +namespace MADS { + +void AAHeader::load(Common::SeekableReadStream *f) { + _spriteSetsCount = f->readUint16LE(); + _miscEntriesCount = f->readUint16LE(); + _frameEntriesCount = f->readUint16LE(); + _messagesCount = f->readUint16LE(); + f->skip(1); + _flags = f->readByte(); + + f->skip(2); + _bgType = (AnimBgType)f->readUint16LE(); + _roomNumber = f->readUint16LE(); + f->skip(2); + _manualFlag = f->readUint16LE() != 0; + _spritesIndex = f->readUint16LE(); + _scrollPosition.x = f->readSint16LE(); + _scrollPosition.y = f->readSint16LE(); + _scrollTicks = f->readUint32LE(); + f->skip(6); + + char buffer[FILENAME_SIZE]; + f->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE - 1] = '\0'; + _interfaceFile = Common::String(buffer); + + for (int i = 0; i < 50; ++i) { + f->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE - 1] = '\0'; + if (i < _spriteSetsCount) + _spriteSetNames.push_back(Common::String(buffer)); + } + + f->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE - 1] = '\0'; + _soundName = Common::String(buffer); + + f->skip(13); + f->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE - 1] = '\0'; + _dsrName = Common::String(buffer); + + f->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE - 1] = '\0'; + _fontResource = Common::String(buffer); +} + +/*------------------------------------------------------------------------*/ + +void AnimMessage::load(Common::SeekableReadStream *f) { + _soundId = f->readSint16LE(); + + char buffer[64]; + f->read(&buffer[0], 64); + _msg = Common::String(buffer); + f->skip(4); + _pos.x = f->readSint16LE(); + _pos.y = f->readSint16LE(); + _flags = f->readUint16LE(); + _rgb1[0] = f->readByte() << 2; + _rgb1[1] = f->readByte() << 2; + _rgb1[2] = f->readByte() << 2; + _rgb2[0] = f->readByte() << 2; + _rgb2[1] = f->readByte() << 2; + _rgb2[2] = f->readByte() << 2; + f->skip(2); // Space for kernelMsgIndex + _kernelMsgIndex = -1; + f->skip(6); + _startFrame = f->readUint16LE(); + _endFrame = f->readUint16LE(); + f->skip(2); +} + +void AnimFrameEntry::load(Common::SeekableReadStream *f, bool uiFlag) { + if (uiFlag) { + f->skip(2); + _frameNumber = -1; // Unused + _seqIndex = f->readByte(); + _spriteSlot._spritesIndex = f->readByte(); + _spriteSlot._frameNumber = (int8)f->readByte(); + f->skip(1); + _spriteSlot._position.x = f->readSint16LE(); + _spriteSlot._position.y = f->readSint16LE(); + } else { + _frameNumber = f->readUint16LE(); + if (_frameNumber & 0x8000) + _frameNumber = -(_frameNumber & 0x7fff); + + _seqIndex = f->readByte(); + _spriteSlot._spritesIndex = f->readByte(); + _spriteSlot._frameNumber = f->readUint16LE(); + if (_spriteSlot._frameNumber & 0x8000) + _spriteSlot._frameNumber = -(_spriteSlot._frameNumber & 0x7fff); + + _spriteSlot._position.x = f->readSint16LE(); + _spriteSlot._position.y = f->readSint16LE(); + _spriteSlot._depth = f->readSByte(); + _spriteSlot._scale = (int8)f->readByte(); + } +} + +/*------------------------------------------------------------------------*/ + +void AnimMiscEntry::load(Common::SeekableReadStream *f) { + _soundId = f->readByte(); + _msgIndex = f->readSByte(); + _numTicks = f->readUint16LE(); + _posAdjust.x = f->readSint16LE(); + _posAdjust.y = f->readSint16LE(); + _field8 = f->readUint16LE(); +} + +/*------------------------------------------------------------------------*/ + +void AnimUIEntry::load(Common::SeekableReadStream *f) { + _probability = f->readUint16LE(); + _imageCount = f->readUint16LE(); + _firstImage = f->readUint16LE(); + _lastImage = f->readUint16LE(); + _counter = f->readSint16LE(); + for (int i = 0; i < ANIM_SPAWN_COUNT; ++i) + _spawn[i] = f->readByte(); + for (int i = 0; i < ANIM_SPAWN_COUNT; ++i) + _spawnFrame[i] = f->readUint16LE(); + _sound = f->readUint16LE() & 0xFF; + _soundFrame = f->readUint16LE(); +} + +/*------------------------------------------------------------------------*/ + +Animation *Animation::init(MADSEngine *vm, Scene *scene) { + return new Animation(vm, scene); +} + +Animation::Animation(MADSEngine *vm, Scene *scene) : _vm(vm), _scene(scene) { + _font = nullptr; + _resetFlag = false; + _messageCtr = 0; + _skipLoad = false; + _freeFlag = false; + _unkIndex = -1; + _nextFrameTimer = 0; + _nextScrollTimer = 0; + _trigger = 0; + _triggerMode = SEQUENCE_TRIGGER_PREPARE; + _actionDetails._verbId = VERB_NONE; + _actionDetails._objectNameId = -1; + _actionDetails._indirectObjectId = -1; + _currentFrame = 0; + _oldFrameEntry = 0; +} + +Animation::~Animation() { + Scene &scene = _vm->_game->_scene; + + if (_header._manualFlag) + scene._sprites.remove(_spriteListIndexes[_header._spritesIndex]); + + for (int idx = 0; idx < _header._spriteSetsCount; ++idx) { + if (!_header._manualFlag || _header._spritesIndex != idx) + scene._sprites.remove(_spriteListIndexes[idx]); + } +} + +void Animation::load(UserInterface &interfaceSurface, DepthSurface &depthSurface, + const Common::String &resName, int flags, Common::Array<PaletteCycle> *palCycles, + SceneInfo *sceneInfo) { + Common::String resourceName = resName; + if (!resourceName.contains(".")) + resourceName += ".AA"; + + File f(resourceName); + MadsPack madsPack(&f); + + Common::SeekableReadStream *stream = madsPack.getItemStream(0); + _header.load(stream); + delete stream; + + if (_header._bgType == ANIMBG_INTERFACE) + flags |= PALFLAG_RESERVED; + + if (flags & ANIMFLAG_LOAD_BACKGROUND) { + loadInterface(interfaceSurface, depthSurface, _header, flags, palCycles, sceneInfo); + } + if (flags & ANIMFLAG_LOAD_BACKGROUND_ONLY) { + // No data + _header._messagesCount = 0; + _header._frameEntriesCount = 0; + _header._miscEntriesCount = 0; + } + + // Initialize the reference list + _spriteListIndexes.clear(); + for (int i = 0; i < _header._spriteSetsCount; ++i) + _spriteListIndexes.push_back(-1); + + int streamIndex = 1; + _messages.clear(); + if (_header._messagesCount > 0) { + // Chunk 2: Following is a list of any messages for the animation + Common::SeekableReadStream *msgStream = madsPack.getItemStream(streamIndex++); + + for (int i = 0; i < _header._messagesCount; ++i) { + AnimMessage rec; + rec.load(msgStream); + _messages.push_back(rec); + } + + delete msgStream; + } + + _frameEntries.clear(); + if (_header._frameEntriesCount > 0) { + // Chunk 3: animation frame info + Common::SeekableReadStream *frameStream = madsPack.getItemStream(streamIndex++); + + for (int i = 0; i < _header._frameEntriesCount; i++) { + AnimFrameEntry rec; + rec.load(frameStream, flags & ANIMFLAG_LOAD_BACKGROUND); + _frameEntries.push_back(rec); + } + + delete frameStream; + } + + _miscEntries.clear(); + _uiEntries.clear(); + if (_header._miscEntriesCount > 0) { + // Chunk 4: Misc Data + Common::SeekableReadStream *miscStream = madsPack.getItemStream(streamIndex++); + + if (flags & ANIMFLAG_LOAD_BACKGROUND) { + for (int i = 0; i < _header._miscEntriesCount; ++i) { + AnimUIEntry rec; + rec.load(miscStream); + _uiEntries.push_back(rec); + } + } else { + for (int i = 0; i < _header._miscEntriesCount; ++i) { + AnimMiscEntry rec; + rec.load(miscStream); + _miscEntries.push_back(rec); + } + } + + delete miscStream; + } + + // If the animation specifies a font, then load it for access + delete _font; + if (_header._flags & ANIMFLAG_CUSTOM_FONT) { + Common::String fontName = "*" + _header._fontResource; + _font = _vm->_font->getFont(fontName.c_str()); + } else { + _font = nullptr; + } + + // Load all the sprite sets for the animation + for (uint i = 0; i < _spriteSets.size(); ++i) + delete _spriteSets[i]; + _spriteSets.clear(); + _spriteSets.resize(_header._spriteSetsCount); + + for (int i = 0; i < _header._spriteSetsCount; ++i) { + if (_header._manualFlag && (i == _header._spritesIndex)) { + // Skip over field, since it's manually loaded + _spriteSets[i] = nullptr; + } else { + _spriteSets[i] = new SpriteAsset(_vm, _header._spriteSetNames[i], flags); + _spriteListIndexes[i] = _vm->_game->_scene._sprites.add(_spriteSets[i]); + } + } + + if (_header._manualFlag) { + Common::String assetResName = "*" + _header._spriteSetNames[_header._spritesIndex]; + SpriteAsset *sprites = new SpriteAsset(_vm, assetResName, flags); + _spriteSets[_header._spritesIndex] = sprites; + + _spriteListIndexes[_header._spritesIndex] = _scene->_sprites.add(sprites); + } + + Common::Array<int> usageList; + for (int idx = 0; idx < _header._spriteSetsCount; ++idx) + usageList.push_back(_spriteSets[idx]->_usageIndex); + + if (usageList.size() > 0) + _vm->_palette->_paletteUsage.updateUsage(usageList, _header._messagesCount); + + // Remaps the sprite list indexes for frames to the loaded sprite list indexes + for (uint i = 0; i < _frameEntries.size(); ++i) { + int spriteListIndex = _frameEntries[i]._spriteSlot._spritesIndex; + _frameEntries[i]._spriteSlot._spritesIndex = _spriteListIndexes[spriteListIndex]; + } + + f.close(); +} + +void Animation::preLoad(const Common::String &resName, int level) { + // No implementation in ScummVM, since access is fast enough that data + // doesn't need to be preloaded +} + +void Animation::startAnimation(int endTrigger) { + _messageCtr = 0; + _skipLoad = true; + + if (_header._manualFlag) { + _unkIndex = -1; + //SpriteAsset *asset = _scene->_sprites[_spriteListIndexes[_header._spritesIndex]]; + + // TODO: Weird stuff with _unkList. Seems like it's treated as pointers + // here, but in processText, it's used as POINTs? + + loadFrame(1); + } + + if (_vm->_game->_kernelMode == KERNEL_ACTIVE_CODE) + _vm->_palette->refreshSceneColors(); + + _currentFrame = 0; + _oldFrameEntry = 0; + _nextFrameTimer = _vm->_game->_scene._frameStartTime; + _trigger = endTrigger; + _triggerMode = _vm->_game->_triggerSetupMode; + _actionDetails = _vm->_game->_scene._action._activeAction; + + for (int idx = 0; idx < _header._messagesCount; ++idx) { + _messages[idx]._kernelMsgIndex = -1; + } +} + +void Animation::loadFrame(int frameNumber) { + Scene &scene = _vm->_game->_scene; + if (_skipLoad) + return; + + Common::Point pt; + int spriteListIndex = _spriteListIndexes[_header._spritesIndex]; + SpriteAsset &spriteSet = *scene._sprites[spriteListIndex]; + + if (_unkIndex < 0) { + MSurface *frame = spriteSet.getFrame(0); + pt.x = frame->getBounds().left; + pt.y = frame->getBounds().top; + } else { + pt.x = _unkList[_unkIndex].x; + pt.y = _unkList[_unkIndex].y; + _unkIndex = 1 - _unkIndex; + } + + if (drawFrame(spriteSet, pt, frameNumber)) + error("drawFrame failure"); +} + +bool Animation::drawFrame(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber) { + return 0; +} + +void Animation::loadInterface(UserInterface &interfaceSurface, DepthSurface &depthSurface, + AAHeader &header, int flags, Common::Array<PaletteCycle> *palCycles, SceneInfo *sceneInfo) { + _scene->_depthStyle = 0; + if (header._bgType <= ANIMBG_FULL_SIZE) { + _vm->_palette->_paletteUsage.setEmpty(); + sceneInfo->load(header._roomNumber, flags, header._interfaceFile, 0, depthSurface, interfaceSurface); + _scene->_depthStyle = sceneInfo->_depthStyle == 2 ? 1 : 0; + if (palCycles) { + palCycles->clear(); + for (uint i = 0; i < sceneInfo->_paletteCycles.size(); ++i) + palCycles->push_back(sceneInfo->_paletteCycles[i]); + } + } else if (header._bgType == ANIMBG_INTERFACE) { + // Load a scene interface + Common::String resourceName = "*" + header._interfaceFile; + interfaceSurface.load(resourceName); + + if (palCycles) + palCycles->clear(); + } else { + // Original has useless code here + } +} + +bool Animation::hasScroll() const { + return (_header._scrollPosition.x != 0) || (_header._scrollPosition.y != 0); +} + +void Animation::update() { + Scene &scene = _vm->_game->_scene; + + if (_header._manualFlag) { + int spriteListIndex = _spriteListIndexes[_header._spritesIndex]; + int newIndex = -1; + + for (uint idx = _oldFrameEntry; idx < _frameEntries.size(); ++idx) { + if (_frameEntries[idx]._frameNumber > _currentFrame) + break; + if (_frameEntries[idx]._spriteSlot._spritesIndex == spriteListIndex) + newIndex = _frameEntries[idx]._spriteSlot._frameNumber; + } + + if (newIndex >= 0) + loadFrame(newIndex); + } + + // If it's not time for the next frame, then exit + if (_vm->_game->_scene._frameStartTime < _nextFrameTimer) + return; + + for (uint idx = 0; idx < scene._spriteSlots.size(); ++idx) { + if (scene._spriteSlots[idx]._seqIndex >= 0x80) + scene._spriteSlots[idx]._flags = IMG_ERASE; + } + + // Validate the current frame + if (_currentFrame >= (int)_miscEntries.size()) { + // Is the animation allowed to be repeated? + if (_resetFlag) { + _currentFrame = 0; + _oldFrameEntry = 0; + } else { + _freeFlag = true; + return; + } + } + + // Handle executing any sound command for this frame + AnimMiscEntry &misc = _miscEntries[_currentFrame]; + if (misc._soundId) + _vm->_sound->command(misc._soundId); + + // Handle any screen scrolling + if (hasScroll()) { + scene._backgroundSurface.scrollX(_header._scrollPosition.x); + scene._backgroundSurface.scrollY(_header._scrollPosition.y); + scene._spriteSlots.fullRefresh(); + } + + // Handle any offset adjustment for sprites as of this frame + bool paChanged = false; + if (scene._posAdjust.x != misc._posAdjust.x) { + scene._posAdjust.x = misc._posAdjust.x; + paChanged = true; + } + if (scene._posAdjust.y != misc._posAdjust.y) { + scene._posAdjust.y = misc._posAdjust.y; + paChanged = true; + } + + if (paChanged) { + int newIndex = scene._spriteSlots.add(); + scene._spriteSlots[newIndex]._seqIndex = -1; + scene._spriteSlots[newIndex]._flags = IMG_REFRESH; + } + + // Main frame animation loop - frames get animated by being placed, as necessary, into the + // main sprite slot array + while ((uint)_oldFrameEntry < _frameEntries.size()) { + if (_frameEntries[_oldFrameEntry]._frameNumber > _currentFrame) + break; + else if (_frameEntries[_oldFrameEntry]._frameNumber == _currentFrame) { + // Found the correct frame + int spriteSlotIndex = 0; + int index = 0; + + for (;;) { + if ((spriteSlotIndex == 0) && (index < (int)scene._spriteSlots.size())) { + int seqIndex = _frameEntries[_oldFrameEntry]._seqIndex - scene._spriteSlots[index]._seqIndex; + if (seqIndex == 0x80) { + if (scene._spriteSlots[index] == _frameEntries[_oldFrameEntry]._spriteSlot) { + scene._spriteSlots[index]._flags = IMG_STATIC; + spriteSlotIndex = -1; + } + } + ++index; + continue; + } + + if (spriteSlotIndex == 0) { + int slotIndex = scene._spriteSlots.add(); + SpriteSlot &slot = scene._spriteSlots[slotIndex]; + slot.copy(_frameEntries[_oldFrameEntry]._spriteSlot); + slot._seqIndex = _frameEntries[_oldFrameEntry]._seqIndex + 0x80; + + SpriteAsset &spriteSet = *scene._sprites[ + scene._spriteSlots[slotIndex]._spritesIndex]; + slot._flags = spriteSet.isBackground() ? IMG_DELTA : IMG_UPDATE; + } + break; + } + } + + ++_oldFrameEntry; + } + + // Handle the display of any messages + for (uint idx = 0; idx < _messages.size(); ++idx) { + if (_messages[idx]._kernelMsgIndex >= 0) { + // Handle currently active message + if ((_currentFrame < _messages[idx]._startFrame) || (_currentFrame > _messages[idx]._endFrame)) { + scene._kernelMessages.remove(_messages[idx]._kernelMsgIndex); + _messages[idx]._kernelMsgIndex = -1; + --_messageCtr; + } + } else if ((_currentFrame >= _messages[idx]._startFrame) && (_currentFrame <= _messages[idx]._endFrame)) { + // Start displaying the message + AnimMessage &me = _messages[idx]; + + // The color index to use is dependant on how many messages are currently on-screen + uint8 colIndex; + switch (_messageCtr) { + case 1: + colIndex = 252; + break; + case 2: + colIndex = 16; + break; + default: + colIndex = 250; + break; + } + + _vm->_palette->setEntry(colIndex, me._rgb1[0], me._rgb1[1], me._rgb1[2]); + _vm->_palette->setEntry(colIndex + 1, me._rgb2[0], me._rgb2[1], me._rgb2[2]); + + // Add a kernel message to display the given text + me._kernelMsgIndex = scene._kernelMessages.add(me._pos, colIndex * 0x101 + 0x100, + 0, 0, INDEFINITE_TIMEOUT, me._msg); + assert(me._kernelMsgIndex >= 0); + ++_messageCtr; + } + } + + // Move to the next frame + _currentFrame++; + if (_currentFrame >= (int)_miscEntries.size()) { + // Animation is complete + if (_trigger != 0) { + _vm->_game->_trigger = _trigger; + _vm->_game->_triggerMode = _triggerMode; + + if (_triggerMode != SEQUENCE_TRIGGER_DAEMON) { + // Copy the noun list + scene._action._activeAction = _actionDetails; + } + } + } + + int frameNum = MIN(_currentFrame, (int)_miscEntries.size() - 1); + _nextFrameTimer = _vm->_game->_scene._frameStartTime + _miscEntries[frameNum]._numTicks; +} + +void Animation::setCurrentFrame(int frameNumber) { + _currentFrame = frameNumber; + _oldFrameEntry = 0; + _freeFlag = false; + + _nextScrollTimer = _nextFrameTimer = _vm->_game->_scene._frameStartTime; +} + +void Animation::setNextFrameTimer(int frameNumber) { + _nextFrameTimer = frameNumber; +} + +} // End of namespace MADS diff --git a/engines/mads/animation.h b/engines/mads/animation.h new file mode 100644 index 0000000000..15086d3e41 --- /dev/null +++ b/engines/mads/animation.h @@ -0,0 +1,230 @@ +/* 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. + * + */ + +#ifndef MADS_ANIMATION_H +#define MADS_ANIMATION_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/rect.h" +#include "mads/msurface.h" +#include "mads/scene_data.h" +#include "mads/font.h" +#include "mads/user_interface.h" + +namespace MADS { + +enum AnimFlag { + ANIMFLAG_DITHER = 0x0001, // Dither to 16 colors + ANIMFLAG_CUSTOM_FONT = 0x0020, // Load ccustom font + ANIMFLAG_LOAD_BACKGROUND = 0x0100, // Load background + ANIMFLAG_LOAD_BACKGROUND_ONLY = 0x0200 // Load background only +}; + +enum AnimBgType { + ANIMBG_ROOM = 1, ANIMBG_FULL_SIZE = 2, ANIMBG_BLACK_SCREEN = 3, + ANIMBG_INTERFACE = 4 +}; + +class MADSEngine; +class Scene; + +class AnimMessage { +public: + int16 _soundId; + Common::String _msg; + Common::Point _pos; + byte _rgb1[3], _rgb2[3]; + int _flags; + int _startFrame, _endFrame; + int _kernelMsgIndex; + + /** + * Loads data for the message from a stream + */ + void load(Common::SeekableReadStream *f); +}; + +class AnimFrameEntry { +public: + int _frameNumber; + int _seqIndex; + SpriteSlotSubset _spriteSlot; + + /** + * Loads data for the record + */ + void load(Common::SeekableReadStream *f, bool uiFlag); +}; + +class AnimMiscEntry { +public: + int _soundId; + int _msgIndex; + int _numTicks; + Common::Point _posAdjust; + int _field8; + + /** + * Loads data for the record + */ + void load(Common::SeekableReadStream *f); +}; + +#define ANIM_SPAWN_COUNT 2 + +class AnimUIEntry { +public: + int _probability; + int _imageCount; + int _firstImage; + int _lastImage; + int _counter; + int _spawn[ANIM_SPAWN_COUNT]; + int _spawnFrame[ANIM_SPAWN_COUNT]; + int _sound; + int _soundFrame; + + /** + * Loads the data for the record + */ + void load(Common::SeekableReadStream *f); +}; + +class AAHeader { +public: + int _spriteSetsCount; + int _miscEntriesCount; + int _frameEntriesCount; + int _messagesCount; + byte _flags; + AnimBgType _bgType; + int _roomNumber; + bool _manualFlag; + int _spritesIndex; + Common::Point _scrollPosition; + uint32 _scrollTicks; + Common::String _interfaceFile; + Common::StringArray _spriteSetNames; + Common::String _lbmFilename; + Common::String _spritesFilename; + Common::String _soundName; + Common::String _dsrName; + Common::String _fontResource; + + /** + * Loads the data for a animation file header + */ + void load(Common::SeekableReadStream *f); +}; + +class Animation { +private: + MADSEngine *_vm; + Scene *_scene; + + Common::Array<AnimMiscEntry> _miscEntries; + Common::Array<SpriteAsset *> _spriteSets; + Font *_font; + + bool _freeFlag; + bool _skipLoad; + int _unkIndex; + Common::Point _unkList[2]; + uint32 _nextFrameTimer; + uint32 _nextScrollTimer; + int _messageCtr; + int _trigger; + TriggerMode _triggerMode; + ActionDetails _actionDetails; + + /** + * Load data for a given frame + * @param frameNumber Frame number + */ + void loadFrame(int frameNumber); + + bool drawFrame(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber); + + /** + * Load the user interface display for an animation + */ + void loadInterface(UserInterface &interfaceSurface, DepthSurface &depthSurface, + AAHeader &header, int flags, Common::Array<PaletteCycle> *palCycles, SceneInfo *sceneInfo); + + /** + * Returns true if there is a scroll required + */ + bool hasScroll() const; +protected: + Animation(MADSEngine *vm, Scene *scene); +public: + AAHeader _header; + Common::Array<int> _spriteListIndexes; + Common::Array<AnimFrameEntry> _frameEntries; + Common::Array<AnimUIEntry> _uiEntries; + Common::Array<AnimMessage> _messages; + bool _resetFlag; + int _currentFrame; + int _oldFrameEntry; + + static Animation *init(MADSEngine *vm, Scene *scene); + /* + * Destructor + */ + ~Animation(); + + /** + * Loads animation data + */ + void load(UserInterface &interfaceSurface, DepthSurface &depthSurface, const Common::String &resName, + int flags, Common::Array<PaletteCycle> *palCycles, SceneInfo *sceneInfo); + + /** + * Preload animation data for the scene + */ + void preLoad(const Common::String &resName, int level); + + /** + * Setups up a loaded animation for playback + */ + void startAnimation(int endTrigger); + + /** + * Update the animation + */ + void update(); + + void setNextFrameTimer(int frameNumber); + int getNextFrameTimer() const { return _nextFrameTimer; } + void setCurrentFrame(int frameNumber); + int getCurrentFrame() const { return _currentFrame; } + + bool freeFlag() const { return _freeFlag; } + int roomNumber() const { return _header._roomNumber; } + + void resetSpriteSetsCount() { _header._spriteSetsCount = 0; } // CHECKME: See if it doesn't leak the memory when the destructor is called +}; + +} // End of namespace MADS + +#endif /* MADS_ANIMATION_H */ diff --git a/engines/mads/assets.cpp b/engines/mads/assets.cpp new file mode 100644 index 0000000000..0bbf6177eb --- /dev/null +++ b/engines/mads/assets.cpp @@ -0,0 +1,228 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "mads/mads.h" +#include "mads/assets.h" +#include "mads/compression.h" +#include "mads/events.h" +#include "mads/palette.h" + +namespace MADS { + +SpriteAsset::SpriteAsset(MADSEngine *vm, const Common::String &resourceName, int flags) : _vm(vm) { + Common::String resName = resourceName; + if (!resName.hasSuffix(".SS") && !resName.hasSuffix(".ss")) + resName += ".SS"; + _srcSize = 0; + + File file(resName); + load(&file, flags); + + file.close(); +} + +SpriteAsset::SpriteAsset(MADSEngine *vm, Common::SeekableReadStream *stream, int flags) : _vm(vm) { + _srcSize = 0; + + load(stream, flags); +} + +SpriteAsset::~SpriteAsset() { + if (_usageIndex) + _vm->_palette->_paletteUsage.resetPalFlags(_usageIndex); + + for (uint i = 0; i < _frames.size(); ++i) + delete _frames[i]._frame; + + delete _charInfo; +} + +void SpriteAsset::load(Common::SeekableReadStream *stream, int flags) { + int curFrame = 0; + uint32 frameOffset = 0; + MadsPack sprite(stream); + _frameRate = 0; + _pixelSpeed = 0; + _maxWidth = 0; + _maxHeight = 0; + _usageIndex = -1; + + Common::SeekableReadStream *spriteStream = sprite.getItemStream(0); + _mode = spriteStream->readByte(); + spriteStream->skip(1); + int type1 = spriteStream->readUint16LE(); + int type2 = spriteStream->readUint16LE(); + _isBackground = (type1 != 0) && (type2 < 4); + spriteStream->skip(32); + _frameCount = spriteStream->readUint16LE(); + + if ((flags & SPRITE_SET_CHAR_INFO) == 0) + _charInfo = nullptr; + else + _charInfo = new SpriteSetCharInfo(spriteStream); + + delete spriteStream; + + // Get the palette data + Common::SeekableReadStream *palStream = sprite.getItemStream(2); + Common::Array<RGB6> palette; + + int numColors = palStream->readUint16LE(); + assert(numColors <= 252); + _colorCount = numColors; + + // Load in the palette + palette.resize(numColors); + for (int i = 0; i < numColors; ++i) + palette[i].load(palStream); + delete palStream; + + // Process the palette data + if (flags & 9) { + _usageIndex = 0; + + if (flags & 8) { + int newPalCtr = 0; + + for (uint i = 0; i < palette.size(); ++i) { + RGB6 &rgb = palette[i]; + + // Scan for existing rgb at beginning of the main palette + bool found = false; + for (int pIndex = 0; pIndex < 4 && !found; ++pIndex) { + byte *palP = &_vm->_palette->_mainPalette[pIndex * 3]; + if (palP[0] == rgb.r && palP[1] == rgb.g && palP[2] == rgb.b) { + rgb._palIndex = pIndex; + found = true; + } + } + + if (!found) { + // Existing palette entry not found, so need to add it in + int palIndex = (0xF7F607 >> (8 * newPalCtr)) & 0xff; + byte *palP = &_vm->_palette->_mainPalette[palIndex * 3]; + palP[0] = rgb.r; + palP[1] = rgb.g; + palP[2] = rgb.b; + rgb._palIndex = palIndex; + + newPalCtr = MIN(newPalCtr + 1, 2); + } + } + } + } else { + _usageIndex = _vm->_palette->_paletteUsage.process(palette, flags); + assert(_usageIndex >= 0); + } + + spriteStream = sprite.getItemStream(1); + Common::SeekableReadStream *spriteDataStream = sprite.getItemStream(3); + SpriteAssetFrame frame; + Common::Array<int> frameSizes; + for (curFrame = 0; curFrame < _frameCount; curFrame++) { + frame._stream = 0; + frame._comp = 0; + frameOffset = spriteStream->readUint32LE(); + _frameOffsets.push_back(frameOffset); + uint32 frameSize = spriteStream->readUint32LE(); + frameSizes.push_back(frameSize); + + frame._bounds.left = spriteStream->readSint16LE(); + frame._bounds.top = spriteStream->readSint16LE(); + frame._bounds.setWidth(spriteStream->readUint16LE()); + frame._bounds.setHeight(spriteStream->readUint16LE()); + + if (curFrame == 0) + debugC(1, kDebugGraphics, "%i frames, x = %i, y = %i, w = %i, h = %i\n", + _frameCount, frame._bounds.left, frame._bounds.top, + frame._bounds.width(), frame._bounds.height()); + + if (_mode == 0) { + // Create a frame and decompress the raw pixel data + uint32 currPos = (uint32)spriteDataStream->pos(); + frame._frame = new MSprite(spriteDataStream, palette, frame._bounds); + assert((uint32)spriteDataStream->pos() == (currPos + frameSize)); + } + + _frames.push_back(frame); + } + + if (_mode != 0) { + // Handle decompressing Fab encoded data + for (curFrame = 0; curFrame < _frameCount; curFrame++) { + FabDecompressor fab; + + int srcSize = (curFrame == (_frameCount - 1)) ? spriteDataStream->size() - _frameOffsets[curFrame] : + _frameOffsets[curFrame + 1] - _frameOffsets[curFrame]; + byte *srcData = new byte[srcSize]; + assert(srcData); + spriteDataStream->read(srcData, srcSize); + + byte *destData = new byte[frameSizes[curFrame]]; + assert(destData); + + fab.decompress(srcData, srcSize, destData, frameSizes[curFrame]); + + // Load the frames + Common::MemoryReadStream *rs = new Common::MemoryReadStream(destData, frameSizes[curFrame]); + _frames[curFrame]._frame = new MSprite(rs, palette, _frames[curFrame]._bounds); + delete rs; + + delete[] srcData; + delete[] destData; + } + } + + delete spriteStream; + delete spriteDataStream; +} + +MSprite *SpriteAsset::getFrame(int frameIndex) { + if ((uint)frameIndex < _frames.size()) { + return _frames[frameIndex]._frame; + } else { + debugC(kDebugGraphics, "SpriteAsset::getFrame: Invalid frame %d, out of %d", frameIndex, _frames.size()); + return _frames[_frames.size() - 1]._frame; + } +} + +/*------------------------------------------------------------------------*/ + +SpriteSetCharInfo::SpriteSetCharInfo(Common::SeekableReadStream *s) { + _totalFrames = s->readByte(); + s->skip(1); + _numEntries = s->readUint16LE(); + + for (int i = 0; i < 16; ++i) + _startFrames[i] = s->readUint16LE(); + for (int i = 0; i < 16; ++i) + _stopFrames[i] = s->readUint16LE(); + for (int i = 0; i < 16; ++i) + _ticksList[i] = s->readUint16LE(); + + _velocity = s->readUint16LE(); + _ticksAmount = s->readByte(); + _centerOfGravity = s->readByte(); +} + +} // End of namespace MADS diff --git a/engines/mads/assets.h b/engines/mads/assets.h new file mode 100644 index 0000000000..9242802187 --- /dev/null +++ b/engines/mads/assets.h @@ -0,0 +1,111 @@ +/* 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. + * + */ + +#ifndef MADS_ASSETS_H +#define MADS_ASSETS_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "mads/palette.h" + +namespace MADS { + +#define SPRITE_SET_CHAR_INFO 4 + +class MADSEngine; +class MSprite; +class MSurface; + +struct SpriteAssetFrame { + uint32 _stream; + Common::Rect _bounds; + uint32 _comp; + MSprite *_frame; +}; + +class SpriteSetCharInfo { +public: + SpriteSetCharInfo(Common::SeekableReadStream *s); + + int _totalFrames; + int _numEntries; + int _startFrames[16]; + int _stopFrames[16]; + int _ticksList[16]; + int _velocity; + int _ticksAmount; + int _centerOfGravity; +}; + +class SpriteAsset { +private: + MADSEngine *_vm; + byte _palette[PALETTE_SIZE]; + int _colorCount; + uint32 _srcSize; + int _frameRate, _pixelSpeed; + int _maxWidth, _maxHeight; + int _frameCount; + Common::Array<uint32> _frameOffsets; + Common::Array<SpriteAssetFrame> _frames; + uint8 _mode; + bool _isBackground; + + /** + * Load the data for the asset + */ + void load(Common::SeekableReadStream *stream, int flags); +public: + SpriteSetCharInfo *_charInfo; + int _usageIndex; +public: + /** + * Constructor + */ + SpriteAsset(MADSEngine *vm, const Common::String &resourceName, int flags); + + /** + * Constructor + */ + SpriteAsset(MADSEngine *vm, Common::SeekableReadStream *stream, int flags); + + /** + * Destructor + */ + ~SpriteAsset(); + + int getCount() { return _frameCount; } + int getFrameRate() const { return _frameRate; } + int getPixelSpeed() const { return _pixelSpeed; } + int getFrameWidth(int index); + int getFrameHeight(int index); + int getMaxFrameWidth() const { return _maxWidth; } + int getMaxFrameHeight() const { return _maxHeight; } + MSprite *getFrame(int frameIndex); + byte *getPalette() { return _palette; } + int getColorCount() { return _colorCount; } + bool isBackground() const { return _isBackground; } +}; + +} // End of namespace MADS + +#endif /* MADS_ASSETS_H */ diff --git a/engines/mads/audio.cpp b/engines/mads/audio.cpp new file mode 100644 index 0000000000..1c61e13957 --- /dev/null +++ b/engines/mads/audio.cpp @@ -0,0 +1,129 @@ +/* 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. + * + */ + +#include "mads/audio.h" +#include "mads/compression.h" + +#include "common/stream.h" +#include "audio/audiostream.h" +#include "audio/mixer.h" +#include "audio/decoders/raw.h" + +namespace MADS { + +AudioPlayer::AudioPlayer(Audio::Mixer *mixer, uint32 gameID) : _mixer(mixer), _gameID(gameID) { + setVolume(Audio::Mixer::kMaxChannelVolume); + setDefaultSoundGroup(); +} + +AudioPlayer::~AudioPlayer() { + _dsrEntries.clear(); +} + +bool AudioPlayer::isPlaying() const { + return _mixer->isSoundHandleActive(_handle); +} + +void AudioPlayer::setVolume(int volume) { + _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, volume); + _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, volume); +} + +void AudioPlayer::setDefaultSoundGroup() { + switch (_gameID) { + case GType_RexNebular: + setSoundGroup("rex009.dsr"); + break; + case GType_Dragonsphere: + setSoundGroup("drag009.dsr"); + break; + case GType_Phantom: + setSoundGroup("phan009.dsr"); + break; + default: + error("setDefaultSoundGroup: Unknown game"); + } +} + +void AudioPlayer::setSoundGroup(const Common::String &filename) { + _dsrEntries.clear(); + + _filename = filename; + _dsrFile.open(filename); + + // Read header + uint16 entryCount = _dsrFile.readUint16LE(); + + for (uint16 i = 0; i < entryCount; i++) { + DSREntry newEntry; + newEntry.frequency = _dsrFile.readUint16LE(); + newEntry.channels = _dsrFile.readUint32LE(); + newEntry.compSize = _dsrFile.readUint32LE(); + newEntry.uncompSize = _dsrFile.readUint32LE(); + newEntry.offset = _dsrFile.readUint32LE(); + _dsrEntries.push_back(newEntry); + } + + _dsrFile.close(); +} + +void AudioPlayer::playSound(int soundIndex, bool loop) { + if (_dsrEntries.empty()) { + warning("DSR file not loaded, not playing sound"); + return; + } + + if (soundIndex < 0 || soundIndex > (int)_dsrEntries.size() - 1) { + warning("Invalid sound index: %i (max %i), not playing sound", soundIndex, _dsrEntries.size() - 1); + return; + } + + // Get sound data + FabDecompressor fab; + int32 compSize = _dsrEntries[soundIndex].compSize; + int32 uncompSize = _dsrEntries[soundIndex].uncompSize; + int32 offset = _dsrEntries[soundIndex].offset; + int16 frequency = _dsrEntries[soundIndex].frequency; + byte *compData = new byte[compSize]; + byte *buffer = new byte[uncompSize]; + _dsrFile.open(_filename); + _dsrFile.seek(offset, SEEK_SET); + _dsrFile.read(compData, compSize); + _dsrFile.close(); + + fab.decompress(compData, compSize, buffer, uncompSize); + + // Play sound + Audio::AudioStream *stream = Audio::makeLoopingAudioStream( + Audio::makeRawStream(buffer, uncompSize, frequency, Audio::FLAG_UNSIGNED), + loop ? 0 : 1); + _mixer->playStream(Audio::Mixer::kSFXSoundType, &_handle, stream, -1, Audio::Mixer::kMaxChannelVolume); + + /* + // Dump the sound file + FILE *destFile = fopen("sound.raw", "wb"); + fwrite(_dsrFile.dsrEntries[soundIndex]->data, _dsrFile.dsrEntries[soundIndex].uncompSize, 1, destFile); + fclose(destFile); + */ +} + +} // End of namespace M4 diff --git a/engines/mads/audio.h b/engines/mads/audio.h new file mode 100644 index 0000000000..21f4bed59a --- /dev/null +++ b/engines/mads/audio.h @@ -0,0 +1,64 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 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. + * + */ + +#ifndef MADS_AUDIO_H +#define MADS_AUDIO_H + +#include "mads/resources.h" + +#include "common/array.h" +#include "audio/mixer.h" + +namespace MADS { + +struct DSREntry { + int16 frequency; + int channels; + int32 compSize; + int32 uncompSize; + int32 offset; +}; + +class AudioPlayer { +public: + AudioPlayer(Audio::Mixer *mixer, uint32 gameID); + ~AudioPlayer(); + + void setSoundGroup(const Common::String &filename); + void setDefaultSoundGroup(); + void playSound(int soundIndex, bool loop = false); + void setVolume(int volume); + bool isPlaying() const; + + private: + Audio::Mixer *_mixer; + Audio::SoundHandle _handle; + uint32 _gameID; + + File _dsrFile; + Common::String _filename; + Common::Array<DSREntry> _dsrEntries; +}; + +} // End of namespace MADS + +#endif diff --git a/engines/mads/compression.cpp b/engines/mads/compression.cpp new file mode 100644 index 0000000000..79cd1786de --- /dev/null +++ b/engines/mads/compression.cpp @@ -0,0 +1,194 @@ +/* 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. + * + */ + +#include "mads/compression.h" + +namespace MADS { + +const char *const madsPackString = "MADSPACK"; +const char *const FabInputExceededError = "FabDecompressor - Passed end of input buffer during decompression"; +const char *const FabOutputExceededError = "FabDecompressor - Decompressed data exceeded specified size"; + +bool MadsPack::isCompressed(Common::SeekableReadStream *stream) { + // Check whether the passed stream is packed + + char tempBuffer[8]; + stream->seek(0); + if (stream->read(tempBuffer, 8) == 8) { + if (!strncmp(tempBuffer, madsPackString, 8)) + return true; + } + + return false; +} + +MadsPack::MadsPack(Common::SeekableReadStream *stream) { + initialize(stream); +} + +MadsPack::MadsPack(const Common::String &resourceName, MADSEngine *vm) { + File file(resourceName); + initialize(&file); + file.close(); +} + +void MadsPack::initialize(Common::SeekableReadStream *stream) { + if (!MadsPack::isCompressed(stream)) + error("Attempted to decompress a resource that was not MadsPacked"); + + stream->seek(14); + _count = stream->readUint16LE(); + _items = new MadsPackEntry[_count]; + + byte *headerData = new byte[0xA0]; + byte *header = headerData; + stream->read(headerData, 0xA0); + + for (int i = 0; i < _count; ++i, header += 10) { + // Get header data + _items[i]._type = (CompressionType)*header; + _items[i]._priority = *(header + 1); + _items[i]._size = READ_LE_UINT32(header + 2); + _items[i]._compressedSize = READ_LE_UINT32(header + 6); + + byte *sourceData = new byte[_items[i]._compressedSize]; + stream->read(sourceData, _items[i]._compressedSize); + + switch (_items[i]._type) { + case COMPRESS_NONE: + // Entry isn't compressed + _items[i]._data = sourceData; + break; + + case COMPRESS_FAB: { + // Decompress the entry + _items[i]._data = new byte[_items[i]._size]; + + FabDecompressor fab; + fab.decompress(sourceData, _items[i]._compressedSize, _items[i]._data, _items[i]._size); + delete[] sourceData; + break; + } + + default: + error("Unknown compression type encountered"); + } + } + + delete[] headerData; + _dataOffset = stream->pos(); +} + +MadsPack::~MadsPack() { + for (int i = 0; i < _count; ++i) + delete[] _items[i]._data; + delete[] _items; +} + +//-------------------------------------------------------------------------- + +void FabDecompressor::decompress(const byte *srcData, int srcSize, byte *destData, int destSize) { + byte copyLen, copyOfsShift, copyOfsMask, copyLenMask; + unsigned long copyOfs; + byte *destP; + + // Validate that the data starts with the FAB header + if (strncmp((const char *)srcData, "FAB", 3) != 0) + error("FabDecompressor - Invalid compressed data"); + + int shiftVal = srcData[3]; + if ((shiftVal < 10) || (shiftVal > 13)) + error("FabDecompressor - Invalid shift start"); + + copyOfsShift = 16 - shiftVal; + copyOfsMask = 0xFF << (shiftVal - 8); + copyLenMask = (1 << copyOfsShift) - 1; + copyOfs = 0xFFFF0000; + destP = destData; + + // Initialize data fields + _srcData = srcData; + _srcP = _srcData + 6; + _srcSize = srcSize; + _bitsLeft = 16; + _bitBuffer = READ_LE_UINT16(srcData + 4); + + for (;;) { + if (getBit() == 0) { + if (getBit() == 0) { + copyLen = ((getBit() << 1) | getBit()) + 2; + copyOfs = *_srcP++ | 0xFFFFFF00; + } else { + copyOfs = (((_srcP[1] >> copyOfsShift) | copyOfsMask) << 8) | _srcP[0]; + copyLen = _srcP[1] & copyLenMask; + _srcP += 2; + if (copyLen == 0) { + copyLen = *_srcP++; + if (copyLen == 0) + break; + else if (copyLen == 1) + continue; + else + copyLen++; + } else { + copyLen += 2; + } + copyOfs |= 0xFFFF0000; + } + while (copyLen-- > 0) { + if (destP - destData == destSize) + error(FabOutputExceededError); + + *destP = destP[(signed int)copyOfs]; + destP++; + } + } else { + if (_srcP - srcData == srcSize) + error(FabInputExceededError); + if (destP - destData == destSize) + error(FabOutputExceededError); + + *destP++ = *_srcP++; + } + } + + if (destP - destData != destSize) + error("FabDecompressor - Decompressed data does not match header decompressed size"); +} + +int FabDecompressor::getBit() { + _bitsLeft--; + if (_bitsLeft == 0) { + if (_srcP - _srcData == _srcSize) + error(FabInputExceededError); + + _bitBuffer = (READ_LE_UINT16(_srcP) << 1) | (_bitBuffer & 1); + _srcP += 2; + _bitsLeft = 16; + } + + int bit = _bitBuffer & 1; + _bitBuffer >>= 1; + return bit; +} + +} // End of namespace MADS diff --git a/engines/mads/compression.h b/engines/mads/compression.h new file mode 100644 index 0000000000..f7381e4af3 --- /dev/null +++ b/engines/mads/compression.h @@ -0,0 +1,89 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 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. + * + */ + +#ifndef MADS_COMPRESSION_H +#define MADS_COMPRESSION_H + +#include "common/scummsys.h" +#include "common/endian.h" +#include "common/memstream.h" +#include "common/stream.h" + +#include "mads/mads.h" + +namespace MADS { + +enum CompressionType { COMPRESS_NONE = 0, COMPRESS_FAB = 1 }; + +struct MadsPackEntry { +public: + CompressionType _type; + byte _priority; + uint32 _size; + uint32 _compressedSize; + byte *_data; +}; + +class MadsPack { +private: + MadsPackEntry *_items; + int _count; + int _dataOffset; + + void initialize(Common::SeekableReadStream *stream); +public: + static bool isCompressed(Common::SeekableReadStream *stream); + MadsPack(Common::SeekableReadStream *stream); + MadsPack(const Common::String &resourceName, MADSEngine *_vm); + ~MadsPack(); + + int getCount() const { return _count; } + MadsPackEntry &getItem(int index) const { + assert(index < _count); + return _items[index]; } + MadsPackEntry &operator[](int index) const { + assert(index < _count); + return _items[index]; + } + Common::MemoryReadStream *getItemStream(int index) { + assert(index < _count); + return new Common::MemoryReadStream(_items[index]._data, _items[index]._size, + DisposeAfterUse::NO); + } + int getDataOffset() const { return _dataOffset; } +}; + +class FabDecompressor { +private: + int _bitsLeft; + uint32 _bitBuffer; + const byte *_srcData, *_srcP; + int _srcSize; + + int getBit(); +public: + void decompress(const byte *srcData, int srcSize, byte *destData, int destSize); +}; + +} // End of namespace MADS + +#endif diff --git a/engines/mads/configure.engine b/engines/mads/configure.engine new file mode 100644 index 0000000000..60d833e9e8 --- /dev/null +++ b/engines/mads/configure.engine @@ -0,0 +1,3 @@ +# This file is included from the main "configure" script +# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] +add_engine mads "Rex Nebular and the Cosmic Gender Bender" no diff --git a/engines/mads/debugger.cpp b/engines/mads/debugger.cpp new file mode 100644 index 0000000000..1ff42c5e2b --- /dev/null +++ b/engines/mads/debugger.cpp @@ -0,0 +1,326 @@ +/* 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. + * + */ + +#include "common/file.h" +#include "mads/mads.h" +#include "mads/debugger.h" + +namespace MADS { + +Debugger::Debugger(MADSEngine *vm) : GUI::Debugger(), _vm(vm) { + _showMousePos = false; + + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("mouse", WRAP_METHOD(Debugger, Cmd_Mouse)); + registerCmd("scene", WRAP_METHOD(Debugger, Cmd_LoadScene)); + registerCmd("show_hotspots", WRAP_METHOD(Debugger, Cmd_ShowHotSpots)); + registerCmd("list_hotspots", WRAP_METHOD(Debugger, Cmd_ListHotSpots)); + registerCmd("play_sound", WRAP_METHOD(Debugger, Cmd_PlaySound)); + registerCmd("play_audio", WRAP_METHOD(Debugger, Cmd_PlayAudio)); + registerCmd("show_codes", WRAP_METHOD(Debugger, Cmd_ShowCodes)); + registerCmd("dump_file", WRAP_METHOD(Debugger, Cmd_DumpFile)); + registerCmd("show_quote", WRAP_METHOD(Debugger, Cmd_ShowQuote)); + registerCmd("show_vocab", WRAP_METHOD(Debugger, Cmd_ShowVocab)); + registerCmd("dump_vocab", WRAP_METHOD(Debugger, Cmd_DumpVocab)); + registerCmd("show_message", WRAP_METHOD(Debugger, Cmd_ShowMessage)); + registerCmd("show_item", WRAP_METHOD(Debugger, Cmd_ShowItem)); + registerCmd("dump_items", WRAP_METHOD(Debugger, Cmd_DumpItems)); + registerCmd("item", WRAP_METHOD(Debugger, Cmd_Item)); +} + +static int strToInt(const char *s) { + if (!*s) + // No string at all + return 0; + else if (toupper(s[strlen(s) - 1]) != 'H') + // Standard decimal string + return atoi(s); + + // Hexadecimal string + uint tmp = 0; + int read = sscanf(s, "%xh", &tmp); + if (read < 1) + error("strToInt failed on string \"%s\"", s); + return (int)tmp; +} + +bool Debugger::Cmd_Mouse(int argc, const char **argv) { + if (argc < 2) { + debugPrintf("Usage: %s [ on | off ]\n", argv[0]); + } else { + _showMousePos = strcmp(argv[1], "on") == 0; + } + + return true; +} + +bool Debugger::Cmd_LoadScene(int argc, const char **argv) { + if (argc != 2) { + debugPrintf("Current scene is: %d\n", _vm->_game->_scene._currentSceneId); + debugPrintf("Usage: %s <scene number>\n", argv[0]); + return true; + } else { + _vm->_game->_scene._nextSceneId = strToInt(argv[1]); + return false; + } +} + +bool Debugger::Cmd_ShowHotSpots(int argc, const char **argv) { + Scene &scene = _vm->_game->_scene; + + // hotspots + byte hotspotCol = _vm->getRandomNumber(255); + for (uint i = 0; i < scene._hotspots.size(); i++) { + scene._backgroundSurface.frameRect(scene._hotspots[i]._bounds, hotspotCol); + } + + // Dynamic hotspots (red) + hotspotCol = _vm->getRandomNumber(255); + for (uint i = 0; i < scene._dynamicHotspots.size(); i++) { + scene._backgroundSurface.frameRect(scene._dynamicHotspots[i]._bounds, hotspotCol); + } + + scene._spriteSlots.fullRefresh(); + return false; +} + +bool Debugger::Cmd_ListHotSpots(int argc, const char **argv) { + Hotspots &hotspots = _vm->_game->_scene._hotspots; + + debugPrintf("%d hotspots present\n", hotspots.size()); + + for (uint index = 0; index < hotspots.size(); ++index) { + debugPrintf("(%d): %p x1 = %d; y1 = %d; x2 = %d; y2 = %d\n", + index, (void *)&hotspots[index], + hotspots[index]._bounds.left, hotspots[index]._bounds.top, + hotspots[index]._bounds.right, hotspots[index]._bounds.bottom); + } + + return true; +} + +bool Debugger::Cmd_PlaySound(int argc, const char **argv) { + if (argc < 2) { + debugPrintf("Usage: %s <sound file>\n", argv[0]); + } else { + int commandId = strToInt(argv[1]); + int param = (argc >= 3) ? strToInt(argv[2]) : 0; + + _vm->_sound->command(commandId, param); + } + + return false; +} + +bool Debugger::Cmd_PlayAudio(int argc, const char **argv) { + if (argc < 2) { + debugPrintf("Usage: %s <sound index> <sound group>\n", argv[0]); + debugPrintf("If the sound group isn't defined, the default one will be used\n"); + } else { + int index = strToInt(argv[1]); + Common::String soundGroup = (argc >= 3) ? argv[2] : ""; + if (argc >= 3) + _vm->_audio->setSoundGroup(argv[2]); + else + _vm->_audio->setDefaultSoundGroup(); + + _vm->_audio->playSound(index); + } + + return true; +} + +bool Debugger::Cmd_ShowCodes(int argc, const char **argv) { + Scene &scene = _vm->_game->_scene; + + // Copy the depth/walk surface to the background and flag for screen refresh + scene._depthSurface.copyTo(&scene._backgroundSurface); + scene._spriteSlots.fullRefresh(); + + // Draw the locations of scene nodes onto the background + int color = _vm->getRandomNumber(255); + for (int i = 0; i < (int)scene._sceneInfo->_nodes.size(); ++i) { + Common::Point &pt = scene._sceneInfo->_nodes[i]._walkPos; + + scene._backgroundSurface.hLine(pt.x - 2, pt.y, pt.x + 2, color); + scene._backgroundSurface.vLine(pt.x, pt.y - 2, pt.y + 2, color); + } + + return false; +} + +bool Debugger::Cmd_DumpFile(int argc, const char **argv) { + if (argc != 2) { + debugPrintf("Usage: %s <resource>\n", argv[0]); + } else { + Common::DumpFile outFile; + Common::File inFile; + + if (!inFile.open(argv[1])) { + debugPrintf("Specified resource does not exist\n"); + } else { + outFile.open(argv[1]); + byte *data = new byte[inFile.size()]; + + inFile.read(data, inFile.size()); + outFile.write(data, inFile.size()); + outFile.flush(); + + delete[] data; + inFile.close(); + outFile.close(); + + debugPrintf("File written successfully.\n"); + } + } + + return true; +} + +bool Debugger::Cmd_ShowQuote(int argc, const char **argv) { + if (argc != 2) + debugPrintf("Usage: %s <quote number>\n", argv[0]); + else + debugPrintf("%s", _vm->_game->getQuote(strToInt(argv[1])).c_str()); + + return true; +} + +bool Debugger::Cmd_ShowVocab(int argc, const char **argv) { + if (argc != 2) { + for (uint32 i = 0; i < _vm->_game->_scene.getVocabStringsCount(); i++) { + debugPrintf("%03d: '%s'\n", i, _vm->_game->_scene.getVocab(i + 1).c_str()); + } + } else { + int vocabId = strToInt(argv[1]); + debugPrintf("%03d: '%s'\n", vocabId, _vm->_game->_scene.getVocab(vocabId + 1).c_str()); + } + + return true; +} + +bool Debugger::Cmd_DumpVocab(int argc, const char **argv) { + Common::DumpFile outFile; + outFile.open("vocab.txt"); + + for (uint32 i = 0; i < _vm->_game->_scene.getVocabStringsCount(); i++) { + Common::String curId = Common::String::format("%x", i + 1); + Common::String curVocab = _vm->_game->_scene.getVocab(i + 1); + curVocab.toUppercase(); + + for (uint j = 0; j < curVocab.size(); j++) { + if (curVocab[j] == ' ' || curVocab[j] == '-') + curVocab.setChar('_', j); + } + + Common::String cur = "\tNOUN_" + curVocab + " = 0x" + curId + ",\n"; + + outFile.writeString(cur.c_str()); + } + + outFile.flush(); + outFile.close(); + + debugPrintf("Game vocab dumped\n"); + + return true; +} + +bool Debugger::Cmd_ShowMessage(int argc, const char **argv) { + if (argc != 2) { + debugPrintf("Usage: %s <message number>\n", argv[0]); + } else { + int messageId = strToInt(argv[1]); + Common::StringArray msg = _vm->_game->getMessage(messageId); + for (uint idx = 0; idx < msg.size(); ++idx) { + Common::String srcLine = msg[idx]; + debugPrintf("%s\n", srcLine.c_str()); + } + } + + return true; +} + +bool Debugger::Cmd_ShowItem(int argc, const char **argv) { + InventoryObjects &objects = _vm->_game->_objects; + + if (argc != 2) { + for (uint32 i = 0; i < objects.size(); i++) { + Common::String desc = _vm->_game->_scene.getVocab(objects[i]._descId); + debugPrintf("%03d: '%s'\n", i, desc.c_str()); + } + } else { + int vocabId = strToInt(argv[1]); + Common::String desc = _vm->_game->_scene.getVocab(objects[vocabId]._descId); + debugPrintf("%03d: '%s'\n", vocabId, desc.c_str()); + } + + return true; +} + +bool Debugger::Cmd_DumpItems(int argc, const char **argv) { + InventoryObjects &objects = _vm->_game->_objects; + + Common::DumpFile outFile; + outFile.open("items.txt"); + + for (uint32 i = 0; i < objects.size(); i++) { + Common::String curId = Common::String::format("%d", i); + Common::String desc = _vm->_game->_scene.getVocab(objects[i]._descId); + desc.toUppercase(); + + for (uint j = 0; j < desc.size(); j++) { + if (desc[j] == ' ' || desc[j] == '-') + desc.setChar('_', j); + } + + Common::String cur = "\tOBJ_" + desc + " = " + curId + ",\n"; + + outFile.writeString(cur.c_str()); + } + + outFile.flush(); + outFile.close(); + + debugPrintf("Game items dumped\n"); + + return true; +} + +bool Debugger::Cmd_Item(int argc, const char **argv) { + InventoryObjects &objects = _vm->_game->_objects; + + if (argc != 2) { + debugPrintf("Usage: %s <item number>\n", argv[0]); + return true; + } else { + int objectId = strToInt(argv[1]); + + if (!objects.isInInventory(objectId)) + objects.addToInventory(objectId); + + debugPrintf("Item added.\n"); + return false; + } +} + +} // End of namespace MADS diff --git a/engines/mads/debugger.h b/engines/mads/debugger.h new file mode 100644 index 0000000000..351eb13615 --- /dev/null +++ b/engines/mads/debugger.h @@ -0,0 +1,61 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 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. + * + */ + +#ifndef MADS_DEBUGGER_H +#define MADS_DEBUGGER_H + +#include "common/scummsys.h" +#include "gui/debugger.h" + +namespace MADS { + +class MADSEngine; + +class Debugger : public GUI::Debugger { +private: + MADSEngine *_vm; +protected: + bool Cmd_Mouse(int argc, const char **argv); + bool Cmd_LoadScene(int argc, const char **argv); + bool Cmd_ShowHotSpots(int argc, const char **argv); + bool Cmd_ListHotSpots(int argc, const char **argv); + bool Cmd_PlaySound(int argc, const char **argv); + bool Cmd_PlayAudio(int argc, const char **argv); + bool Cmd_ShowCodes(int argc, const char **argv); + bool Cmd_DumpFile(int argc, const char **argv); + bool Cmd_ShowQuote(int argc, const char **argv); + bool Cmd_ShowVocab(int argc, const char **argv); + bool Cmd_DumpVocab(int argc, const char **argv); + bool Cmd_ShowMessage(int argc, const char **argv); + bool Cmd_ShowItem(int argc, const char **argv); + bool Cmd_DumpItems(int argc, const char **argv); + bool Cmd_Item(int argc, const char **argv); +public: + bool _showMousePos; +public: + Debugger(MADSEngine *vm); + virtual ~Debugger() {} +}; + +} // End of namespace MADS + +#endif /* MADS_DEBUGGER_H */ diff --git a/engines/mads/detection.cpp b/engines/mads/detection.cpp new file mode 100644 index 0000000000..971acde024 --- /dev/null +++ b/engines/mads/detection.cpp @@ -0,0 +1,194 @@ +/* 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. + * + * + */ + +#include "mads/mads.h" + +#include "base/plugins.h" +#include "common/savefile.h" +#include "common/str-array.h" +#include "common/memstream.h" +#include "engines/advancedDetector.h" +#include "common/system.h" +#include "graphics/colormasks.h" +#include "graphics/surface.h" +#include "mads/events.h" +#include "mads/game.h" + +#define MAX_SAVES 99 + +namespace MADS { + +struct MADSGameDescription { + ADGameDescription desc; + + int gameID; + uint32 features; +}; + +uint32 MADSEngine::getGameID() const { + return _gameDescription->gameID; +} + +uint32 MADSEngine::getGameFeatures() const { + return _gameDescription->features; +} + +uint32 MADSEngine::getFeatures() const { + return _gameDescription->desc.flags; +} + +Common::Language MADSEngine::getLanguage() const { + return _gameDescription->desc.language; +} + +Common::Platform MADSEngine::getPlatform() const { + return _gameDescription->desc.platform; +} + +} // End of namespace MADS + +static const PlainGameDescriptor MADSGames[] = { + {"MADS", "MADS"}, + {"dragonsphere", "Dragonsphere"}, + {"nebular", "Rex Nebular and the Cosmic Gender Bender"}, + {"phantom", "Return of the Phantom"}, + {0, 0} +}; + +#include "mads/detection_tables.h" + +class MADSMetaEngine : public AdvancedMetaEngine { +public: + MADSMetaEngine() : AdvancedMetaEngine(MADS::gameDescriptions, sizeof(MADS::MADSGameDescription), MADSGames) { + _maxScanDepth = 3; + } + + virtual const char *getName() const { + return "MADS Engine"; + } + + virtual const char *getOriginalCopyright() const { + return "MADS (c)"; + } + + virtual bool hasFeature(MetaEngineFeature f) const; + virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; + virtual SaveStateList listSaves(const char *target) const; + virtual int getMaximumSaveSlot() const; + virtual void removeSaveState(const char *target, int slot) const; + SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const; +}; + +bool MADSMetaEngine::hasFeature(MetaEngineFeature f) const { + return + (f == kSupportsListSaves) || + (f == kSupportsLoadingDuringStartup) || + (f == kSupportsDeleteSave) || + (f == kSavesSupportMetaInfo) || + (f == kSavesSupportThumbnail); +} + +bool MADS::MADSEngine::hasFeature(EngineFeature f) const { + return + (f == kSupportsRTL) || + (f == kSupportsLoadingDuringRuntime) || + (f == kSupportsSavingDuringRuntime); +} + +bool MADSMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { + const MADS::MADSGameDescription *gd = (const MADS::MADSGameDescription *)desc; + if (gd) { + *engine = new MADS::MADSEngine(syst, gd); + } + return gd != 0; +} + +SaveStateList MADSMetaEngine::listSaves(const char *target) const { + Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); + Common::StringArray filenames; + Common::String saveDesc; + Common::String pattern = Common::String::format("%s.0??", target); + MADS::MADSSavegameHeader header; + + filenames = saveFileMan->listSavefiles(pattern); + sort(filenames.begin(), filenames.end()); // Sort to get the files in numerical order + + SaveStateList saveList; + for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) { + const char *ext = strrchr(file->c_str(), '.'); + int slot = ext ? atoi(ext + 1) : -1; + + if (slot >= 0 && slot < MAX_SAVES) { + Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file); + + if (in) { + MADS::Game::readSavegameHeader(in, header); + saveList.push_back(SaveStateDescriptor(slot, header._saveName)); + + header._thumbnail->free(); + delete header._thumbnail; + delete in; + } + } + } + + return saveList; +} + +int MADSMetaEngine::getMaximumSaveSlot() const { + return MAX_SAVES; +} + +void MADSMetaEngine::removeSaveState(const char *target, int slot) const { + Common::String filename = Common::String::format("%s.%03d", target, slot); + g_system->getSavefileManager()->removeSavefile(filename); +} + +SaveStateDescriptor MADSMetaEngine::querySaveMetaInfos(const char *target, int slot) const { + Common::String filename = Common::String::format("%s.%03d", target, slot); + Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(filename); + + if (f) { + MADS::MADSSavegameHeader header; + MADS::Game::readSavegameHeader(f, header); + delete f; + + // Create the return descriptor + SaveStateDescriptor desc(slot, header._saveName); + desc.setThumbnail(header._thumbnail); + desc.setSaveDate(header._year, header._month, header._day); + desc.setSaveTime(header._hour, header._minute); + desc.setPlayTime(header._totalFrames * GAME_FRAME_TIME); + + return desc; + } + + return SaveStateDescriptor(); +} + + +#if PLUGIN_ENABLED_DYNAMIC(MADS) + REGISTER_PLUGIN_DYNAMIC(MADS, PLUGIN_TYPE_ENGINE, MADSMetaEngine); +#else + REGISTER_PLUGIN_STATIC(MADS, PLUGIN_TYPE_ENGINE, MADSMetaEngine); +#endif diff --git a/engines/mads/detection_tables.h b/engines/mads/detection_tables.h new file mode 100644 index 0000000000..e68ae380d0 --- /dev/null +++ b/engines/mads/detection_tables.h @@ -0,0 +1,122 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 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. + * + */ + +namespace MADS { + +static const MADSGameDescription gameDescriptions[] = { +#if 0 + { + // Rex Nebular and the Cosmic Gender Bender DOS English (compressed) + // Removed for now, until the original floppy compression is supported + { + "nebular", + 0, + { + {"mpslabs.001", 0, "4df5c557b52abb5b661cf4befe5ae301", 1315354}, + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GUIO_NONE) + }, + GType_RexNebular, + 0 + }, +#endif + + { + // Rex Nebular and the Cosmic Gender Bender DOS English + { + "nebular", + 0, + { + {"section1.hag", 0, "6f725eb38660de8af31ec7cdd628d615", 927222}, + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GUIO_NONE) + }, + GType_RexNebular, + 0 + }, + + { + // Rex Nebular and the Cosmic Gender Bender DOS English 8.49 Alternate + { + "nebular", + 0, + { + { "section1.hag", 0, "d583576923e3437937fb7f46f4b6274f", 927222 }, + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GUIO_NONE) + }, + GType_RexNebular, + 0 + }, + + { + // Return of the Phantom DOS English + { + "phantom", + 0, + { + {"section1.hag", 0, "76e2d47a7aebafe48edc9884b3d91782", 1130939}, + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GUIO_NONE) + }, + GType_Phantom, + 0 + }, + + { + // Dragonsphere DOS English + { + "dragonsphere", + 0, + { + {"section1.hag", 0, "2770e441d296be5e806194693eebd95a", 2061199}, + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GUIO_NONE) + }, + GType_Dragonsphere, + 0 + }, + + { AD_TABLE_END_MARKER, 0, 0 } +}; + +} // End of namespace MADS diff --git a/engines/mads/dialogs.cpp b/engines/mads/dialogs.cpp new file mode 100644 index 0000000000..dc8c846beb --- /dev/null +++ b/engines/mads/dialogs.cpp @@ -0,0 +1,398 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "common/config-manager.h" +#include "mads/mads.h" +#include "mads/screen.h" +#include "mads/msurface.h" +#include "mads/nebular/dialogs_nebular.h" + +namespace MADS { + +Dialog::Dialog(MADSEngine *vm) + : _vm(vm), _savedSurface(nullptr), _position(Common::Point(-1, -1)), + _width(0), _height(0) { + TEXTDIALOG_CONTENT1 = 0XF8; + TEXTDIALOG_CONTENT2 = 0XF9; + TEXTDIALOG_EDGE = 0XFA; + TEXTDIALOG_BACKGROUND = 0XFB; + TEXTDIALOG_FC = 0XFC; + TEXTDIALOG_FD = 0XFD; + TEXTDIALOG_FE = 0XFE; + TEXTDIALOG_BLACK = 0; +} + +Dialog::~Dialog() { +} + +void Dialog::save() { + _savedSurface = new MSurface(_width, _height); + _vm->_screen.copyTo(_savedSurface, + Common::Rect(_position.x, _position.y, _position.x + _width, _position.y + _height), + Common::Point()); + + _vm->_screen.copyRectToScreen(getBounds()); +} + +void Dialog::restore() { + if (_savedSurface) { + _savedSurface->copyTo(&_vm->_screen, _position); + delete _savedSurface; + _savedSurface = nullptr; + + _vm->_screen.copyRectToScreen(getBounds()); + + Common::copy(&_dialogPalette[0], &_dialogPalette[8 * 3], + &_vm->_palette->_mainPalette[248 * 3]); + _vm->_palette->setPalette(_vm->_palette->_mainPalette, 248, 8); + } +} + +void Dialog::draw() { + // Calculate the dialog positioning + calculateBounds(); + + // Save the screen portion the dialog will overlap + save(); + + setDialogPalette(); + + // Draw the dialog + // Fill entire content of dialog + Common::Rect bounds = getBounds(); + _vm->_screen.fillRect(bounds, TEXTDIALOG_BACKGROUND); + + // Draw the outer edge lines + _vm->_screen.hLine(_position.x + 1, _position.y + _height - 2, + _position.x + _width - 2, TEXTDIALOG_EDGE); + _vm->_screen.hLine(_position.x, _position.y + _height - 1, + _position.x + _width - 1, TEXTDIALOG_EDGE); + _vm->_screen.vLine(_position.x + _width - 2, _position.y + 2, + _position.y + _height - 2, TEXTDIALOG_EDGE); + _vm->_screen.vLine(_position.x + _width - 1, _position.y + 1, + _position.y + _height - 1, TEXTDIALOG_EDGE); + + // Draw the gravelly dialog content + drawContent(Common::Rect(_position.x + 2, _position.y + 2, + _position.x + _width - 2, _position.y + _height - 2), 0, + TEXTDIALOG_CONTENT1, TEXTDIALOG_CONTENT2); +} + +void Dialog::setDialogPalette() { + // Save the high end of the palette, and set up the entries for dialog display + Common::copy(&_vm->_palette->_mainPalette[TEXTDIALOG_CONTENT1 * 3], + &_vm->_palette->_mainPalette[TEXTDIALOG_CONTENT1 * 3 + 8 * 3], + &_dialogPalette[0]); + Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_CONTENT1, 2, 0x90, 0x80); + Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_EDGE, 2, 0x9C, 0x70); + Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_FC, 2, 0x90, 0x80); + Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_FE, 1, 0xDC, 0xDC); + + _vm->_palette->setPalette(_vm->_palette->_mainPalette + (TEXTDIALOG_CONTENT1 * 3), + TEXTDIALOG_CONTENT1, 8); +} + +void Dialog::calculateBounds() { +} + +void Dialog::drawContent(const Common::Rect &r, int seed, byte color1, byte color2) { + uint16 currSeed = seed ? seed : 0xB78E; + + for (int yp = 0; yp < r.height(); ++yp) { + byte *destP = _vm->_screen.getBasePtr(r.left, r.top + yp); + + for (int xp = 0; xp < r.width(); ++xp) { + uint16 seedAdjust = currSeed; + currSeed += 0x181D; + seedAdjust = (seedAdjust >> 9) | ((seedAdjust & 0x1ff) << 7); + currSeed ^= seedAdjust; + seedAdjust = (seedAdjust >> 3) | ((seedAdjust & 7) << 13); + currSeed += seedAdjust; + + *destP++ = (currSeed & 0x10) ? color2 : color1; + } + } +} + +/*------------------------------------------------------------------------*/ + +TextDialog::TextDialog(MADSEngine *vm, const Common::String &fontName, + const Common::Point &pos, int maxChars) + : Dialog(vm) { + _vm = vm; + _font = _vm->_font->getFont(fontName); + _position = pos; + + _vm->_font->setColors(TEXTDIALOG_BLACK, TEXTDIALOG_BLACK, TEXTDIALOG_BLACK, TEXTDIALOG_BLACK); + + _innerWidth = (_font->maxWidth() + 1) * maxChars; + _width = _innerWidth + 10; + _lineSize = maxChars * 2; + _lineWidth = 0; + _currentX = 0; + _numLines = 0; + Common::fill(&_lineXp[0], &_lineXp[TEXT_DIALOG_MAX_LINES], 0); + _askLineNum = -1; + _askXp = 0; +} + +TextDialog::~TextDialog() { +} + +void TextDialog::addLine(const Common::String &line, bool underline) { + if (_lineWidth > 0 || _currentX > 0) + incNumLines(); + + int stringWidth = _font->getWidth(line, 1); + if (stringWidth >= _innerWidth || (int)line.size() >= _lineSize) { + wordWrap(line); + } else { + _lineXp[_numLines] = (_innerWidth / 2) - (stringWidth / 2); + _lines[_numLines] = line; + + if (underline) + underlineLine(); + } + + incNumLines(); +} + +void TextDialog::underlineLine() { + _lineXp[_numLines] |= 0x80; +} + +void TextDialog::downPixelLine() { + _lineXp[_numLines] |= 0x40; +} + +void TextDialog::incNumLines() { + _lineWidth = 0; + _currentX = 0; + if (++_numLines == TEXT_DIALOG_MAX_LINES) + error("Exceeded text dialog line max"); +} + +void TextDialog::wordWrap(const Common::String &line) { + Common::String tempLine; + + if (!line.empty()) { + const char *srcP = line.c_str(); + + do { + tempLine = ""; + bool endWord = false; + bool newLine = false; + bool continueFlag = true; + + do { + if (!*srcP) { + continueFlag = false; + } else { + tempLine += *srcP; + + if (*srcP == 10) { + continueFlag = false; + newLine = true; + ++srcP; + tempLine.deleteLastChar(); + } else if (*srcP == ' ') { + ++srcP; + endWord = true; + } else if (!endWord) { + ++srcP; + } else { + tempLine.deleteLastChar(); + continueFlag = false; + } + } + } while (continueFlag); + + if (tempLine.hasSuffix(" ")) + tempLine.deleteLastChar(); + + Common::String tempLine2; + if (_currentX > 0) + tempLine2 += ' '; + tempLine2 += tempLine; + + int lineWidth = _font->getWidth(tempLine2, 1); + if (((_currentX + (int)tempLine2.size()) > _lineSize) || + ((_lineWidth + lineWidth) > _innerWidth)) { + incNumLines(); + appendLine(tempLine); + } else { + appendLine(tempLine2); + } + + if (newLine) + incNumLines(); + } while (*srcP); + } +} + +void TextDialog::appendLine(const Common::String &line) { + _currentX += line.size(); + _lineWidth += _font->getWidth(line, 1) + 1; + _lines[_numLines] += line; +} + +void TextDialog::addInput() { + _askXp = _currentX + 1; + _askLineNum = _numLines; + incNumLines(); +} + +void TextDialog::addBarLine() { + if (_lineWidth > 0 || _currentX > 0) + incNumLines(); + + _lineXp[_numLines] = 0xFF; + incNumLines(); +} + +void TextDialog::setLineXp(int xp) { + _lineXp[_numLines] = xp; +} + +void TextDialog::draw() { + if (!_lineWidth) + --_numLines; + + // Figure out the size and position for the dialog + calculateBounds(); + + // Draw the underlying dialog + Dialog::draw(); + + // Draw the text lines + int lineYp = _position.y + 5; + for (int lineNum = 0; lineNum <= _numLines; ++lineNum) { + if (_lineXp[lineNum] == -1) { + // Draw a line across the entire dialog + _vm->_screen.hLine(_position.x + 2, + lineYp + (_font->getHeight() + 1) / 2, + _position.x + _width - 4, TEXTDIALOG_BLACK); + } else { + // Draw a text line + int xp = (_lineXp[lineNum] & 0x7F) + _position.x + 5; + int yp = lineYp; + if (_lineXp[lineNum] & 0x40) + ++yp; + + _font->writeString(&_vm->_screen, _lines[lineNum], + Common::Point(xp, yp), 1); + + if (_lineXp[lineNum] & 0x80) { + // Draw an underline under the text + int lineWidth = _font->getWidth(_lines[lineNum], 1); + _vm->_screen.hLine(xp, yp + _font->getHeight(), xp + lineWidth, + TEXTDIALOG_BLACK); + } + } + + lineYp += _font->getHeight() + 1; + } + + _vm->_screen.copyRectToScreen(getBounds()); +} + +void TextDialog::calculateBounds() { + _height = (_font->getHeight() + 1) * (_numLines + 1) + 10; + if (_position.x == -1) + _position.x = 160 - (_width / 2); + if (_position.y == -1) + _position.y = 100 - (_height / 2); + + if ((_position.x + _width) > _vm->_screen.getWidth()) + _position.x = _vm->_screen.getWidth() - (_position.x + _width); + if ((_position.y + _height) > _vm->_screen.getHeight()) + _position.y = _vm->_screen.getHeight() - (_position.y + _height); +} + +void TextDialog::drawWithInput() { + //int innerWidth = _innerWidth; + //int lineHeight = _font->getHeight() + 1; + //int xp = _position.x + 5; + + // Draw the content of the dialog + drawContent(Common::Rect(_position.x + 2, _position.y + 2, + _position.x + _width - 2, _position.y + _height - 2), 0, + TEXTDIALOG_CONTENT1, TEXTDIALOG_CONTENT2); + + error("TODO: drawWithInput"); +} + +void TextDialog::show() { + // Draw the dialog + draw(); + _vm->_events->showCursor(); + + // Wait for mouse click + do { + _vm->_events->waitForNextFrame(); + } while (!_vm->shouldQuit() && !_vm->_events->isKeyPressed() && !_vm->_events->_mouseReleased); + + // Allow the mouse release or keypress to be gobbled up + if (!_vm->shouldQuit()) { + _vm->_events->waitForNextFrame(); + _vm->_events->_pendingKeys.clear(); + } + + // Restore the background + restore(); +} + +/*------------------------------------------------------------------------*/ + +MessageDialog::MessageDialog(MADSEngine *vm, int maxChars, ...) + : TextDialog(vm, FONT_INTERFACE, Common::Point(-1, -1), maxChars) { + // Add in passed line list + va_list va; + va_start(va, maxChars); + + const char *line = va_arg(va, const char *); + while (line) { + addLine(line); + line = va_arg(va, const char *); + } + va_end(va); +} + +/*------------------------------------------------------------------------*/ + +Dialogs *Dialogs::init(MADSEngine *vm) { + if (vm->getGameID() == GType_RexNebular) + return new Nebular::DialogsNebular(vm); + + // Throw a warning for now, since the associated Dialogs class isn't implemented yet + warning("Dialogs: Unknown game"); + // HACK: Reuse the implemented Nebular dialogs for now, to avoid crashing later on + return new Nebular::DialogsNebular(vm); +} + +Dialogs::Dialogs(MADSEngine *vm) + : _vm(vm) { + _pendingDialog = DIALOG_NONE; +} + +} // End of namespace MADS diff --git a/engines/mads/dialogs.h b/engines/mads/dialogs.h new file mode 100644 index 0000000000..aad29f6551 --- /dev/null +++ b/engines/mads/dialogs.h @@ -0,0 +1,229 @@ +/* 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. + * + */ + +#ifndef MADS_DIALOGS_H +#define MADS_DIALOGS_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/font.h" +#include "mads/msurface.h" + +namespace MADS { + +class Dialog { +private: + void setDialogPalette(); +protected: + MADSEngine *_vm; + MSurface *_savedSurface; + Common::Point _position; + int _width; + int _height; + byte _dialogPalette[8 * 3]; + + int TEXTDIALOG_CONTENT1; + int TEXTDIALOG_CONTENT2; + int TEXTDIALOG_EDGE; + int TEXTDIALOG_BACKGROUND; + int TEXTDIALOG_FC; + int TEXTDIALOG_FD; + int TEXTDIALOG_FE; + int TEXTDIALOG_BLACK; +protected: + /** + * Draw the dialog + */ + virtual void draw(); + + /** + * Calculate bounds for the dialog + */ + virtual void calculateBounds(); + + /** + * Save the section of the passed surface the dialog will cover. + */ + virtual void save(); + + /** + * Restore saved dialog surface + */ + virtual void restore(); + + /** + * Draws the content of a dialog with a gravelly alternating color. + */ + void drawContent(const Common::Rect &r, int seed, byte color1, byte color2); +public: + /** + * Constructor + */ + Dialog(MADSEngine *vm); + + /** + * Destructor + */ + virtual ~Dialog(); + + /** + * Return the bounds of the dialog. + */ + Common::Rect getBounds() const { + return Common::Rect(_position.x, _position.y, + _position.x + _width, _position.y + _height); + } +}; + +#define TEXT_DIALOG_MAX_LINES 20 + +class TextDialog : protected Dialog { +private: + /** + * Append text to the currently end line. + */ + void appendLine(const Common::String &line); + + /** + * Clean up after finishing displaying the dialog + */ + void restorePalette(); +protected: + Font *_font; + int _innerWidth; + int _lineWidth; + int _currentX; + int _numLines; + int _lineSize; + int _askXp; + int _askLineNum; + Common::String _lines[TEXT_DIALOG_MAX_LINES]; + int _lineXp[TEXT_DIALOG_MAX_LINES]; + + /** + * Calculate the bounds for the dialog + */ + virtual void calculateBounds(); +public: + /** + * Constructor + * @param vm Engine reference + * @param fontName Font to use for display + * @param pos Position for window top-left + * @param maxChars Horizontal width of window in characters + */ + TextDialog(MADSEngine *vm, const Common::String &fontName, const Common::Point &pos, + int maxChars); + + /** + * Destructor + */ + virtual ~TextDialog(); + + /** + * Draw the dialog + */ + virtual void draw(); + + /** + * Draw the dialog along with any input box + */ + void drawWithInput(); + + /** + * Add a new line to the dialog + */ + void addLine(const Common::String &line, bool underline = false); + + /** + * Adds one or more lines, word wrapping the passed text + */ + void wordWrap(const Common::String &line); + + /** + * Increments the number of text lines the text dialog uses + */ + void incNumLines(); + + /** + * Adds an input area following previously added text + */ + void addInput(); + + /** + * Adds a bar line to separate sections of text + */ + void addBarLine(); + + /** + * Flags the previously added line to be underlined + */ + void underlineLine(); + + void downPixelLine(); + + /** + * Set the x position for the given line + */ + void setLineXp(int xp); + + /** + * Show the dialog, and wait until a key or mouse press. + */ + virtual void show(); +}; + +class MessageDialog : public TextDialog { +public: + MessageDialog(MADSEngine *vm, int lines, ...); + + virtual ~MessageDialog() {} +}; + +enum DialogId { + DIALOG_NONE = 0, DIALOG_GAME_MENU = 1, DIALOG_SAVE = 2, DIALOG_RESTORE = 3, + DIALOG_OPTIONS = 4, DIALOG_DIFFICULTY = 5, DIALOG_ERROR = 6 +}; + +class Dialogs { +protected: + MADSEngine *_vm; + + Dialogs(MADSEngine *vm); +public: + static Dialogs *init(MADSEngine *vm); +public: + Common::Point _defaultPosition; + DialogId _pendingDialog; + int _indexList[10]; + + virtual ~Dialogs() {} + + virtual void showDialog() = 0; + virtual void showItem(int objectId, int messageId, int speech = 0) = 0; + virtual Common::String getVocab(int vocabId) = 0; + virtual bool show(int messageId, int objectId = -1) = 0; +}; + +} // End of namespace MADS + +#endif /* MADS_DIALOGS_H */ diff --git a/engines/mads/dragonsphere/dragonsphere_scenes.cpp b/engines/mads/dragonsphere/dragonsphere_scenes.cpp new file mode 100644 index 0000000000..59d7914378 --- /dev/null +++ b/engines/mads/dragonsphere/dragonsphere_scenes.cpp @@ -0,0 +1,236 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "common/config-manager.h" +#include "mads/mads.h" +#include "mads/compression.h" +#include "mads/resources.h" +#include "mads/scene.h" +#include "mads/dragonsphere/game_dragonsphere.h" +#include "mads/dragonsphere/dragonsphere_scenes.h" + +namespace MADS { + +namespace Dragonsphere { + +SceneLogic *SceneFactory::createScene(MADSEngine *vm) { + Scene &scene = vm->_game->_scene; + + // TODO + //scene.addActiveVocab(NOUN_DROP); + + switch (scene._nextSceneId) { + // Scene group #1 (Castle, river and caves) + case 101: // king's bedroom + return new DummyScene(vm); // TODO + case 102: // queen's bedroom + return new DummyScene(vm); // TODO + case 103: // outside king's bedroom + return new DummyScene(vm); // TODO + case 104: // fireplace / bookshelf + return new DummyScene(vm); // TODO + case 105: // dining room + return new DummyScene(vm); // TODO + case 106: // throne room + return new DummyScene(vm); // TODO + case 107: // council chamber + return new DummyScene(vm); // TODO + case 108: // dungeon, cell entrance + return new DummyScene(vm); // TODO + case 109: // cell + return new DummyScene(vm); // TODO + case 110: // outside castle, merchants and well + return new DummyScene(vm); // TODO + case 111: // Dragonsphere closeup + return new DummyScene(vm); // TODO + case 112: // well descend + return new DummyScene(vm); // TODO + case 113: // bottom of well, river and trap door + return new DummyScene(vm); // TODO + case 114: // cave + return new DummyScene(vm); // TODO + case 115: // cave with passageway to west + return new DummyScene(vm); // TODO + case 116: // cave with pedestral + return new DummyScene(vm); // TODO + case 117: // river + return new DummyScene(vm); // TODO + case 118: // castle courtyard and gate + return new DummyScene(vm); // TODO + case 119: // castle stairs + return new DummyScene(vm); // TODO + case 120: // map + return new DummyScene(vm); // TODO + + // Scene group #2 (Slathan ni Patan, land of shapeshifters) + case 201: // guardhouse, entrance to Slathan ni Patan + return new DummyScene(vm); // TODO + case 203: // forest + return new DummyScene(vm); // TODO + case 204: // cave + return new DummyScene(vm); // TODO + case 205: // outside village + return new DummyScene(vm); // TODO + case 206: // village + return new DummyScene(vm); // TODO + + // Scene group #3 (Brynn-Fann, Land of faeries) + case 301: // maze entrance + return new DummyScene(vm); // TODO + case 302: // maze + return new DummyScene(vm); // TODO + case 303: // toads + return new DummyScene(vm); // TODO + + // Scene group #4 (The Desert) + case 401: // desert + return new DummyScene(vm); // TODO + case 402: // desert + return new DummyScene(vm); // TODO + case 403: // desert + return new DummyScene(vm); // TODO + case 404: // desert with dunes + return new DummyScene(vm); // TODO + case 405: // oasis + return new DummyScene(vm); // TODO + case 406: // inside tent + return new DummyScene(vm); // TODO + case 407: // gem sack closeup + return new DummyScene(vm); // TODO + case 408: // spirit plane + return new DummyScene(vm); // TODO + case 409: // spirit plane top down view, disks + return new DummyScene(vm); // TODO + case 410: // snake pit and spirit tree + return new DummyScene(vm); // TODO + case 411: // nest + return new DummyScene(vm); // TODO + case 412: // desert + return new DummyScene(vm); // TODO + case 454: // cutscene + return new DummyScene(vm); // TODO + + // Scene group #5 (The Mountain) + case 501: // base of mountain / wall + return new DummyScene(vm); // TODO + case 502: // base of mountain + return new DummyScene(vm); // TODO + case 503: // waterfall + return new DummyScene(vm); // TODO + case 504: // hermit's cave + return new DummyScene(vm); // TODO + case 505: // rock trees + return new DummyScene(vm); // TODO + case 506: // nest + return new DummyScene(vm); // TODO + case 507: // above nest + return new DummyScene(vm); // TODO + case 508: // ledge, right + return new DummyScene(vm); // TODO + case 509: // ledge, left + return new DummyScene(vm); // TODO + case 510: // nest top down view and pillars + return new DummyScene(vm); // TODO + case 511: // pillars + return new DummyScene(vm); // TODO + case 512: // nest + return new DummyScene(vm); // TODO + case 557: // cutscene + return new DummyScene(vm); // TODO + + // Scene group #6 (The Tower) + case 601: // ??? (tile count mismatch) + return new DummyScene(vm); // TODO + case 603: // eye chamber + return new DummyScene(vm); // TODO + case 604: // room of magic + return new DummyScene(vm); // TODO + case 605: // science room + return new DummyScene(vm); // TODO + case 606: // doorway + return new DummyScene(vm); // TODO + case 607: // prison + return new DummyScene(vm); // TODO + case 609: // stone pedestral chamber + return new DummyScene(vm); // TODO + case 612: // infernal machine room + return new DummyScene(vm); // TODO + case 613: // room with lava floor + return new DummyScene(vm); // TODO + case 614: // sorcerer's room + return new DummyScene(vm); // TODO + + default: + error("Invalid scene %d called", scene._nextSceneId); + } +} + +/*------------------------------------------------------------------------*/ + +DragonsphereScene::DragonsphereScene(MADSEngine *vm) : SceneLogic(vm), + _globals(static_cast<GameDragonsphere *>(vm->_game)->_globals), + _game(*static_cast<GameDragonsphere *>(vm->_game)), + _action(vm->_game->_scene._action) { +} + +Common::String DragonsphereScene::formAnimName(char sepChar, int suffixNum) { + return Resources::formatName(_scene->_currentSceneId, sepChar, suffixNum, + EXT_NONE, ""); +} + +/*------------------------------------------------------------------------*/ + +void SceneInfoDragonsphere::loadCodes(MSurface &depthSurface, int variant) { + File f(Resources::formatName(RESPREFIX_RM, _sceneId, ".DAT")); + MadsPack codesPack(&f); + Common::SeekableReadStream *stream = codesPack.getItemStream(variant + 1); + + loadCodes(depthSurface, stream); + + delete stream; + f.close(); +} + +void SceneInfoDragonsphere::loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream) { + byte *destP = depthSurface.getData(); + byte *endP = depthSurface.getBasePtr(0, depthSurface.h); + + byte runLength = stream->readByte(); + while (destP < endP && runLength > 0) { + byte runValue = stream->readByte(); + + // Write out the run length + Common::fill(destP, destP + runLength, runValue); + destP += runLength; + + // Get the next run length + runLength = stream->readByte(); + } + + if (destP < endP) + Common::fill(destP, endP, 0); +} + +} // End of namespace Dragonsphere + +} // End of namespace MADS diff --git a/engines/mads/dragonsphere/dragonsphere_scenes.h b/engines/mads/dragonsphere/dragonsphere_scenes.h new file mode 100644 index 0000000000..a6c778eca7 --- /dev/null +++ b/engines/mads/dragonsphere/dragonsphere_scenes.h @@ -0,0 +1,695 @@ +/* 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. + * + */ + +#ifndef MADS_DRAGONSPHERE_SCENES_H +#define MADS_DRAGONSPHERE_SCENES_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/scene.h" +#include "mads/dragonsphere/game_dragonsphere.h" +//#include "mads/dragonsphere/globals_dragonsphere.h" + + +namespace MADS { + +namespace Dragonsphere { + +enum Noun { + NOUN_GAME = 0x1, + NOUN_QSAVE = 0x2, + NOUN_LOOK = 0x3, + NOUN_TAKE = 0x4, + NOUN_PUSH = 0x5, + NOUN_OPEN = 0x6, + NOUN_PUT = 0x7, + NOUN_TALK_TO = 0x8, + NOUN_GIVE = 0x9, + NOUN_PULL = 0xA, + NOUN_CLOSE = 0xB, + NOUN_THROW = 0xC, + NOUN_WALK_TO = 0xD, + NOUN_NOTHING = 0xE, + NOUN_ = 0xF, + NOUN_FLOOR = 0x10, + NOUN_WALK_ACROSS = 0x11, + NOUN_RUG = 0x12, + NOUN_CARPET = 0x13, + NOUN_WALL = 0x14, + NOUN_BED = 0x15, + NOUN_PILLOW = 0x16, + NOUN_CHEST = 0x17, + NOUN_WINDOW = 0x18, + NOUN_NIGHTSTAND = 0x19, + NOUN_TAPESTRY = 0x1A, + NOUN_DRESSING_SCREEN = 0x1B, + NOUN_WALK_BEHIND = 0x1C, + NOUN_ROYAL_CREST = 0x1D, + NOUN_LOOK_AT = 0x1E, + NOUN_WASHBASIN = 0x1F, + NOUN_WASH_AT = 0x20, + NOUN_BOOK = 0x21, + NOUN_FIREPLACE = 0x22, + NOUN_FIREPLACE_SCREEN = 0x23, + NOUN_DOOR_TO_QUEENS_ROOM = 0x24, + NOUN_WALK_THROUGH = 0x25, + NOUN_HALL_TO_SOUTH = 0x26, + NOUN_WALK_INTO = 0x27, + NOUN_WALL_PLAQUE = 0x28, + NOUN_DECORATION = 0x29, + NOUN_SWORDS = 0x2A, + NOUN_WALL_SCONCE = 0x2B, + NOUN_BUST_ON_WALL = 0x2C, + NOUN_WALL_ARCH = 0x2D, + NOUN_SIGNET_RING = 0x2E, + NOUN_INVOKE = 0x2F, + NOUN_POLISH = 0x30, + NOUN_GANGBANG = 0x31, + NOUN_BIRD_FIGURINE = 0x32, + NOUN_RUB = 0x33, + NOUN_BIRDCALL = 0x34, + NOUN_USE = 0x35, + NOUN_MAKE_NOISE = 0x36, + NOUN_SHIELDSTONE = 0x37, + NOUN_SWORD = 0x38, + NOUN_ATTACK = 0x39, + NOUN_CARVE_UP = 0x3A, + NOUN_GOBLET = 0x3B, + NOUN_FILL = 0x3C, + NOUN_DRINK_FROM = 0x3D, + NOUN_BONE = 0x3E, + NOUN_GNAW = 0x3F, + NOUN_FRUIT = 0x40, + NOUN_EAT = 0x41, + NOUN_DOLL = 0x42, + NOUN_PLAY_WITH = 0x43, + NOUN_HEAL = 0x44, + NOUN_HEAL_THYSELF = 0x45, + NOUN_HEAL_SELF = 0x46, + NOUN_POLYSTONE = 0x47, + NOUN_MIMIC = 0x48, + NOUN_RED_POWERSTONE = 0x49, + NOUN_YELLOW_POWERSTONE = 0x4A, + NOUN_BLUE_POWERSTONE = 0x4B, + NOUN_KEY_CROWN = 0x4C, + NOUN_WEAR = 0x4D, + NOUN_DATES = 0x4E, + NOUN_STATUE = 0x4F, + NOUN_BOTTLE_OF_FLIES = 0x50, + NOUN_LISTEN_TO = 0x51, + NOUN_SOUL_EGG = 0x52, + NOUN_BREAK = 0x53, + NOUN_MAGIC_BELT = 0x54, + NOUN_ADJUST = 0x55, + NOUN_AMULET = 0x56, + NOUN_THRUST = 0x57, + NOUN_MUD = 0x58, + NOUN_FEEL = 0x59, + NOUN_TASTE = 0x5A, + NOUN_FEATHERS = 0x5B, + NOUN_TICKLE = 0x5C, + NOUN_TORCH = 0x5D, + NOUN_WAVE = 0x5E, + NOUN_FLASK = 0x5F, + NOUN_FLASK_FULL_OF_ACID = 0x60, + NOUN_POUR_CONTENTS = 0x61, + NOUN_POUR = 0x62, + NOUN_POUR_CONTENTS_OF = 0x63, + NOUN_DRINK = 0x64, + NOUN_ROPE = 0x65, + NOUN_TIE = 0x66, + NOUN_POWER_VACUUM_STONE = 0x67, + NOUN_TAKE_MAGIC_FROM = 0x68, + NOUN_DEAD_RAT = 0x69, + NOUN_PET = 0x6A, + NOUN_MAP = 0x6B, + NOUN_FOLD = 0x6C, + NOUN_CRYSTAL_BALL = 0x6D, + NOUN_GAZE_INTO = 0x6E, + NOUN_INVOKE_POWER_OF = 0x6F, + NOUN_BLACK_SPHERE = 0x70, + NOUN_SOPTUS_SOPORIFIC = 0x71, + NOUN_SHIFTER_RING = 0x72, + NOUN_SHIFT_SELF = 0x73, + NOUN_SHIFT_INTO_BEAR = 0x74, + NOUN_SHIFT_INTO_SEAL = 0x75, + NOUN_SHIFT_INTO_SNAKE = 0x76, + NOUN_REVERT = 0x77, + NOUN_MEDICINE_BUNDLE = 0x78, + NOUN_SHAKE = 0x79, + NOUN_PARTLY_BUILT_BUNDLE = 0x7A, + NOUN_RATSICLE = 0x7B, + NOUN_LICK = 0x7C, + NOUN_TENTACLE_PARTS = 0x7D, + NOUN_CHEW = 0x7E, + NOUN_TELEPORT_DOOR = 0x7F, + NOUN_UNROLL = 0x80, + NOUN_RARE_COIN = 0x81, + NOUN_ADMIRE = 0x82, + NOUN_CRYSTAL_FLOWER = 0x83, + NOUN_DIAMOND_DUST = 0x84, + NOUN_RUBY_RING = 0x85, + NOUN_GOLD_NUGGET = 0x86, + NOUN_MAGIC_MUSIC_BOX = 0x87, + NOUN_EMERALD = 0x88, + NOUN_PIECE_OF_PAPER = 0x89, + NOUN_SPEAK_WORDS_ON = 0x8A, + NOUN_VORTEX_STONE = 0x8B, + NOUN_RUG2 = 0x8C, + NOUN_FIREPLACE_SCREEN2 = 0x8D, + NOUN_BUST_ON_WALL2 = 0x8E, + NOUN_LOOK_AT2 = 0x8F, + NOUN_DRAGON = 0x90, + NOUN_DRAGONSPHERE = 0x91, + NOUN_TOUCH = 0x92, + NOUN_THRONE_ROOM = 0x93, + NOUN_RETURN_TO = 0x94, + NOUN_CAVE = 0x95, + NOUN_PASSAGEWAY_TO_WEST = 0x96, + NOUN_PASSAGEWAY_TO_EAST = 0x97, + NOUN_CAVE_FLOOR = 0x98, + NOUN_STONE_COLUMN = 0x99, + NOUN_ABYSS = 0x9A, + NOUN_LOOK_INTO = 0x9B, + NOUN_CASTLE = 0x9C, + NOUN_CASTLE_GATE = 0x9D, + NOUN_GROUND = 0x9E, + NOUN_BARREL = 0x9F, + NOUN_BARRELS = 0xA0, + NOUN_HAYSTACK = 0xA1, + NOUN_ROOT_THROUGH = 0xA2, + NOUN_BATTLEMENTS = 0xA3, + NOUN_GATE_TO_THRONE_ROOM = 0xA4, + NOUN_CASTLE_WALL = 0xA5, + NOUN_DOOR = 0xA6, + NOUN_WALL_SWITCH = 0xA7, + NOUN_STAIRS = 0xA8, + NOUN_WALK_DOWN = 0xA9, + NOUN_EDGE_OF_ABYSS = 0xAA, + NOUN_COURTYARD = 0xAB, + NOUN_ROCK = 0xAC, + NOUN_CAVE_CEILING = 0xAD, + NOUN_CAVE_WALL = 0xAE, + NOUN_BRAZIER = 0xAF, + NOUN_DOOR_TO_THRONE_ROOM = 0xB0, + NOUN_GO_THROUGH = 0xB1, + NOUN_DINING_TABLE = 0xB2, + NOUN_ACTIVATE = 0xB3, + NOUN_BATTLEMENT = 0xB4, + NOUN_DOOR_TO_GAURDROOM = 0xB5, + NOUN_DUNGEON_FLOOR = 0xB6, + NOUN_DUNGEON_WALLS = 0xB7, + NOUN_DUNGEON_CEILING = 0xB8, + NOUN_BEDDING = 0xB9, + NOUN_FLOOR_GRATE = 0xBA, + NOUN_MANACLES = 0xBB, + NOUN_CALENDAR = 0xBC, + NOUN_DOOR_TO_GUARDROOM = 0xBD, + NOUN_DOOR_TO_COUNCIL_ROOM = 0xBE, + NOUN_GUARD_STATION = 0xBF, + NOUN_DOOR_TO_DUNGEON_CELL = 0xC0, + NOUN_DOORWAY_TO_CELL = 0xC1, + NOUN_DUNGEON_DOOR = 0xC2, + NOUN_DUNGEON_WALL = 0xC3, + NOUN_CEILING = 0xC4, + NOUN_DOOR_TO_HALLWAY = 0xC5, + NOUN_TABLE = 0xC6, + NOUN_BOOKSHELF = 0xC7, + NOUN_TROPHY = 0xC8, + NOUN_READING_BENCH = 0xC9, + NOUN_CHAIR = 0xCA, + NOUN_LOVESEAT = 0xCB, + NOUN_WOOD_BASKET = 0xCC, + NOUN_STOOL = 0xCD, + NOUN_GUARD_STOOL = 0xCE, + NOUN_ROCKS = 0xCF, + NOUN_DIVIDING_WALL = 0xD0, + NOUN_ARCHWAY = 0xD1, + NOUN_MARKET_GROUNDS = 0xD2, + NOUN_HEDGE = 0xD3, + NOUN_SKY = 0xD4, + NOUN_PLAINS = 0xD5, + NOUN_FIELDS = 0xD6, + NOUN_GATE_TO_COURTYARD = 0xD7, + NOUN_ROAD_TO_EAST = 0xD8, + NOUN_TREES = 0xD9, + NOUN_CLOUDS = 0xDA, + NOUN_MERCHANTS_STALL = 0xDB, + NOUN_WELL = 0xDC, + NOUN_DOWN_WELL = 0xDD, + NOUN_GO = 0xDE, + NOUN_GO_DOWN = 0xDF, + NOUN_CRANK = 0xE0, + NOUN_BUCKET = 0xE1, + NOUN_JUMP_DOWN = 0xE2, + NOUN_WALLS = 0xE3, + NOUN_DOORWAY_TO_SOUTH = 0xE4, + NOUN_PEDESTAL = 0xE5, + NOUN_DOOR_TO_NORTH = 0xE6, + NOUN_PAINTING = 0xE7, + NOUN_DOCUMENT = 0xE8, + NOUN_INK_BOTTLE = 0xE9, + NOUN_QUILL_PEN = 0xEA, + NOUN_CHANDELIER = 0xEB, + NOUN_COUNCIL_TABLE = 0xEC, + NOUN_CANDLESTICK = 0xED, + NOUN_DESK = 0xEE, + NOUN_TURN = 0xEF, + NOUN_POLE = 0xF0, + NOUN_THE_SCENE = 0xF1, + NOUN_LEAVE = 0xF2, + NOUN_END_TABLE = 0xF3, + NOUN_BATTLE_AXES = 0xF4, + NOUN_DOOR_TO_KINGS_ROOM = 0xF5, + NOUN_COAT_OF_ARMS = 0xF6, + NOUN_LARGE_WINDOW = 0xF7, + NOUN_SMALL_WINDOW = 0xF8, + NOUN_DOOR_TO_MEETING_ROOM = 0xF9, + NOUN_DOOR_TO_BALLROOM = 0xFA, + NOUN_FLOWERS = 0xFB, + NOUN_SHUTTERS = 0xFC, + NOUN_BOOKCASE = 0xFD, + NOUN_DOOR_TO_COURTYARD = 0xFE, + NOUN_PLATFORM = 0xFF, + NOUN_STEP = 0x100, + NOUN_RED_CARPET = 0x101, + NOUN_KINGS_THRONE = 0x102, + NOUN_SIT_IN = 0x103, + NOUN_QUEENS_THRONE = 0x104, + NOUN_TRAPDOOR = 0x105, + NOUN_GRATE = 0x106, + NOUN_RIVER = 0x107, + NOUN_DIARIES = 0x108, + NOUN_SWIM_DOWN = 0x109, + NOUN_SCULLERY_MAID = 0x10A, + NOUN_DOORWAY_TO_DUNGEON = 0x10B, + NOUN_WARD = 0x10C, + NOUN_DARKNESS_BEAST = 0x10D, + NOUN_BEAST = 0x10E, + NOUN_PUT_MAGIC_INTO = 0x10F, + NOUN_GUARD = 0x110, + NOUN_CROWN = 0x111, + NOUN_BOOKS = 0x112, + NOUN_SECRET_DOOR = 0x113, + NOUN_WALL_PANEL = 0x114, + NOUN_DOORWAY = 0x115, + NOUN_FAERIE = 0x116, + NOUN_SOPTUS_ECLIPTUS = 0x117, + NOUN_GUARD_CAPTAIN = 0x118, + NOUN_MERCHANT = 0x119, + NOUN_SHAPECHANGER = 0x11A, + NOUN_RED_STONE = 0x11B, + NOUN_YELLOW_STONE = 0x11C, + NOUN_BLUE_STONE = 0x11D, + NOUN_FLIES = 0x11E, + NOUN_FLASK_OF_ACID = 0x11F, + NOUN_PARTIAL_BUNDLE = 0x120, + NOUN_SOPORIFIC = 0x121, + NOUN_PARCHMENT = 0x122, + NOUN_KING = 0x123, + NOUN_MACMORN = 0x124, + NOUN_MOUNTAINSIDE = 0x125, + NOUN_PATH_TO_SOUTH = 0x126, + NOUN_ROUGH_STONE = 0x127, + NOUN_CLIMB_UP = 0x128, + NOUN_LARGE_ROCK = 0x129, + NOUN_SMALL_ROCK = 0x12A, + NOUN_PATH_TO_WEST = 0x12B, + NOUN_CAVE_ENTRANCE = 0x12C, + NOUN_PALLET = 0x12D, + NOUN_BLANKET = 0x12E, + NOUN_FIREPIT = 0x12F, + NOUN_FLAT_STONE = 0x130, + NOUN_MOVE = 0x131, + NOUN_SPIRIT_BUNDLE = 0x132, + NOUN_TRAIL_LEADING_UP = 0x133, + NOUN_FOLLOW = 0x134, + NOUN_TRAIL_LEADING_DOWN = 0x135, + NOUN_NEST = 0x136, + NOUN_REACH_IN = 0x137, + NOUN_TRAIL_LEADING_WEST = 0x138, + NOUN_PATH_TO_EAST = 0x139, + NOUN_WATERFALL = 0x13A, + NOUN_PUDDLE = 0x13B, + NOUN_EDGE_OF_CLIFF = 0x13C, + NOUN_LEDGE = 0x13D, + NOUN_CLIMB_DOWN = 0x13E, + NOUN_LANDING = 0x13F, + NOUN_BOULDERS = 0x140, + NOUN_ROCK_TUMBLE = 0x141, + NOUN_ROCK_TREE = 0x142, + NOUN_PILLAR = 0x143, + NOUN_JUMP_TO = 0x144, + NOUN_CLIFF = 0x145, + NOUN_PILLARS = 0x146, + NOUN_SPECIAL_ROCK = 0x147, + NOUN_GAZE_UPON = 0x148, + NOUN_SCONCE = 0x149, + NOUN_LADDER = 0x14A, + NOUN_STAIRWAY = 0x14B, + NOUN_MECHANISM = 0x14C, + NOUN_SPEARHEADS = 0x14D, + NOUN_TRAP_DOOR = 0x14E, + NOUN_SWIM = 0x14F, + NOUN_DOWN_RIVER = 0x150, + NOUN_SWIM_UP = 0x151, + NOUN_UP_RIVER = 0x152, + NOUN_SHORE = 0x153, + NOUN_SWIM_TO = 0x154, + NOUN_SWIM_TOWARDS = 0x155, + NOUN_KING_CALLASH = 0x156, + NOUN_KINGS_THRONE2 = 0x157, + NOUN_KING2 = 0x158, + NOUN_GROTTO = 0x159, + NOUN_CLIMB_THROUGH = 0x15A, + NOUN_QUEEN_MOTHER = 0x15B, + NOUN_MACMORN2 = 0x15C, + NOUN_SMALL_LEDGE = 0x15D, + NOUN_MACMORN3 = 0x15E, + NOUN_TO_110 = 0x15F, + NOUN_TO_KITTY_HEAVEN = 0x160, + NOUN_KITTY_HEAVEN = 0x161, + NOUN_ROOM_110 = 0x162, + NOUN_LLANIE = 0x163, + NOUN_CW = 0x164, + NOUN_HERMIT = 0x165, + NOUN_TROU = 0x166, + NOUN_SHAK = 0x167, + NOUN_ROOM_501 = 0x168, + NOUN_MOON = 0x169, + NOUN_UFO = 0x16A, + NOUN_SIT_ON = 0x16B, + NOUN_STRANGER = 0x16C, + NOUN_TOWER_DOOR = 0x16D, + NOUN_DOOR_TO_EAST = 0x16E, + NOUN_DOOR_TO_WEST = 0x16F, + NOUN_EYE = 0x170, + NOUN_DOORWAY_TO_EAST = 0x171, + NOUN_DOORWAY_TO_WEST = 0x172, + NOUN_SKULL = 0x173, + NOUN_DOOR_TO_MAGIC_ROOM = 0x174, + NOUN_ANCIENT_BARREL = 0x175, + NOUN_COBWEBS = 0x176, + NOUN_SHELF = 0x177, + NOUN_MUSTY_CHART = 0x178, + NOUN_LAB_TABLE = 0x179, + NOUN_PETCOCK = 0x17A, + NOUN_NOZZLE = 0x17B, + NOUN_TUBING = 0x17C, + NOUN_BEAKER = 0x17D, + NOUN_FLAME = 0x17E, + NOUN_METAL_PLATE = 0x17F, + NOUN_SHAFT_OF_LIGHT = 0x180, + NOUN_CABINET = 0x181, + NOUN_BALANCE = 0x182, + NOUN_CAGE = 0x183, + NOUN_FREEZER = 0x184, + NOUN_CONTENTS_OF_FREEZER = 0x185, + NOUN_CAGE_WITH_RATS = 0x186, + NOUN_DOOR_TO_SOUTH = 0x187, + NOUN_TRAIL_OF_GREEN_SLIME = 0x188, + NOUN_NECK_LOCK = 0x189, + NOUN_BENCH = 0x18A, + NOUN_SKELETON = 0x18B, + NOUN_LEG_CLAMPS = 0x18C, + NOUN_LEG_LOCK = 0x18D, + NOUN_WAIST_LOCK = 0x18E, + NOUN_NER_TOM = 0x18F, + NOUN_BELT = 0x190, + NOUN_JUMP_INTO = 0x191, + NOUN_CLOSET = 0x192, + NOUN_DOOR_TO_EYE_CHAMBER = 0x193, + NOUN_DRESSER = 0x194, + NOUN_SCROLL = 0x195, + NOUN_WITCH_PARAPHERNALIA = 0x196, + NOUN_SHELVES = 0x197, + NOUN_MAGIC_TOMES = 0x198, + NOUN_MAGIC_PARAPHERNALIA = 0x199, + NOUN_BOOK_OF_MAGIC = 0x19A, + NOUN_HOURGLASS = 0x19B, + NOUN_STONE_SPHERE = 0x19C, + NOUN_SHADOW_OF_WINDOW = 0x19D, + NOUN_MUSIC_BOX = 0x19E, + NOUN_LARGE_SPIDER_WEB = 0x19F, + NOUN_INFERNAL_MACHINE = 0x1A0, + NOUN_WATER_SOURCE = 0x1A1, + NOUN_FLOW_OF_WATER = 0x1A2, + NOUN_RETORT = 0x1A3, + NOUN_DOORWAY_TO_CORRIDOR = 0x1A4, + NOUN_TELESCOPE = 0x1A5, + NOUN_STRANGE_MAP = 0x1A6, + NOUN_CIRCLE_OF_SPHERES = 0x1A7, + NOUN_STONE_BED = 0x1A8, + NOUN_DRAGON_SCULPTURE = 0x1A9, + NOUN_RAT = 0x1AA, + NOUN_RAT_CAGE = 0x1AB, + NOUN_DOWN_BUTTON = 0x1AC, + NOUN_DOOR_TO_MACHINE_ROOM = 0x1AD, + NOUN_STRANGE_PORTAL = 0x1AE, + NOUN_DOOR_FRAME = 0x1AF, + NOUN_ELEVATOR_HOLE = 0x1B0, + NOUN_UP_BUTTON = 0x1B1, + NOUN_DOORWAY_TO_DARK_ROOM = 0x1B2, + NOUN_BIG_SKULL = 0x1B3, + NOUN_ELEVATOR_PLATFORM = 0x1B4, + NOUN_BUTTON = 0x1B5, + NOUN_TOP_BUTTON = 0x1B6, + NOUN_BOTTOM_BUTTON = 0x1B7, + NOUN_TELEPORTAL = 0x1B8, + NOUN_EYE_CHAMBER_DOORWAY = 0x1B9, + NOUN_MACHINE_ROOM_DOORWAY = 0x1BA, + NOUN_GLOWING_FLOOR = 0x1BB, + NOUN_BRYNN_FANN = 0x1BC, + NOUN_GRAN_CALLAHACH = 0x1BD, + NOUN_SLATHAN_NI_PATAN = 0x1BE, + NOUN_HIGHTOWER = 0x1BF, + NOUN_SOPTUS_ECLIPTUS2 = 0x1C0, + NOUN_TOWER = 0x1C1, + NOUN_MOUNTAIN_PATH = 0x1C2, + NOUN_PATH_BEHIND_TOWER = 0x1C3, + NOUN_VINES = 0x1C4, + NOUN_SLATHAN_NI_PATAN2 = 0x1C5, + NOUN_SICK = 0x1C6, + NOUN_PATH_AROUND_TOWER = 0x1C7, + NOUN_PATH_TO_HIGHTOWER = 0x1C8, + NOUN_SPIRIT_PLANE = 0x1C9, + NOUN_SPIRIT_TREE = 0x1CA, + NOUN_WALK = 0x1CB, + NOUN_REMAINS = 0x1CC, + NOUN_DOORWAY_TO_ELEVATOR = 0x1CD, + NOUN_DRAGON_DOOR = 0x1CE, + NOUN_DRAGON_BONES = 0x1CF, + NOUN_IRON_FLOOR = 0x1D0, + NOUN_HOLE = 0x1D1, + NOUN_STONE = 0x1D2, + NOUN_HOMEMADE_BUNDLE = 0x1D3, + NOUN_LEFT = 0x1D4, + NOUN_RIGHT = 0x1D5, + NOUN_UP = 0x1D6, + NOUN_DOWN = 0x1D7, + NOUN_WEST = 0x1D8, + NOUN_DESERT_TO_WEST = 0x1D9, + NOUN_CROSS = 0x1DA, + NOUN_DESERT_TO_EAST = 0x1DB, + NOUN_DESERT_TO_SOUTH = 0x1DC, + NOUN_DESERT_TO_NORTH = 0x1DD, + NOUN_DESERT = 0x1DE, + NOUN_POWERSTONE = 0x1DF, + NOUN_BONES = 0x1E0, + NOUN_TENT = 0x1E1, + NOUN_BUSH = 0x1E2, + NOUN_SANWE = 0x1E3, + NOUN_TANGLE = 0x1E4, + NOUN_SAND = 0x1E5, + NOUN_MAGIC_GRAPES = 0x1E6, + NOUN_ROCS_NEST = 0x1E7, + NOUN_GRAPE_VINE = 0x1E8, + NOUN_STRANGE_SQUARE = 0x1E9, + NOUN_WATER_SPHERE = 0x1EA, + NOUN_EAST_END_OF_ISLAND = 0x1EB, + NOUN_ISLAND = 0x1EC, + NOUN_SECRET_MESSAGE = 0x1ED, + NOUN_FIND = 0x1EE, + NOUN_SAND_NEAR_STONES = 0x1EF, + NOUN_DESERT_SKY = 0x1F0, + NOUN_POOL = 0x1F1, + NOUN_PALM_TREE = 0x1F2, + NOUN_OASIS = 0x1F3, + NOUN_LEAN_TO = 0x1F4, + NOUN_TRADER = 0x1F5, + NOUN_SIGN = 0x1F6, + NOUN_WATER_FLOW = 0x1F7, + NOUN_FLOATING_DISK = 0x1F8, + NOUN_GNARLED_ROOT = 0x1F9, + NOUN_SNAKE_PIT = 0x1FA, + NOUN_MARKER = 0x1FB, + NOUN_SHAMAN = 0x1FC, + NOUN_GUARDHOUSE = 0x1FD, + NOUN_BONE_TREE = 0x1FE, + NOUN_EAR_ROCK = 0x1FF, + NOUN_MOUTH_ROCK = 0x200, + NOUN_NOSE_ROCK = 0x201, + NOUN_NEW_BUNDLE = 0x202, + NOUN_LIZARD = 0x203, + NOUN_ROC = 0x204, + NOUN_ROCS_NEST2 = 0x205, + NOUN_SELECT = 0x206, + NOUN_PURPLE_GEM = 0x207, + NOUN_PURPLE_STONE = 0x208, + NOUN_GREEN_STONE = 0x209, + NOUN_PATH = 0x20A, + NOUN_GUARDS = 0x20B, + NOUN_LAMP = 0x20C, + NOUN_SCIMITAR = 0x20D, + NOUN_SITTING_PILLOW = 0x20E, + NOUN_WATER_GOURD = 0x20F, + NOUN_JAR = 0x210, + NOUN_TENT_POLE = 0x211, + NOUN_EXIT = 0x212, + NOUN_PARAPHERNALIA = 0x213, + NOUN_SLATHAN_NI_PATAN3 = 0x214, + NOUN_EYE_ROCK = 0x215, + NOUN_BODY_TREE = 0x216, + NOUN_CLEARING = 0x217, + NOUN_TENTACLES = 0x218, + NOUN_SPELL_SHIELD = 0x219, + NOUN_POOL_MONSTER = 0x21A, + NOUN_SHIFTER_BOULDER = 0x21B, + NOUN_DEAD_TREE = 0x21C, + NOUN_PIT = 0x21D, + NOUN_SHIFTER_VILLAGE = 0x21E, + NOUN_SLATHAN_SKY = 0x21F, + NOUN_SHIFTER = 0x220, + NOUN_WALK_AROUND = 0x221, + NOUN_WRECKED_BRIDGE = 0x222, + NOUN_SHACK = 0x223, + NOUN_WRECKED_SHACK = 0x224, + NOUN_WISE_SHIFTER = 0x225, + NOUN_GRASS = 0x226, + NOUN_ENTRANCE_TO_MAZE = 0x227, + NOUN_TOPIARY_TOAD = 0x228, + NOUN_BOULDER = 0x229, + NOUN_MUSHROOM = 0x22A, + NOUN_SLATHAN_SKY2 = 0x22B, + NOUN_GRETA = 0x22C, + NOUN_TREE_STUMP = 0x22D, + NOUN_SANCTUARY_WOODS = 0x22E, + NOUN_TOADS = 0x22F, + NOUN_DOOFUS = 0x230, + NOUN_SHIFTING_MONSTER = 0x231, + NOUN_SPRITE = 0x232, + NOUN_MAZE = 0x233, + NOUN_TOPIARY_TOADSTOOL = 0x234, + NOUN_TOPIARY_GARGOYLE = 0x235, + NOUN_TOPIARY_DRAGON = 0x236, + NOUN_GUARDIAN = 0x237, + NOUN_BUTTERFLY_KING = 0x238, + NOUN_ROBE = 0x239, + NOUN_CEDAR_CHEST = 0x23A, + NOUN_DRAGONSPHERE2 = 0x23B, + NOUN_PATH_TO_HIGHTOWER2 = 0x23C, + NOUN_CALIPH = 0x23D +}; + +class SceneFactory { +public: + static SceneLogic *createScene(MADSEngine *vm); +}; + +/** + * Specialized base class for Dragonsphere game scenes + */ +class DragonsphereScene : public SceneLogic { +protected: + DragonsphereGlobals &_globals; + GameDragonsphere &_game; + MADSAction &_action; + + /** + * Forms an animation resource name + */ + Common::String formAnimName(char sepChar, int suffixNum); + + /** + * Plays appropriate sound for entering varous rooms + */ + void lowRoomsEntrySound(); +public: + /** + * Constructor + */ + DragonsphereScene(MADSEngine *vm); + + void sub7178C(); +}; + +class SceneInfoDragonsphere : public SceneInfo { + friend class SceneInfo; +protected: + virtual void loadCodes(MSurface &depthSurface, int variant); + + virtual void loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream); + + /** + * Constructor + */ + SceneInfoDragonsphere(MADSEngine *vm) : SceneInfo(vm) {} +}; + +// TODO: Temporary, remove once implemented properly +class Scene1xx : public DragonsphereScene { +protected: + /** + * Plays an appropriate sound when entering a scene + */ + void sceneEntrySound() {} + + /** + *Sets the AA file to use for the scene + */ + void setAAName() {} + + /** + * Updates the prefix used for getting player sprites for the scene + */ + void setPlayerSpritesPrefix() {} +public: + Scene1xx(MADSEngine *vm) : DragonsphereScene(vm) {} +}; + +// TODO: Temporary, remove once implemented properly +class DummyScene : public DragonsphereScene { +public: + DummyScene(MADSEngine *vm) : DragonsphereScene(vm) { + warning("Unimplemented scene"); + } + + virtual void setup() {} + virtual void enter() {} + virtual void actions() {} +}; + +} // End of namespace Dragonsphere + +} // End of namespace MADS + +#endif /* MADS_DRAGONSPHERE_SCENES_H */ diff --git a/engines/mads/dragonsphere/game_dragonsphere.cpp b/engines/mads/dragonsphere/game_dragonsphere.cpp new file mode 100644 index 0000000000..c6097125b1 --- /dev/null +++ b/engines/mads/dragonsphere/game_dragonsphere.cpp @@ -0,0 +1,173 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "common/config-manager.h" +#include "mads/mads.h" +#include "mads/game.h" +#include "mads/screen.h" +#include "mads/msurface.h" +#include "mads/dragonsphere/game_dragonsphere.h" +//#include "mads/nebular/dialogs_nebular.h" +//#include "mads/nebular/globals_nebular.h" +#include "mads/dragonsphere/dragonsphere_scenes.h" + +namespace MADS { + +namespace Dragonsphere { + +GameDragonsphere::GameDragonsphere(MADSEngine *vm) + : Game(vm) { + _surface = new MSurface(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT); + _storyMode = STORYMODE_NAUGHTY; +} + +ProtectionResult GameDragonsphere::checkCopyProtection() { + /* + // DEBUG: Flag copy protection failure + _globals[5] = -1; + + if (!ConfMan.getBool("copy_protection")) + return true; + + * DEBUG: Disabled for now + CopyProtectionDialog *dlg = new CopyProtectionDialog(_vm, false); + dlg->show(); + delete dlg; + */ + + // DEBUG: Return that copy protection failed + return PROTECTION_SUCCEED; +} + +void GameDragonsphere::initializeGlobals() { + //int count, count2; + //int bad; + + _globals.reset(); + //_globals[kTalkInanimateCount] = 8; + + /* Section #1 variables */ + // TODO + + /* Section #2 variables */ + // TODO + + /* Section #3 variables */ + // TODO + + /* Section #4 variables */ + // TODO + + /* Section #5 variables */ + // TODO + + /* Section #6 variables */ + // TODO + + /* Section #9 variables */ + // TODO + + _player._facing = FACING_NORTH; + _player._turnToFacing = FACING_NORTH; + + //Player::preloadSequences("RXM", 1); + //Player::preloadSequences("ROX", 1); +} + +void GameDragonsphere::setSectionHandler() { + delete _sectionHandler; + + switch (_sectionNumber) { + case 1: + _sectionHandler = new Section1Handler(_vm); + break; + case 2: + _sectionHandler = new Section2Handler(_vm); + break; + case 3: + _sectionHandler = new Section3Handler(_vm); + break; + case 4: + _sectionHandler = new Section4Handler(_vm); + break; + case 5: + _sectionHandler = new Section5Handler(_vm); + break; + case 6: + _sectionHandler = new Section6Handler(_vm); + break; + case 7: + _sectionHandler = new Section7Handler(_vm); + break; + case 8: + _sectionHandler = new Section8Handler(_vm); + break; + default: + break; + } +} + +void GameDragonsphere::checkShowDialog() { + // TODO: Copied from Nebular + if (_vm->_dialogs->_pendingDialog && _player._stepEnabled && !_globals[5]) { + _player.releasePlayerSprites(); + _vm->_dialogs->showDialog(); + _vm->_dialogs->_pendingDialog = DIALOG_NONE; + } +} + +void GameDragonsphere::doObjectAction() { + // TODO: Copied from Nebular + //Scene &scene = _scene; + MADSAction &action = _scene._action; + //Dialogs &dialogs = *_vm->_dialogs; + //int id; + + action._inProgress = false; +} + +void GameDragonsphere::unhandledAction() { + // TODO +} + +void GameDragonsphere::step() { + if (_player._visible && _player._stepEnabled && !_player._moving && + (_player._facing == _player._turnToFacing)) { + + // TODO + } + +} + +void GameDragonsphere::synchronize(Common::Serializer &s, bool phase1) { + Game::synchronize(s, phase1); + + // TODO: Copied from Nebular + if (!phase1) { + _globals.synchronize(s); + } +} + +} // End of namespace Dragonsphere + +} // End of namespace MADS diff --git a/engines/mads/dragonsphere/game_dragonsphere.h b/engines/mads/dragonsphere/game_dragonsphere.h new file mode 100644 index 0000000000..5147f75178 --- /dev/null +++ b/engines/mads/dragonsphere/game_dragonsphere.h @@ -0,0 +1,151 @@ +/* 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. + * + */ + +#ifndef MADS_GAME_DRAGONSPHERE_H +#define MADS_GAME_DRAGONSPHERE_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/globals.h" +//#include "mads/nebular/globals_nebular.h" + +namespace MADS { + +namespace Dragonsphere { + +// TODO: Adapt for Dragonsphere's difficulty setting +enum StoryMode { STORYMODE_NAUGHTY = 1, STORYMODE_NICE = 2 }; + +enum InventoryObject { + OBJ_NONE = -1, + OBJ_SIGNET_RING = 0, + OBJ_BIRD_FIGURINE = 1, + OBJ_BIRDCALL = 2, + OBJ_SHIELDSTONE = 3, + OBJ_SWORD = 4, + OBJ_GOBLET = 5, + OBJ_BONE = 6, + OBJ_FRUIT = 7, + OBJ_DOLL = 8, + OBJ_POLYSTONE = 9, + OBJ_RED_STONE = 10, + OBJ_YELLOW_STONE = 11, + OBJ_BLUE_STONE = 12, + OBJ_KEY_CROWN = 13, + OBJ_DATES = 14, + OBJ_STATUE = 15, + OBJ_FLIES = 16, + OBJ_SOUL_EGG = 17, + OBJ_MAGIC_BELT = 18, + OBJ_AMULET = 19, + OBJ_MUD = 20, + OBJ_FEATHERS = 21, + OBJ_TORCH = 22, + OBJ_FLASK = 23, + OBJ_FLASK_OF_ACID = 24, + OBJ_ROPE = 25, + OBJ_VORTEX_STONE = 26, + OBJ_DEAD_RAT = 27, + OBJ_MAP = 28, + OBJ_CRYSTAL_BALL = 29, + OBJ_BLACK_SPHERE = 30, + OBJ_SOPORIFIC = 31, + OBJ_SHIFTER_RING = 32, + OBJ_SPIRIT_BUNDLE = 33, + OBJ_PARTIAL_BUNDLE = 34, + OBJ_RATSICLE = 35, + OBJ_TENTACLE_PARTS = 36, + OBJ_TELEPORT_DOOR = 37, + OBJ_RARE_COIN = 38, + OBJ_CRYSTAL_FLOWER = 39, + OBJ_DIAMOND_DUST = 40, + OBJ_RUBY_RING = 41, + OBJ_GOLD_NUGGET = 42, + OBJ_MUSIC_BOX = 43, + OBJ_EMERALD = 44, + OBJ_PARCHMENT = 45, + OBJ_GAME = 46, + OBJ_GAME2 = 47, + OBJ_NEW_BUNDLE = 48 +}; + +// HACK: A stub for now, remove from here once it's implemented properly +class DragonsphereGlobals : public Globals { +public: + DragonsphereGlobals() { + resize(210); // Rex has 210 globals + } + virtual ~DragonsphereGlobals() {} +}; + +class GameDragonsphere : public Game { + friend class Game; +protected: + GameDragonsphere(MADSEngine *vm); + + virtual ProtectionResult checkCopyProtection(); + + virtual void initializeGlobals(); + + virtual void setSectionHandler(); + + virtual void checkShowDialog(); +public: + DragonsphereGlobals _globals; + StoryMode _storyMode; + + virtual Globals &globals() { return _globals; } + + virtual void doObjectAction(); + + virtual void unhandledAction(); + + virtual void step(); + + virtual void synchronize(Common::Serializer &s, bool phase1); +}; + + +class Section1Handler : public SectionHandler { +public: + Section1Handler(MADSEngine *vm) : SectionHandler(vm) {} + + // TODO: Properly implement handler methods + virtual void preLoadSection() {} + virtual void sectionPtr2() {} + virtual void postLoadSection() {} +}; + +// TODO: Properly implement handler classes +typedef Section1Handler Section2Handler; +typedef Section1Handler Section3Handler; +typedef Section1Handler Section4Handler; +typedef Section1Handler Section5Handler; +typedef Section1Handler Section6Handler; +typedef Section1Handler Section7Handler; +typedef Section1Handler Section8Handler; + +} // End of namespace Nebular + +} // End of namespace MADS + +#endif /* MADS_GAME_DRAGONSPHERE_H */ diff --git a/engines/mads/events.cpp b/engines/mads/events.cpp new file mode 100644 index 0000000000..c3e6d5c122 --- /dev/null +++ b/engines/mads/events.cpp @@ -0,0 +1,256 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "graphics/cursorman.h" +#include "common/events.h" +#include "engines/util.h" +#include "mads/mads.h" +#include "mads/events.h" +#include "mads/scene.h" + +namespace MADS { + +EventsManager::EventsManager(MADSEngine *vm) { + _vm = vm; + _cursorSprites = nullptr; + _cursorId = CURSOR_NONE; + _newCursorId = CURSOR_NONE; + _frameCounter = 10; + _priorFrameTime = 0; + _mouseClicked = false; + _mouseReleased = false; + _mouseButtons = 0; + _mouseStatus = 0; + _vD2 = 0; + _mouseStatusCopy = 0; + _mouseMoved = false; + _vD8 = 0; + _rightMousePressed = false; +} + +EventsManager::~EventsManager() { + freeCursors(); +} + +void EventsManager::loadCursors(const Common::String &spritesName) { + delete _cursorSprites; + _cursorSprites = new SpriteAsset(_vm, spritesName, 0x4000); +} + +void EventsManager::setCursor(CursorType cursorId) { + _cursorId = cursorId; + changeCursor(); +} + +void EventsManager::setCursor2(CursorType cursorId) { + _cursorId = cursorId; + _newCursorId = cursorId; + changeCursor(); +} + +void EventsManager::showCursor() { + CursorMan.showMouse(true); +} + +void EventsManager::hideCursor() { + CursorMan.showMouse(false); +} + +bool EventsManager::isCursorVisible() { + return CursorMan.isVisible(); +} + +void EventsManager::waitCursor() { + CursorType cursorId = (CursorType)MIN(_cursorSprites->getCount(), (int)CURSOR_WAIT); + _newCursorId = cursorId; + if (_cursorId != _newCursorId) { + changeCursor(); + _cursorId = _newCursorId; + } +} + +void EventsManager::changeCursor() { + if (_cursorSprites) { + MSprite *cursor = _cursorSprites->getFrame(_cursorId - 1); + assert(cursor->w == cursor->h); + byte transIndex = cursor->getTransparencyIndex(); + + // Check for hotspot indication pixels along the right-hand and bottom + // row. Put together, these give the cursor's hotspot x,y + int hotspotX = 0, hotspotY = 0; + byte *cursorData = cursor->getData(); + for (int idx = 0; idx < cursor->w; ++idx) { + if (cursorData[(cursor->h - 1) * cursor->w + idx] != transIndex) + hotspotX = idx; + + if (cursorData[(idx + 1) * cursor->w - 1] != transIndex) + hotspotY = idx; + } + + // Reduce the cursor data to remove the last column from each row, since + // the cursor routines don't have a pitch option + byte *destCursor = new byte[(cursor->w - 1) * (cursor->h - 1)]; + byte *srcP = cursorData; + byte *destP = destCursor; + + for (int idx = 0; idx < (cursor->h - 1); ++idx) { + Common::copy(srcP, srcP + cursor->w - 1, destP); + srcP += cursor->w; + destP += cursor->w - 1; + } + + // Set the raw cursor data to use + CursorMan.replaceCursor(destCursor, cursor->w - 1, cursor->h - 1, + hotspotX, hotspotY, transIndex); + showCursor(); + delete[] destCursor; + } +} + +void EventsManager::freeCursors() { + delete _cursorSprites; + _cursorSprites = nullptr; +} + +void EventsManager::pollEvents() { + checkForNextFrameCounter(); + _mouseMoved = false; + + Common::Event event; + while (g_system->getEventManager()->pollEvent(event)) { + // Handle keypress + switch (event.type) { + case Common::EVENT_QUIT: + case Common::EVENT_RTL: + return; + + case Common::EVENT_KEYDOWN: + // Check for debugger + if (event.kbd.keycode == Common::KEYCODE_d && (event.kbd.flags & Common::KBD_CTRL)) { + // Attach to the debugger + _vm->_debugger->attach(); + _vm->_debugger->onFrame(); + } else { + _pendingKeys.push(event); + } + return; + case Common::EVENT_KEYUP: + return; + case Common::EVENT_LBUTTONDOWN: + case Common::EVENT_RBUTTONDOWN: + _mouseClicked = true; + _mouseButtons = 1; + _mouseMoved = true; + if (event.type == Common::EVENT_RBUTTONDOWN) { + _rightMousePressed = true; + _mouseStatus |= 2; + } else { + _mouseStatus |= 1; + } + return; + case Common::EVENT_LBUTTONUP: + case Common::EVENT_RBUTTONUP: + _mouseClicked = false; + _mouseReleased = true; + _mouseMoved = true; + _rightMousePressed = false; + if (event.type == Common::EVENT_RBUTTONUP) { + _mouseStatus &= ~2; + } else { + _mouseStatus &= ~1; + } + return; + case Common::EVENT_MOUSEMOVE: + _mousePos = event.mouse; + _currentPos = event.mouse; + _mouseMoved = true; + break; + default: + break; + } + } +} + +void EventsManager::checkForNextFrameCounter() { + // Check for next game frame + uint32 milli = g_system->getMillis(); + if ((milli - _priorFrameTime) >= GAME_FRAME_TIME) { + ++_frameCounter; + _priorFrameTime = milli; + + // Do any palette cycling + _vm->_game->_scene.animatePalette(); + + // Give time to the debugger + _vm->_debugger->onFrame(); + + // Display the frame + _vm->_screen.updateScreen(); + + // Signal the ScummVM debugger + _vm->_debugger->onFrame(); + } +} + +void EventsManager::delay(int cycles) { + uint32 totalMilli = cycles * 1000 / GAME_FRAME_RATE; + uint32 delayEnd = g_system->getMillis() + totalMilli; + + while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd) { + g_system->delayMillis(10); + + pollEvents(); + } +} + +void EventsManager::waitForNextFrame() { + _mouseClicked = false; + _mouseReleased = false; + _mouseButtons = 0; + + bool mouseClicked = false; + bool mouseReleased = false; + int mouseButtons = 0; + + uint32 frameCtr = getFrameCounter(); + while (!_vm->shouldQuit() && frameCtr == _frameCounter) { + delay(1); + + mouseClicked |= _mouseClicked; + mouseReleased |= _mouseReleased; + mouseButtons |= _mouseButtons; + } + + _mouseClicked = mouseClicked; + _mouseReleased = mouseReleased; + _mouseButtons = mouseButtons; + _mouseMoved |= _mouseClicked || _mouseReleased; +} + +void EventsManager::initVars() { + _mousePos = Common::Point(-1, -1); + _mouseStatusCopy = _mouseStatus; + _vD2 = _vD8 = 0; +} + +} // End of namespace MADS diff --git a/engines/mads/events.h b/engines/mads/events.h new file mode 100644 index 0000000000..3d7504c0bd --- /dev/null +++ b/engines/mads/events.h @@ -0,0 +1,164 @@ +/* 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. + * + */ + +#ifndef MADS_EVENTS_H +#define MADS_EVENTS_H + +#include "common/scummsys.h" +#include "common/events.h" +#include "common/stack.h" +#include "mads/assets.h" +#include "mads/sprites.h" + +namespace MADS { + +enum CursorType { CURSOR_NONE = 0, CURSOR_ARROW = 1, CURSOR_WAIT = 2, CURSOR_GO_DOWN = 3, + CURSOR_GO_UP = 4, CURSOR_GO_LEFT = 5, CURSOR_GO_RIGHT = 6 }; + +#define GAME_FRAME_RATE 50 +#define GAME_FRAME_TIME (1000 / GAME_FRAME_RATE) + +class MADSEngine; + +class EventsManager { +private: + MADSEngine *_vm; + uint32 _frameCounter; + uint32 _priorFrameTime; + Common::Point _mousePos; + Common::Point _currentPos; + + /** + * Updates the cursor image when the current cursor changes + */ + void changeCursor(); + + /** + * Checks for whether the next game frame number has been reached. + */ + void checkForNextFrameCounter(); +public: + SpriteAsset *_cursorSprites; + CursorType _cursorId; + CursorType _newCursorId; + bool _mouseClicked; + bool _mouseReleased; + byte _mouseButtons; + bool _rightMousePressed; + int _mouseStatus; + int _vD2; + int _mouseStatusCopy; + bool _mouseMoved; + int _vD8; + Common::Stack<Common::Event> _pendingKeys; +public: + /** + * Constructor + */ + EventsManager(MADSEngine *vm); + + /** + * Destructor + */ + ~EventsManager(); + + /** + * Loads the sprite set containing the cursors + */ + void loadCursors(const Common::String &spritesName); + + /** + * Sets the cursor + */ + void setCursor(CursorType cursorId); + + /** + * Sets the cursor + */ + void setCursor2(CursorType cursorId); + + /** + * Show the mouse cursor + */ + void showCursor(); + + /** + * Hide the mouse cursor + */ + void hideCursor(); + + /** + * Returns if the mouse cursor is visible + */ + bool isCursorVisible(); + + /** + * Shows the wait cursor + */ + void waitCursor(); + + /** + * Free currently loaded cursors + */ + void freeCursors(); + + /** + * Poll any pending events + */ + void pollEvents(); + + /** + * Return the current mouse position + */ + Common::Point mousePos() const { return _mousePos; } + + /** + * Return the current mouse position + */ + Common::Point currentPos() const { return _currentPos; } + + /** + * Delay for a given number of frames + */ + void delay(int amount); + + /** + * Wait for the next frame + */ + void waitForNextFrame(); + + /** + * Gets the current frame counter + */ + uint32 getFrameCounter() const { return _frameCounter; } + + void initVars(); + + /** + * Returns true if there's any pending keys to be processed + */ + bool isKeyPressed() const { return !_pendingKeys.empty(); } +}; + +} // End of namespace MADS + +#endif /* MADS_EVENTS_H */ diff --git a/engines/mads/font.cpp b/engines/mads/font.cpp new file mode 100644 index 0000000000..6af1346f01 --- /dev/null +++ b/engines/mads/font.cpp @@ -0,0 +1,252 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 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. + * + */ + +#include "common/scummsys.h" +#include "mads/mads.h" +#include "mads/compression.h" +#include "mads/font.h" +#include "mads/msurface.h" + +namespace MADS { + +MADSEngine *Font::_vm; + +Common::HashMap<Common::String, Font *> *Font::_fonts; + +uint8 Font::_fontColors[4]; + +void Font::init(MADSEngine *vm) { + _vm = vm; + _fontColors[0] = 0xFF; + _fontColors[1] = 0xF; + _fontColors[2] = 7; + _fontColors[3] = 8; + + _fonts = new Common::HashMap<Common::String, Font *>(); +} + +void Font::deinit() { + Common::HashMap<Common::String, Font *>::iterator i; + for (i = _fonts->begin(); i != _fonts->end(); ++i) + delete (*i)._value; + + delete _fonts; +} + +Font *Font::getFont(const Common::String &fontName) { + if (_fonts->contains(fontName)) { + return _fonts->getVal(fontName); + } else { + Font *font = new Font(fontName); + _fonts->setVal(fontName, font); + return font; + } +} + +Font::Font() { + _charWidths = nullptr; + _charOffs = nullptr; + _charData = nullptr; + setFont(FONT_INTERFACE); +} + +Font::Font(const Common::String &filename) { + _charWidths = nullptr; + _charOffs = nullptr; + _charData = nullptr; + setFont(filename); +} + +Font::~Font() { + delete[] _charWidths; + delete[] _charOffs; + delete[] _charData; +} + +void Font::setFont(const Common::String &filename) { + if (!_filename.empty() && (filename == _filename)) + // Already using specified font, so don't bother reloading + return; + + _filename = filename; + + MadsPack fontData(filename, _vm); + Common::SeekableReadStream *fontFile = fontData.getItemStream(0); + + _maxHeight = fontFile->readByte(); + _maxWidth = fontFile->readByte(); + + _charWidths = new uint8[128]; + // Char data is shifted by 1 + _charWidths[0] = 0; + fontFile->read(_charWidths + 1, 127); + fontFile->readByte(); // remainder + + _charOffs = new uint16[128]; + + uint startOffs = 2 + 128 + 256; + uint fontSize = fontFile->size() - startOffs; + + // Char data is shifted by 1 + _charOffs[0] = 0; + for (int i = 1; i < 128; i++) + _charOffs[i] = fontFile->readUint16LE() - startOffs; + fontFile->readUint16LE(); // remainder + + _charData = new uint8[fontSize]; + fontFile->read(_charData, fontSize); + + delete fontFile; +} + +void Font::setColors(uint8 v1, uint8 v2, uint8 v3, uint8 v4) { + _fontColors[0] = v1; + _fontColors[1] = v2; + _fontColors[2] = v3; + _fontColors[3] = v4; +} + +void Font::setColorMode(SelectionMode mode) { + switch (mode) { + case SELMODE_UNSELECTED: + setColors(0xFF, 4, 4, 0); + break; + case SELMODE_HIGHLIGHTED: + setColors(0xFF, 5, 5, 0); + break; + case SELMODE_SELECTED: + setColors(0xFF, 6, 6, 0); + break; + default: + break; + } +} + +int Font::writeString(MSurface *surface, const Common::String &msg, const Common::Point &pt, + int spaceWidth, int width) { + int xEnd; + if (width > 0) + xEnd = MIN((int)surface->w, pt.x + width); + else + xEnd = surface->w; + + int x = pt.x; + int y = pt.y; + + int skipY = 0; + if (y < 0) { + skipY = -y; + y = 0; + } + + int height = MAX(0, _maxHeight - skipY); + if (height == 0) + return x; + + int bottom = y + height - 1; + if (bottom > surface->getHeight() - 1) { + height -= MIN(height, bottom - (surface->getHeight() - 1)); + } + + if (height <= 0) + return x; + + byte *destPtr = surface->getBasePtr(x, y); + uint8 *oldDestPtr = destPtr; + + int xPos = x; + + const char *text = msg.c_str(); + while (*text) { + char theChar = (*text++) & 0x7F; + int charWidth = _charWidths[(byte)theChar]; + + if (charWidth > 0) { + + if (xPos + charWidth > xEnd) + return xPos; + + uint8 *charData = &_charData[_charOffs[(byte)theChar]]; + int bpp = getBpp(charWidth); + + if (skipY != 0) + charData += bpp * skipY; + + for (int i = 0; i < height; i++) { + for (int j = 0; j < bpp; j++) { + if (*charData & 0xc0) + *destPtr = _fontColors[(*charData & 0xc0) >> 6]; + destPtr++; + if (*charData & 0x30) + *destPtr = _fontColors[(*charData & 0x30) >> 4]; + destPtr++; + if (*charData & 0x0C) + *destPtr = _fontColors[(*charData & 0x0C) >> 2]; + destPtr++; + if (*charData & 0x03) + *destPtr = _fontColors[*charData & 0x03]; + destPtr++; + charData++; + } + + destPtr += surface->getWidth() - bpp * 4; + + } + + destPtr = oldDestPtr + charWidth + spaceWidth; + oldDestPtr = destPtr; + + } + + xPos += charWidth + spaceWidth; + + } + + return xPos; + +} + +int Font::getWidth(const Common::String &msg, int spaceWidth) { + int width = 0; + const char *text = msg.c_str(); + + if (msg.size() > 0) { + while (*text) + width += _charWidths[*text++ & 0x7F] + spaceWidth; + width -= spaceWidth; + } + + return width; +} + +int Font::getBpp(int charWidth) { + if (charWidth > 12) + return 4; + else if (charWidth > 8) + return 3; + else if (charWidth > 4) + return 2; + else + return 1; +} + +} // End of namespace MADS diff --git a/engines/mads/font.h b/engines/mads/font.h new file mode 100644 index 0000000000..47df647637 --- /dev/null +++ b/engines/mads/font.h @@ -0,0 +1,95 @@ +/* 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. + * + */ + +#ifndef MADS_FONT_H +#define MADS_FONT_H + +#include "common/scummsys.h" +#include "common/hashmap.h" +#include "common/endian.h" +#include "common/util.h" +#include "mads/msurface.h" + +namespace MADS { + +#define FONT_CONVERSATION "*FONTCONV.FF" +#define FONT_INTERFACE "*FONTINTR.FF" +#define FONT_MAIN "*FONTMAIN.FF" +#define FONT_MENU "*FONTMENU.FF" // Not in Rex (uses bitmap files for menu strings) +#define FONT_MISC "*FONTMISC.FF" +#define FONT_TELE "*FONTTELE.FF" // Not in Phantom +#define FONT_PHAN "*FONTPHAN.FF" // Phantom only + +enum SelectionMode { + SELMODE_UNSELECTED = 0, SELMODE_HIGHLIGHTED = 1, SELMODE_SELECTED = 2 +}; + +class MADSEngine; + +class Font { +private: + static uint8 _fontColors[4]; + static MADSEngine *_vm; + static Common::HashMap<Common::String, Font *> *_fonts; +public: + /** + * Initialize the font system + */ + static void init(MADSEngine *vm); + + /** + * Free up the resources used by the font + */ + static void deinit(); + + /** + * Returns a new Font instance using the specified font name + */ + static Font *getFont(const Common::String &fontName); +private: + uint8 _maxWidth, _maxHeight; + uint8 *_charWidths; + uint16 *_charOffs; + uint8 *_charData; + Common::String _filename; + + int getBpp(int charWidth); + + void setFont(const Common::String &filename); +public: + Font(); + Font(const Common::String &filename); + virtual ~Font(); + + void setColors(uint8 v1, uint8 v2, uint8 v3, uint8 v4); + void setColorMode(SelectionMode mode); + + int maxWidth() const { return _maxWidth; } + int getWidth(const Common::String &msg, int spaceWidth = -1); + int getHeight() const { return _maxHeight; } + int writeString(MSurface *surface, const Common::String &msg, const Common::Point &pt, + int spaceWidth = 0, int width = 0); +}; + +} // End of namespace MADS + +#endif /* MADS_FONT_H */ diff --git a/engines/mads/game.cpp b/engines/mads/game.cpp new file mode 100644 index 0000000000..05dd932482 --- /dev/null +++ b/engines/mads/game.cpp @@ -0,0 +1,608 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "common/config-manager.h" +#include "common/memstream.h" +#include "common/serializer.h" +#include "graphics/palette.h" +#include "graphics/scaler.h" +#include "graphics/thumbnail.h" +#include "mads/mads.h" +#include "mads/compression.h" +#include "mads/game.h" +#include "mads/game_data.h" +#include "mads/events.h" +#include "mads/screen.h" +#include "mads/msurface.h" +#include "mads/resources.h" +#include "mads/dragonsphere/game_dragonsphere.h" +#include "mads/nebular/game_nebular.h" +#include "mads/phantom/game_phantom.h" + +namespace MADS { + +Game *Game::init(MADSEngine *vm) { + switch (vm->getGameID()) { + case GType_RexNebular: + return new Nebular::GameNebular(vm); + case GType_Dragonsphere: + return new Dragonsphere::GameDragonsphere(vm); + case GType_Phantom: + return new Phantom::GamePhantom(vm); + default: + error("Game: Unknown game"); + } + + return nullptr; +} + +Game::Game(MADSEngine *vm) + : _vm(vm), _surface(nullptr), _objects(vm), _scene(vm), + _screenObjects(vm), _player(vm) { + _sectionNumber = _priorSectionNumber = 0; + _loadGameSlot = -1; + _lastSave = -1; + _saveFile = nullptr; + _statusFlag = 0; + _sectionHandler = nullptr; + _sectionNumber = 1; + _priorSectionNumber = 0; + _currentSectionNumber = -1; + _kernelMode = KERNEL_GAME_LOAD; + _quoteEmergency = false; + _vocabEmergency = false; + _aaName = "*I0.AA"; + _priorFrameTimer = 0; + _anyEmergency = false; + _triggerMode = SEQUENCE_TRIGGER_PARSER; + _triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _trigger = 0; + _winStatus = 0; + _widepipeCtr = 0; + _fx = kTransitionNone; + + // Load the inventory object list + _objects.load(); + if (_objects._inventoryList.size() > 0) + // At least one item in default inventory, so select first item for display + _scene._userInterface._selectedInvIndex = 0; + + // Load the quotes + loadQuotes(); +} + +Game::~Game() { + delete _saveFile; + delete _surface; + delete _sectionHandler; +} + +void Game::run() { + initializeGlobals(); + + // If requested, load a savegame instead of showing the intro + if (ConfMan.hasKey("save_slot")) { + int saveSlot = ConfMan.getInt("save_slot"); + if (saveSlot >= 0 && saveSlot <= 999) + _loadGameSlot = saveSlot; + } + + _statusFlag = true; + int protectionResult = -1; + + if (_loadGameSlot == -1) { + protectionResult = checkCopyProtection(); + switch (protectionResult) { + case PROTECTION_FAIL: + // Copy protection failed + _scene._nextSceneId = 804; + break; + case PROTECTION_ESCAPE: + // User escaped out of copy protection dialog + _vm->quitGame(); + break; + default: + // Copy protection check succeeded + _scene._nextSceneId = 101; + _scene._priorSceneId = -1; + break; + } + } + + // Get the initial starting time for the first scene + _scene._frameStartTime = _vm->_events->getFrameCounter(); + + if (_saveFile == nullptr && protectionResult != -1 && protectionResult != -2) { + initSection(_sectionNumber); + _statusFlag = true; + + _vm->_dialogs->_pendingDialog = DIALOG_DIFFICULTY; + _vm->_dialogs->showDialog(); + _vm->_dialogs->_pendingDialog = DIALOG_NONE; + + _priorSectionNumber = 0; + _priorSectionNumber = -1; + _scene._priorSceneId = 0; + _scene._currentSceneId = -1; + } + + if (protectionResult != 1 && protectionResult != 2) { + initializeGlobals(); + } + + if (_statusFlag) + gameLoop(); +} + +void Game::splitQuote(const Common::String &source, Common::String &line1, Common::String &line2) { + // Make the first line up the end of the word at the half-way point + const char *strP = source.c_str() + source.size() / 2; + while (*strP != ' ') ++strP; + + line1 = Common::String(source.c_str(), strP); + + // The rest of the string goes in the second line + while (*strP == ' ') ++strP; + line2 = Common::String(strP); +} + +void Game::gameLoop() { + while (!_vm->shouldQuit() && _statusFlag) { + if (_loadGameSlot != -1) { + loadGame(_loadGameSlot); + _loadGameSlot = -1; + } + + setSectionHandler(); + _sectionHandler->preLoadSection(); + initSection(_sectionNumber); + _vm->_sound->init(_sectionNumber); + _sectionHandler->postLoadSection(); + + _scene._spriteSlots.reset(); + + if (_sectionNumber == _currentSectionNumber) + sectionLoop(); + + _player.releasePlayerSprites(); + assert(_scene._sprites._assetCount == 0); + + _vm->_palette->unlock(); + _vm->_events->waitCursor(); + _vm->_events->freeCursors(); + _vm->_sound->closeDriver(); + } + + _vm->_palette->close(); +} + +void Game::sectionLoop() { + while (!_vm->shouldQuit() && _statusFlag && (_sectionNumber == _currentSectionNumber)) { + _kernelMode = KERNEL_ROOM_PRELOAD; + _player._spritesChanged = true; + _quoteEmergency = false; + _vocabEmergency = false; + _vm->_events->waitCursor(); + + _scene.clearVocab(); + _scene._dynamicHotspots.clear(); + _scene.loadSceneLogic(); + + _player._walkAnywhere = false; + _player._stepEnabled = true; + _player._visible = true; + _vm->_dialogs->_defaultPosition = Common::Point(-1, -1); + _visitedScenes.add(_scene._nextSceneId); + + // Reset the user interface + _screenObjects._forceRescan = true; + _screenObjects._inputMode = kInputBuildingSentences; + _scene._userInterface._scrollbarActive = SCROLLBAR_NONE; + + _player._loadsFirst = true; + + _scene._sceneLogic->setup(); + if (_player._spritesChanged || _player._loadsFirst) { + if (_player._spritesLoaded) + _player.releasePlayerSprites(); + _vm->_palette->resetGamePalette(18, 10); + _scene._spriteSlots.reset(); + } else { + _vm->_palette->initPalette(); + } + + // Set up scene palette usage + _scene._scenePaletteUsage.clear(); + _scene._scenePaletteUsage.push_back(PaletteUsage::UsageEntry(0xF0)); + _scene._scenePaletteUsage.push_back(PaletteUsage::UsageEntry(0xF1)); + _scene._scenePaletteUsage.push_back(PaletteUsage::UsageEntry(0xF2)); + _vm->_palette->_paletteUsage.load(&_scene._scenePaletteUsage); + + if (!_player._spritesLoaded && _player._loadsFirst) { + if (_player.loadSprites("")) + _vm->quitGame(); + _player._loadedFirst = true; + } + + _scene.loadScene(_scene._nextSceneId, _aaName, 0); + _vm->_sound->pauseNewCommands(); + + if (!_player._spritesLoaded) { + if (_player.loadSprites("")) + _vm->quitGame(); + _player._loadedFirst = false; + } + + _vm->_events->initVars(); + _scene._userInterface._highlightedCommandIndex = -1; + _scene._userInterface._highlightedInvIndex = -1; + _scene._userInterface._highlightedItemVocabIndex = -1; + + _scene._action.clear(); + _player.setFinalFacing(); + _player._facing = _player._turnToFacing; + _player.cancelCommand(); + _kernelMode = KERNEL_ROOM_INIT; + + switch (_vm->_screenFade) { + case SCREEN_FADE_SMOOTH: + _fx = kTransitionFadeOutIn; + break; + case SCREEN_FADE_FAST: + _fx = kCenterVertTransition; + break; + default: + _fx = kTransitionNone; + break; + } + + _trigger = 0; + _priorFrameTimer = _scene._frameStartTime; + + // Call the scene logic for entering the given scene + _triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene._sceneLogic->enter(); + + // If in the middle of restoring a game, handle the rest of the loading + if (_saveFile != nullptr) { + Common::Serializer s(_saveFile, nullptr); + synchronize(s, false); + delete _saveFile; + _saveFile = nullptr; + } + + // Set player data + _player._targetPos = _player._playerPos; + _player._turnToFacing = _player._facing; + _player._targetFacing = _player._facing; + _player.selectSeries(); + _player.updateFrame(); + + _player._beenVisible = _player._visible; + _player._special = _scene.getDepthHighBits(_player._playerPos); + _player._priorTimer = _scene._frameStartTime - _player._ticksAmount; + _player.idle(); + + if (_scene._userInterface._selectedInvIndex >= 0) { + _scene._userInterface.loadInventoryAnim( + _objects._inventoryList[_scene._userInterface._selectedInvIndex]); + } else { + _scene._userInterface.noInventoryAnim(); + } + + _kernelMode = KERNEL_ACTIVE_CODE; + _scene._roomChanged = false; + + if ((_quoteEmergency || _vocabEmergency) && !_anyEmergency) { + _scene._currentSceneId = _scene._priorSceneId; + _anyEmergency = true; + } else { + _anyEmergency = false; + _scene.loop(); + } + + _vm->_events->waitCursor(); + _kernelMode = KERNEL_ROOM_PRELOAD; + + delete _scene._activeAnimation; + _scene._activeAnimation = nullptr; + + _scene._reloadSceneFlag = false; + + _scene._userInterface.noInventoryAnim(); + _scene.removeSprites(); + + if (!_player._loadedFirst) { + _player._spritesLoaded = false; + _player._spritesChanged = true; + } + + // Clear the scene + _scene.freeCurrentScene(); + _sectionNumber = _scene._nextSceneId / 100; + + // Check whether to show a dialog + checkShowDialog(); + } +} + +void Game::initSection(int sectionNumber) { + _priorSectionNumber = _currentSectionNumber; + _currentSectionNumber = sectionNumber; + + _vm->_palette->resetGamePalette(18, 10); + _vm->_palette->setLowRange(); + + if (_scene._layer == LAYER_GUI) + _vm->_palette->setPalette(_vm->_palette->_mainPalette, 0, 4); + + _vm->_events->loadCursors("*CURSOR.SS"); + + assert(_vm->_events->_cursorSprites); + _vm->_events->setCursor2((_vm->_events->_cursorSprites->getCount() <= 1) ? + CURSOR_ARROW : CURSOR_WAIT); +} + +void Game::loadQuotes() { + File f("*QUOTES.DAT"); + + Common::String msg; + while (true) { + uint8 b = f.readByte(); + + msg += b; + if (f.eos() || b == '\0') { + // end of string, add it to the strings list + _quotes.push_back(msg); + msg = ""; + } + + if (f.eos()) break; + } + + f.close(); +} + +Common::StringArray Game::getMessage(uint32 id) { + File f("*MESSAGES.DAT"); + int count = f.readUint16LE(); + + for (int idx = 0; idx < count; ++idx) { + uint32 itemId = f.readUint32LE(); + uint32 offset = f.readUint32LE(); + uint16 size = f.readUint16LE(); + + if (itemId == id) { + // Get the source buffer size + uint16 sizeIn; + if (idx == (count - 1)) { + sizeIn = f.size() - offset; + } else { + f.skip(4); + uint32 nextOffset = f.readUint32LE(); + sizeIn = nextOffset - offset; + } + + // Get the compressed data + f.seek(offset); + byte *bufferIn = new byte[sizeIn]; + f.read(bufferIn, sizeIn); + + // Decompress it + char *bufferOut = new char[size]; + FabDecompressor fab; + fab.decompress(bufferIn, sizeIn, (byte *)bufferOut, size); + + // Form the output string list + Common::StringArray result; + const char *p = bufferOut; + while (p < (bufferOut + size)) { + result.push_back(p); + p += strlen(p) + 1; + } + + delete[] bufferIn; + delete[] bufferOut; + return result; + } + } + + error("Invalid message Id specified"); +} + +static const char *const DEBUG_STRING = "WIDEPIPE"; + +void Game::handleKeypress(const Common::Event &event) { + if (event.kbd.flags & Common::KBD_CTRL) { + if (_widepipeCtr == 8) { + // Implement original game cheating keys here someday + } else { + if (event.kbd.keycode == (Common::KEYCODE_a + + (DEBUG_STRING[_widepipeCtr] - 'a'))) { + if (++_widepipeCtr == 8) { + MessageDialog *dlg = new MessageDialog(_vm, 2, + "CHEATING ENABLED", "(for your convenience)."); + dlg->show(); + delete dlg; + } + } + } + } + + switch (event.kbd.keycode) { + case Common::KEYCODE_F1: + _vm->_dialogs->_pendingDialog = DIALOG_GAME_MENU; + break; + case Common::KEYCODE_F5: + _vm->_dialogs->_pendingDialog = DIALOG_SAVE; + break; + case Common::KEYCODE_F7: + _vm->_dialogs->_pendingDialog = DIALOG_RESTORE; + break; + default: + break; + } + + warning("TODO: handleKeypress - %d", (int)event.kbd.keycode); +} + +void Game::synchronize(Common::Serializer &s, bool phase1) { + if (phase1) { + s.syncAsSint16LE(_fx); + s.syncAsSint16LE(_trigger); + s.syncAsUint16LE(_triggerSetupMode); + s.syncAsUint16LE(_triggerMode); + s.syncString(_aaName); + s.syncAsSint16LE(_lastSave); + + _scene.synchronize(s); + _objects.synchronize(s); + _visitedScenes.synchronize(s); + _player.synchronize(s); + _screenObjects.synchronize(s); + } else { + // Load scene specific data for the loaded scene + _scene._sceneLogic->synchronize(s); + } +} + +void Game::loadGame(int slotNumber) { + _saveFile = g_system->getSavefileManager()->openForLoading( + _vm->generateSaveName(slotNumber)); + + Common::Serializer s(_saveFile, nullptr); + + // Load the savaegame header + MADSSavegameHeader header; + if (!readSavegameHeader(_saveFile, header)) + error("Invalid savegame"); + + if (header._thumbnail) { + header._thumbnail->free(); + delete header._thumbnail; + } + + // Load most of the savegame data with the exception of scene specific info + synchronize(s, true); + + // Set up section/scene and other initial states for post-load + _currentSectionNumber = -2; + _scene._currentSceneId = -2; + _sectionNumber = _scene._nextSceneId / 100; + _scene._frameStartTime = _vm->_events->getFrameCounter(); + _vm->_screen._shakeCountdown = -1; + + // Default the selected inventory item to the first one, if the player has any + _scene._userInterface._selectedInvIndex = _objects._inventoryList.size() > 0 ? 0 : -1; + + // Set player sprites sets flags + _player._spritesLoaded = false; + _player._spritesChanged = true; +} + +void Game::saveGame(int slotNumber, const Common::String &saveName) { + Common::OutSaveFile *out = g_system->getSavefileManager()->openForSaving( + _vm->generateSaveName(slotNumber)); + + MADSSavegameHeader header; + header._saveName = saveName; + writeSavegameHeader(out, header); + + Common::Serializer s(nullptr, out); + synchronize(s, true); + synchronize(s, false); + + out->finalize(); + delete out; +} + +const char *const SAVEGAME_STR = "MADS"; +#define SAVEGAME_STR_SIZE 4 + +bool Game::readSavegameHeader(Common::InSaveFile *in, MADSSavegameHeader &header) { + char saveIdentBuffer[SAVEGAME_STR_SIZE + 1]; + header._thumbnail = nullptr; + + // Validate the header Id + in->read(saveIdentBuffer, SAVEGAME_STR_SIZE + 1); + if (strncmp(saveIdentBuffer, SAVEGAME_STR, SAVEGAME_STR_SIZE)) + return false; + + header._version = in->readByte(); + if (header._version > MADS_SAVEGAME_VERSION) + return false; + + // Read in the string + header._saveName.clear(); + char ch; + while ((ch = (char)in->readByte()) != '\0') header._saveName += ch; + + // Get the thumbnail + header._thumbnail = Graphics::loadThumbnail(*in); + if (!header._thumbnail) + return false; + + // Read in save date/time + header._year = in->readSint16LE(); + header._month = in->readSint16LE(); + header._day = in->readSint16LE(); + header._hour = in->readSint16LE(); + header._minute = in->readSint16LE(); + header._totalFrames = in->readUint32LE(); + + return true; +} + +void Game::writeSavegameHeader(Common::OutSaveFile *out, MADSSavegameHeader &header) { + // Write out a savegame header + out->write(SAVEGAME_STR, SAVEGAME_STR_SIZE + 1); + + out->writeByte(MADS_SAVEGAME_VERSION); + + // Write savegame name + out->write(header._saveName.c_str(), header._saveName.size()); + out->writeByte('\0'); + + // Get the active palette + uint8 thumbPalette[256 * 3]; + g_system->getPaletteManager()->grabPalette(thumbPalette, 0, 256); + + // Create a thumbnail and save it + Graphics::Surface *thumb = new Graphics::Surface(); + ::createThumbnail(thumb, _vm->_screen.getData(), MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT, thumbPalette); + Graphics::saveThumbnail(*out, *thumb); + thumb->free(); + delete thumb; + + // Write out the save date/time + TimeDate td; + g_system->getTimeAndDate(td); + out->writeSint16LE(td.tm_year + 1900); + out->writeSint16LE(td.tm_mon + 1); + out->writeSint16LE(td.tm_mday); + out->writeSint16LE(td.tm_hour); + out->writeSint16LE(td.tm_min); + out->writeUint32LE(_vm->_events->getFrameCounter()); +} + +} // End of namespace MADS diff --git a/engines/mads/game.h b/engines/mads/game.h new file mode 100644 index 0000000000..1b06f847d0 --- /dev/null +++ b/engines/mads/game.h @@ -0,0 +1,241 @@ +/* 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. + * + */ + +#ifndef MADS_GAME_H +#define MADS_GAME_H + +#include "common/scummsys.h" +#include "common/savefile.h" +#include "common/str-array.h" +#include "common/serializer.h" +#include "mads/audio.h" +#include "mads/scene.h" +#include "mads/game_data.h" +#include "mads/globals.h" +#include "mads/inventory.h" +#include "mads/player.h" +#include "mads/screen.h" + +namespace MADS { + +class MADSEngine; + +enum { + PLAYER_INVENTORY = 2 +}; + +enum KernelMode { + KERNEL_GAME_LOAD = 0, KERNEL_SECTION_PRELOAD = 1, KERNEL_SECTION_INIT = 2, + KERNEL_ROOM_PRELOAD = 3, KERNEL_ROOM_INIT = 4, KERNEL_ACTIVE_CODE = 5 +}; + +enum ProtectionResult { + PROTECTION_SUCCEED = 0, PROTECTION_FAIL = 1, PROTECTION_ESCAPE = 2 +}; + +#define MADS_SAVEGAME_VERSION 1 + +struct MADSSavegameHeader { + uint8 _version; + Common::String _saveName; + Graphics::Surface *_thumbnail; + int _year, _month, _day; + int _hour, _minute; + int _totalFrames; +}; + +class Game { +private: + /** + * Main game loop + */ + void gameLoop(); + + /** + * Inner game loop for executing gameplay within a game section + */ + void sectionLoop(); + + /** + * Load quotes data + */ + void loadQuotes(); +protected: + MADSEngine *_vm; + MSurface *_surface; + int _statusFlag; + Common::StringArray _quotes; + bool _quoteEmergency; + bool _vocabEmergency; + bool _anyEmergency; + int _lastSave; + Common::String _saveName; + Common::InSaveFile *_saveFile; + + /** + * Constructor + */ + Game(MADSEngine *vm); + + /** + * Initializes the current section number of the game + */ + void initSection(int sectionNumber); + + //@{ + /** @name Virtual Method list */ + + /** + * Perform any copy protection check + */ + virtual ProtectionResult checkCopyProtection() = 0; + + /** + * Initializes global variables for a new game + */ + virtual void initializeGlobals() = 0; + + /** + * Set up the section handler specific to each section + */ + virtual void setSectionHandler() = 0; + + /** + * Checks for whether to show a dialog + */ + virtual void checkShowDialog() = 0; + + //@} + +public: + static Game *init(MADSEngine *vm); + +public: + Player _player; + ScreenObjects _screenObjects; + int _sectionNumber; + int _priorSectionNumber; + int _currentSectionNumber; + InventoryObjects _objects; + SectionHandler *_sectionHandler; + VisitedScenes _visitedScenes; + Scene _scene; + KernelMode _kernelMode; + int _trigger; + ScreenTransition _fx; + TriggerMode _triggerMode; + TriggerMode _triggerSetupMode; + uint32 _priorFrameTimer; + Common::String _aaName; + int _winStatus; + int _widepipeCtr; + int _loadGameSlot; + +public: + virtual ~Game(); + + /** + * Main outer loop for the game + */ + void run(); + + /** + * Return the number of quotes + */ + uint32 getQuotesSize() { return _quotes.size(); } + + /** + * Get a specific quote string + */ + const Common::String &getQuote(uint32 index) { return _quotes[index - 1]; } + + /** + * Split a quote into two lines for display on-screen + */ + void splitQuote(const Common::String &source, Common::String &line1, Common::String &line2); + + Common::StringArray getMessage(uint32 id); + + /** + * Returns the globals for the game + */ + virtual Globals &globals() = 0; + + /** + * Standard object handling across the game + */ + virtual void doObjectAction() = 0; + + /** + * Fallback handler for any action that isn't explicitly handled + */ + virtual void unhandledAction() = 0; + + /** + * Global game step + */ + virtual void step() = 0; + + /** + * Synchronize the game data + * @param s Serializer + * @param phase1 If true, it's synchronizing the basic scene information + */ + virtual void synchronize(Common::Serializer &s, bool phase1); + + // DEPRECATED: ScummVM re-implementation keeps all the quotes loaded, so the methods below are stubs + void clearQuotes() {} + void loadQuoteRange(int startNum, int endNum) {} + void loadQuoteSet(...) {} + void loadQuote(int quoteNum) {} + + /** + * Handle a keyboard event + */ + void handleKeypress(const Common::Event &event); + + /** + * Starts a savegame loading. + * @remarks Due to the way the engine is implemented, loading is done in two + * parts, the second part after the specific scene has been loaded + */ + void loadGame(int slotNumber); + + /** + * Save the current game + */ + void saveGame(int slotNumber, const Common::String &saveName); + + /** + * Write out a savegame header + */ + void writeSavegameHeader(Common::OutSaveFile *out, MADSSavegameHeader &header); + + /** + * Read in a savegame header + */ + static bool readSavegameHeader(Common::InSaveFile *in, MADSSavegameHeader &header); +}; + +} // End of namespace MADS + +#endif /* MADS_GAME_H */ diff --git a/engines/mads/game_data.cpp b/engines/mads/game_data.cpp new file mode 100644 index 0000000000..0e2dcec70f --- /dev/null +++ b/engines/mads/game_data.cpp @@ -0,0 +1,54 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 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. + * + */ + +#include "common/scummsys.h" +#include "mads/mads.h" +#include "mads/game.h" +#include "mads/nebular/game_nebular.h" +#include "mads/screen.h" +#include "mads/msurface.h" +#include "mads/resources.h" + +namespace MADS { + +void VisitedScenes::add(int sceneId) { + _sceneRevisited = exists(sceneId); + + if (!_sceneRevisited) + push_back(sceneId); +} + +bool VisitedScenes::exists(int sceneId) { + for (uint i = 0; i < size(); ++i) { + if ((*this)[i] == sceneId) + return true; + } + + return false; +} + +void VisitedScenes::synchronize(Common::Serializer &s) { + SynchronizedList::synchronize(s); + s.syncAsByte(_sceneRevisited); +} + +} // End of namespace MADS diff --git a/engines/mads/game_data.h b/engines/mads/game_data.h new file mode 100644 index 0000000000..f15cd1a8f0 --- /dev/null +++ b/engines/mads/game_data.h @@ -0,0 +1,73 @@ +/* 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. + * + */ + +#ifndef MADS_GAME_DATA_H +#define MADS_GAME_DATA_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "mads/resources.h" + +namespace MADS { + +class MADSEngine; +class Game; + +class VisitedScenes : public SynchronizedList { +public: + /** + * Stores true when a previously visited scene is revisited + */ + bool _sceneRevisited; + + /** + * Returns true if a given Scene Id exists in the listed of previously visited scenes. + */ + bool exists(int sceneId); + + /** + * Adds a scene Id to the list of previously visited scenes, if it doesn't already exist + */ + void add(int sceneId); + + /** + * Synchronizes the list + */ + void synchronize(Common::Serializer &s); +}; + +class SectionHandler { +protected: + MADSEngine *_vm; +public: + SectionHandler(MADSEngine *vm) : _vm(vm) {} + virtual ~SectionHandler() {} + + virtual void preLoadSection() = 0; + virtual void sectionPtr2() = 0; + virtual void postLoadSection() = 0; + virtual void step() {} +}; + +} // End of namespace MADS + +#endif /* MADS_GAME_DATA_H */ diff --git a/engines/mads/globals.cpp b/engines/mads/globals.cpp new file mode 100644 index 0000000000..1d088992ea --- /dev/null +++ b/engines/mads/globals.cpp @@ -0,0 +1,33 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 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. + * + */ + +#include "common/scummsys.h" +#include "mads/globals.h" + +namespace MADS { + +void Globals::reset() { + for (uint i = 0; i < size(); ++i) + (*this)[i] = 0; +} + +} // End of namespace MADS diff --git a/engines/mads/globals.h b/engines/mads/globals.h new file mode 100644 index 0000000000..a6c9b628dd --- /dev/null +++ b/engines/mads/globals.h @@ -0,0 +1,47 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 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. + * + */ + +#ifndef MADS_GLOBALS_H +#define MADS_GLOBALS_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/serializer.h" +#include "mads/resources.h" + +namespace MADS { + +class Globals : public SynchronizedList { +public: + Globals() {} + + virtual ~Globals() {} + + /* + * Resets all the globals to empty + */ + void reset(); +}; + +} // End of namespace MADS + +#endif /* MADS_GLOBALS_H */ diff --git a/engines/mads/hotspots.cpp b/engines/mads/hotspots.cpp new file mode 100644 index 0000000000..365f30985b --- /dev/null +++ b/engines/mads/hotspots.cpp @@ -0,0 +1,207 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 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. + * + */ + +#include "mads/mads.h" +#include "mads/hotspots.h" + +namespace MADS { + +DynamicHotspot::DynamicHotspot() { + _seqIndex = 0; + _facing = FACING_NONE; + _descId = 0; + _verbId = 0; + _articleNumber = 0; + _cursor = CURSOR_NONE; + _active = false; +} + +void DynamicHotspot::synchronize(Common::Serializer &s) { + +} + +/*------------------------------------------------------------------------*/ + +DynamicHotspots::DynamicHotspots(MADSEngine *vm) : _vm(vm) { + for (int i = 0; i < DYNAMIC_HOTSPOTS_SIZE; ++i) { + DynamicHotspot rec; + rec._active = false; + _entries.push_back(rec); + } + + _changed = true; + _count = 0; +} + +int DynamicHotspots::add(int descId, int verbId, int seqIndex, const Common::Rect &bounds) { + // Find a free slot + uint idx = 0; + while ((idx < _entries.size()) && _entries[idx]._active) + ++idx; + if (idx == _entries.size()) + error("DynamicHotspots overflow"); + + _entries[idx]._active = true; + _entries[idx]._descId = descId; + _entries[idx]._seqIndex = seqIndex; + _entries[idx]._bounds = bounds; + _entries[idx]._feetPos = Common::Point(-3, 0); + _entries[idx]._facing = FACING_NONE; + _entries[idx]._verbId = verbId; + _entries[idx]._articleNumber = PREP_IN; + _entries[idx]._cursor = CURSOR_NONE; + + ++_count; + _changed = true; + + if (seqIndex >= 0) + _vm->_game->_scene._sequences[seqIndex]._dynamicHotspotIndex = idx; + + return idx; +} + +int DynamicHotspots::setPosition(int index, const Common::Point &pos, Facing facing) { + if (index >= 0) { + _entries[index]._feetPos = pos; + _entries[index]._facing = facing; + } + + return index; +} + +int DynamicHotspots::setCursor(int index, CursorType cursor) { + if (index >= 0) + _entries[index]._cursor = cursor; + + return index; +} + +void DynamicHotspots::remove(int index) { + Scene &scene = _vm->_game->_scene; + + if (index >= 0 && _entries[index]._active) { + if (_entries[index]._seqIndex >= 0) + scene._sequences[_entries[index]._seqIndex]._dynamicHotspotIndex = -1; + _entries[index]._active = false; + + --_count; + _changed = true; + } +} + +void DynamicHotspots::clear() { + for (uint i = 0; i < _entries.size(); ++i) + _entries[i]._active = false; + + _changed = false; + _count = 0; +} + +void DynamicHotspots::reset() { + for (uint i = 0; i < _entries.size(); ++i) + remove(i); + + _count = 0; + _changed = false; +} + +void DynamicHotspots::refresh() { + // Reset the screen objects back to only contain UI elements + ScreenObjects &scrObjects = _vm->_game->_screenObjects; + scrObjects.resize(scrObjects._uiCount); + + // Loop through adding hotspots + for (uint i = 0; i < _entries.size(); ++i) { + DynamicHotspot &dh = (*this)[i]; + + if ((*this)[i]._active) { + switch (scrObjects._inputMode) { + case kInputBuildingSentences: + case kInputLimitedSentences: + scrObjects.add(dh._bounds, _vm->_game->_scene._layer, CAT_12, dh._descId); + scrObjects._forceRescan = true; + break; + default: + break; + } + } + } + + // Reset the list's changed flag + _changed = false; +} + +void DynamicHotspots::synchronize(Common::Serializer &s) { + int count = _entries.size(); + s.syncAsSint16LE(count); + + // The MIN in the below loop is a workaround to fix earlier savegame + // loading accidentally adding new dynamic hotspots to the fixed list + for (int i = 0; i < count; ++i) { + _entries[MIN(i, (int)_entries.size() - 1)].synchronize(s); + } +} + +/*------------------------------------------------------------------------*/ + +Hotspot::Hotspot() { + _facing = FACING_NONE; + _articleNumber = 0; + _cursor = CURSOR_NONE; + _vocabId = 0; + _verbId = 0; + _active = false; +} + +Hotspot::Hotspot(Common::SeekableReadStream &f, bool isV2) { + _bounds.left = f.readSint16LE(); + _bounds.top = f.readSint16LE(); + _bounds.right = f.readSint16LE(); + _bounds.bottom = f.readSint16LE(); + _feetPos.x = f.readSint16LE(); + _feetPos.y = f.readSint16LE(); + _facing = (Facing)f.readByte(); + _articleNumber = f.readByte(); + _active = f.readByte() != 0; + _cursor = (CursorType)f.readByte(); + if (isV2) { + // This looks to be some sort of bitmask. Perhaps it signifies + // the valid verbs for this hotspot + f.skip(2); // unknown + } + _vocabId = f.readUint16LE(); + _verbId = f.readUint16LE(); +} + +/*------------------------------------------------------------------------*/ + +void Hotspots::activate(int vocabId, bool active) { + for (uint idx = 0; idx < size(); ++idx) { + Hotspot &hotspot = (*this)[idx]; + if (hotspot._vocabId == vocabId) { + hotspot._active = active; + _vm->_game->_screenObjects.setActive(CAT_HOTSPOT, idx, active); + } + } +} + +} // End of namespace MADS diff --git a/engines/mads/hotspots.h b/engines/mads/hotspots.h new file mode 100644 index 0000000000..5fd910e1aa --- /dev/null +++ b/engines/mads/hotspots.h @@ -0,0 +1,114 @@ +/* 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. + * + */ + +#ifndef MADS_HOTSPOTS_H +#define MADS_HOTSPOTS_H + +#include "common/scummsys.h" +#include "mads/events.h" +#include "mads/player.h" + +namespace MADS { + +class MADSEngine; + +class DynamicHotspot { +public: + bool _active; + int _seqIndex; + Common::Rect _bounds; + Common::Point _feetPos; + Facing _facing; + int _descId; + int _verbId; + int _articleNumber; + CursorType _cursor; + + /** + * Constructor + */ + DynamicHotspot(); + + /** + * Synchronize the data + */ + void synchronize(Common::Serializer &s); +}; + +#define DYNAMIC_HOTSPOTS_SIZE 8 + +class DynamicHotspots { +private: + MADSEngine *_vm; + Common::Array<DynamicHotspot> _entries; + int _count; +public: + bool _changed; +public: + DynamicHotspots(MADSEngine *vm); + + Common::Array<MADS::DynamicHotspot>::size_type size() const { return _entries.size(); } + DynamicHotspot &operator[](uint idx) { return _entries[idx]; } + int add(int descId, int verbId, int seqIndex, const Common::Rect &bounds); + int setPosition(int index, const Common::Point &pos, Facing facing); + int setCursor(int index, CursorType cursor); + void remove(int index); + void clear(); + void reset(); + void refresh(); + + /** + * Synchronize the data + */ + void synchronize(Common::Serializer &s); +}; + +class Hotspot { +public: + Common::Rect _bounds; + Common::Point _feetPos; + Facing _facing; + int _articleNumber; + bool _active; + CursorType _cursor; + int _vocabId; + int _verbId; + + Hotspot(); + Hotspot(Common::SeekableReadStream &f, bool isV2); +}; + +class Hotspots : public Common::Array<Hotspot> { +private: + MADSEngine *_vm; +public: + Hotspots(MADSEngine *vm) : _vm(vm) {} + + /** + * Sets the active state of a given hotspot + */ + void activate(int vocabId, bool active); +}; + +} // End of namespace MADS + +#endif /* MADS_HOTSPOTS_H */ diff --git a/engines/mads/inventory.cpp b/engines/mads/inventory.cpp new file mode 100644 index 0000000000..b7864bc6a7 --- /dev/null +++ b/engines/mads/inventory.cpp @@ -0,0 +1,226 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "mads/mads.h" +#include "mads/inventory.h" + +namespace MADS { + +void InventoryObject::synchronize(Common::Serializer &s) { + s.syncAsUint16LE(_descId); + s.syncAsUint16LE(_roomNumber); + s.syncAsByte(_article); + s.syncAsByte(_vocabCount); + s.syncAsByte(_qualitiesCount); + s.skip(1); + + for (int i = 0; i < MAX_VOCAB; ++i) { + s.syncAsUint16LE(_vocabList[i]._vocabId); + s.syncAsByte(_vocabList[i]._verbType); + s.syncAsByte(_vocabList[i]._prepType); + } + + for (int i = 0; i < MAX_QUALITIES; ++i) + s.syncAsByte(_qualityId[i]); + for (int i = 0; i < MAX_QUALITIES; ++i) + s.syncAsSint32LE(_qualityValue[i]); +} + +bool InventoryObject::hasQuality(int qualityId) const { + for (int i = 0; i < _qualitiesCount; ++i) { + if (_qualityId[i] == qualityId) + return true; + } + + return false; +} + +void InventoryObject::setQuality(int qualityId, int qualityValue) { + for (int i = 0; i < _qualitiesCount; ++i) { + if (_qualityId[i] == qualityId) { + _qualityValue[i] = qualityValue; + } + } +} + +int InventoryObject::getQuality(int qualityId) const { + for (int i = 0; i < _qualitiesCount; ++i) { + if (_qualityId[i] == qualityId) { + return _qualityValue[i]; + } + } + + return 0; +} + +/*------------------------------------------------------------------------*/ + +void InventoryObjects::load() { + File f("*OBJECTS.DAT"); + int count = f.readUint16LE(); + Common::Serializer s(&f, nullptr); + + // Load the objects data + reserve(count); + for (int i = 0; i < count; ++i) { + InventoryObject obj; + obj.synchronize(s); + push_back(obj); + + // If it's for the player's inventory, add the index to the inventory list + if (obj._roomNumber == PLAYER_INVENTORY) { + _inventoryList.push_back(i); + assert(_inventoryList.size() <= 32); + } + } +} + +void InventoryObjects::synchronize(Common::Serializer &s) { + int count = size(); + s.syncAsUint16LE(count); + + if (s.isSaving()) { + // Store the data for each object in the inventory lsit + for (int idx = 0; idx < count; ++idx) + (*this)[idx].synchronize(s); + + // Synchronize the player's inventory + _inventoryList.synchronize(s); + } else { + clear(); + + // Read in each object + reserve(count); + for (int i = 0; i < count; ++i) { + InventoryObject obj; + obj.synchronize(s); + push_back(obj); + } + + // Synchronize the player's inventory + _inventoryList.synchronize(s); + } +} + +void InventoryObjects::setRoom(int objectId, int sceneNumber) { + InventoryObject &obj = (*this)[objectId]; + + if (obj._roomNumber == PLAYER_INVENTORY) + removeFromInventory(objectId, 1); + + if (sceneNumber == PLAYER_INVENTORY) + addToInventory(objectId); + else + obj._roomNumber = sceneNumber; +} + +bool InventoryObjects::isInRoom(int objectId) const { + return objectId >= 0 && (*this)[objectId]._roomNumber == _vm->_game->_scene._currentSceneId; +} + +bool InventoryObjects::isInInventory(int objectId) const { + return objectId >= 0 && (*this)[objectId]._roomNumber == PLAYER_INVENTORY; +} + +void InventoryObjects::addToInventory(int objectId) { + assert(_inventoryList.size() < 32); + UserInterface &userInterface = _vm->_game->_scene._userInterface; + + if (!isInInventory(objectId)) { + _inventoryList.push_back(objectId); + userInterface._selectedInvIndex = _inventoryList.size() - 1; + userInterface._inventoryTopIndex = CLIP(userInterface._inventoryTopIndex, + 0, userInterface._selectedInvIndex); + + if ((userInterface._inventoryTopIndex + 5) <= (int)_inventoryList.size()) + userInterface._inventoryTopIndex = _inventoryList.size() - 5; + userInterface._inventoryChanged = true; + + (*this)[objectId]._roomNumber = PLAYER_INVENTORY; + + if (_vm->_game->_kernelMode == KERNEL_ACTIVE_CODE && + _vm->_game->_screenObjects._inputMode == kInputBuildingSentences) { + userInterface.categoryChanged(); + userInterface.selectObject(userInterface._selectedInvIndex); + } + } +} + +void InventoryObjects::removeFromInventory(int objectId, int newScene) { + Scene &scene = _vm->_game->_scene; + UserInterface &userInterface = scene._userInterface; + + // Scan the inventory list for the object + int invIndex = -1; + for (int idx = 0; idx < (int)_inventoryList.size() && invIndex == -1; ++idx) { + if (_inventoryList[idx] == objectId) + invIndex = idx; + } + + // If the object isn't in the player's inventory, stop here + if (invIndex < 0) + return; + + int selectedIndex = userInterface._selectedInvIndex; + bool noSelection = selectedIndex < 0; + + if (_vm->_game->_kernelMode == KERNEL_ACTIVE_CODE && + _vm->_game->_screenObjects._inputMode == kInputBuildingSentences) + userInterface.selectObject(-1); + + // Remove the item from the inventory list + _inventoryList.remove_at(invIndex); + + if (invIndex > userInterface._inventoryTopIndex) { + userInterface._inventoryTopIndex = MAX(userInterface._inventoryTopIndex, 0); + } + + userInterface._inventoryChanged = true; + (*this)[objectId]._roomNumber = newScene; + + int newIndex = selectedIndex; + if (!noSelection) { + if (newIndex >= invIndex) + --newIndex; + if (newIndex < 0 && size() > 0) + newIndex = 0; + } + + if (_vm->_game->_kernelMode == KERNEL_ACTIVE_CODE && + _vm->_game->_screenObjects._inputMode == kInputBuildingSentences) { + userInterface.categoryChanged(); + userInterface.selectObject(newIndex); + } +} + +int InventoryObjects::getIdFromDesc(int descId) { + for (int i = 0; i < (int)size(); ++i) { + InventoryObject &obj = (*this)[i]; + if (obj._descId == descId) + return i; + } + + return -1; +} + +} // End of namespace MADS diff --git a/engines/mads/inventory.h b/engines/mads/inventory.h new file mode 100644 index 0000000000..09ed67a826 --- /dev/null +++ b/engines/mads/inventory.h @@ -0,0 +1,141 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 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. + * + */ + +#ifndef MADS_INVENTORY_H +#define MADS_INVENTORY_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/serializer.h" + +namespace MADS { + +enum { + NOWHERE = 1 +}; + +class MADSEngine; + +#define MAX_VOCAB 5 +#define MAX_QUALITIES 4 + +class InventoryObject { +public: + int _descId; + int _roomNumber; + int _article; + int _vocabCount; + int _qualitiesCount; + int syntax; + + struct { + int _vocabId; + VerbType _verbType; + PrepType _prepType; + } _vocabList[MAX_VOCAB]; + + int _qualityId[MAX_QUALITIES]; + int _qualityValue[MAX_QUALITIES]; + + /** + * Synchronizes the data for a given object + */ + void synchronize(Common::Serializer &s); + + /** + * Returns true if the given object has the specified quality + */ + bool hasQuality(int qualityId) const; + + /** + * Sets the quality value for a given quality Id + */ + void setQuality(int qualityId, int qualityValue); + + /** + * Gets the quality value for a given quality Id + */ + int getQuality(int qualityId) const; +}; + +class InventoryObjects : public Common::Array<InventoryObject> { +private: + MADSEngine *_vm; + +public: + SynchronizedList _inventoryList; + + /** + * Constructor + */ + InventoryObjects(MADSEngine *vm) : _vm(vm) {} + + /** + * Loads the game's object list + */ + void load(); + + /** + * Synchronize the objects list in a savegame + */ + void synchronize(Common::Serializer &s); + + /** + * Returns the inventory item from the player's inventory + */ + InventoryObject &getItem(int itemIndex) { + return (*this)[_inventoryList[itemIndex]]; + } + + /** + * Sets an item's scene number + */ + void setRoom(int objectId, int sceneNumber); + + /** + * Returns true if a given object is in the player's current scene + */ + bool isInRoom(int objectId) const; + + /** + * Returns true if a given object is in the player's inventory + */ + bool isInInventory(int objectId) const; + + /** + * Removes the specified object from the player's inventory + */ + void addToInventory(int objectId); + + /** + * Removes the specified object to the player's inventory + * @param objectId Object to remove + * @param newScene Specifies the new scene to set the item to + */ + void removeFromInventory(int objectId, int newScene); + + int getIdFromDesc(int objectId); +}; + +} // End of namespace MADS + +#endif /* MADS_INVENTORY_H */ diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp new file mode 100644 index 0000000000..31e9b0dbe2 --- /dev/null +++ b/engines/mads/mads.cpp @@ -0,0 +1,157 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "common/config-manager.h" +#include "common/debug-channels.h" +#include "common/events.h" +#include "engines/util.h" +#include "mads/mads.h" +#include "mads/game.h" +#include "mads/screen.h" +#include "mads/msurface.h" +#include "mads/resources.h" +#include "mads/sound.h" +#include "mads/sprites.h" + +namespace MADS { + +MADSEngine::MADSEngine(OSystem *syst, const MADSGameDescription *gameDesc) : + _gameDescription(gameDesc), Engine(syst), _randomSource("MADS") { + + // Initialize fields + _easyMouse = true; + _invObjectsAnimated = true; + _textWindowStill = false; + _screenFade = SCREEN_FADE_SMOOTH; + _musicFlag = true; + _dithering = false; + + _debugger = nullptr; + _dialogs = nullptr; + _events = nullptr; + _font = nullptr; + _game = nullptr; + _palette = nullptr; + _resources = nullptr; + _sound = nullptr; + _audio = nullptr; +} + +MADSEngine::~MADSEngine() { + delete _debugger; + delete _dialogs; + delete _events; + delete _font; + Font::deinit(); + delete _game; + delete _palette; + delete _resources; + delete _sound; +} + +void MADSEngine::initialize() { + // Set up debug channels + DebugMan.addDebugChannel(kDebugPath, "Path", "Pathfinding debug level"); + DebugMan.addDebugChannel(kDebugScripts, "scripts", "Game scripts"); + DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics handling"); + + // Initial sub-system engine references + MSurface::setVm(this); + MSprite::setVm(this); + + Resources::init(this); + Conversation::init(this); + _debugger = new Debugger(this); + _dialogs = Dialogs::init(this); + _events = new EventsManager(this); + _palette = new Palette(this); + Font::init(this); + _font = new Font(); + _screen.init(); + _sound = new SoundManager(this, _mixer); + _audio = new AudioPlayer(_mixer, getGameID()); + _game = Game::init(this); + + _screen.empty(); +} + +Common::Error MADSEngine::run() { + initGraphics(MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT, false); + initialize(); + + // Run the game + _game->run(); + + // Dummy loop to keep application active + _events->delay(9999); + + return Common::kNoError; +} + +int MADSEngine::getRandomNumber(int maxNumber) { + return _randomSource.getRandomNumber(maxNumber); +} + +int MADSEngine::getRandomNumber(int minNumber, int maxNumber) { + int range = maxNumber - minNumber; + + return minNumber + _randomSource.getRandomNumber(range); +} + +int MADSEngine::hypotenuse(int xv, int yv) { + return (int)sqrt((double)(xv * xv + yv * yv)); +} + +bool MADSEngine::canLoadGameStateCurrently() { + return !_game->_winStatus && !_game->globals()[5] + && _dialogs->_pendingDialog == DIALOG_NONE + && _events->_cursorId != CURSOR_WAIT; +} + +bool MADSEngine::canSaveGameStateCurrently() { + return !_game->_winStatus && !_game->globals()[5] + && _dialogs->_pendingDialog == DIALOG_NONE + && _events->_cursorId != CURSOR_WAIT; +} + +/** +* Support method that generates a savegame name +* @param slot Slot number +*/ +Common::String MADSEngine::generateSaveName(int slot) { + return Common::String::format("%s.%03d", _targetName.c_str(), slot); +} + +Common::Error MADSEngine::loadGameState(int slot) { + _game->_loadGameSlot = slot; + _game->_scene._currentSceneId = -1; + _game->_currentSectionNumber = -1; + return Common::kNoError; +} + +Common::Error MADSEngine::saveGameState(int slot, const Common::String &desc) { + _game->saveGame(slot, desc); + return Common::kNoError; +} + +} // End of namespace MADS diff --git a/engines/mads/mads.h b/engines/mads/mads.h new file mode 100644 index 0000000000..9a8f2152a1 --- /dev/null +++ b/engines/mads/mads.h @@ -0,0 +1,152 @@ +/* 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. + * + */ + +#ifndef MADS_MADS_H +#define MADS_MADS_H + +#include "common/scummsys.h" +#include "common/system.h" +#include "common/error.h" +#include "common/random.h" +#include "common/util.h" +#include "engines/engine.h" +#include "graphics/surface.h" +#include "mads/debugger.h" +#include "mads/dialogs.h" +#include "mads/events.h" +#include "mads/font.h" +#include "mads/game.h" +#include "mads/screen.h" +#include "mads/msurface.h" +#include "mads/resources.h" +#include "mads/sound.h" + +/** + * This is the namespace of the MADS engine. + * + * Status of this engine: In Development + * + * Games using this engine: + * - Rex Nebular and the Cosmic Gender Bender + */ +namespace MADS { + +#define DEBUG_BASIC 1 +#define DEBUG_INTERMEDIATE 2 +#define DEBUG_DETAILED 3 + +enum MADSDebugChannels { + kDebugPath = 1 << 0, + kDebugScripts = 1 << 1, + kDebugGraphics = 1 << 2 +}; + +enum { + GType_RexNebular = 0, + GType_Dragonsphere = 1, + GType_Phantom = 2 +}; + +enum ScreenFade { + SCREEN_FADE_SMOOTH = 0, + SCREEN_FADE_MEDIUM = 1, + SCREEN_FADE_FAST = 2 +}; + +struct MADSGameDescription; + + +class MADSEngine : public Engine { +private: + const MADSGameDescription *_gameDescription; + Common::RandomSource _randomSource; + + /** + * Handles basic initialisation + */ + void initialize(); +protected: + // Engine APIs + virtual Common::Error run(); + virtual bool hasFeature(EngineFeature f) const; +public: + Debugger *_debugger; + Dialogs *_dialogs; + EventsManager *_events; + Font *_font; + Game *_game; + Palette *_palette; + Resources *_resources; + ScreenSurface _screen; + SoundManager *_sound; + AudioPlayer *_audio; + bool _easyMouse; + bool _invObjectsAnimated; + bool _textWindowStill; + ScreenFade _screenFade; + bool _musicFlag; + bool _dithering; +public: + MADSEngine(OSystem *syst, const MADSGameDescription *gameDesc); + virtual ~MADSEngine(); + + uint32 getFeatures() const; + Common::Language getLanguage() const; + Common::Platform getPlatform() const; + uint16 getVersion() const; + uint32 getGameID() const; + uint32 getGameFeatures() const; + + int getRandomNumber(int maxNumber); + int getRandomNumber(int minNumber, int maxNumber); + int hypotenuse(int xv, int yv); + + /** + * Returns true if it is currently okay to restore a game + */ + bool canLoadGameStateCurrently(); + + /** + * Returns true if it is currently okay to save the game + */ + bool canSaveGameStateCurrently(); + + /** + * Support method that generates a savegame name + * @param slot Slot number + */ + Common::String generateSaveName(int slot); + + /** + * Handles loading a game via the GMM + */ + virtual Common::Error loadGameState(int slot); + + /** + * Handles saving the game via the GMM + */ + virtual Common::Error saveGameState(int slot, const Common::String &desc); +}; + +} // End of namespace MADS + +#endif /* MADS_MADS_H */ diff --git a/engines/mads/messages.cpp b/engines/mads/messages.cpp new file mode 100644 index 0000000000..9b2d6f3114 --- /dev/null +++ b/engines/mads/messages.cpp @@ -0,0 +1,570 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "mads/mads.h" +#include "mads/font.h" +#include "mads/screen.h" +#include "mads/messages.h" +#include "mads/scene_data.h" + +namespace MADS { + +RandomMessages::RandomMessages() { + reserve(RANDOM_MESSAGE_SIZE); + _randomSpacing = 0; + _color = -1; + _duration = 0; + _scrollRate = -1; +} + +void RandomMessages::reset() { + for (uint i = 0; i < size(); ++i) { + (*this)[i]._handle = -1; + (*this)[i]._quoteId = -1; + } +} + + +KernelMessages::KernelMessages(MADSEngine *vm) + : _vm(vm) { + for (int i = 0; i < KERNEL_MESSAGES_SIZE; ++i) { + KernelMessage rec; + _entries.push_back(rec); + } + + _talkFont = _vm->_font->getFont(FONT_CONVERSATION); +} + +KernelMessages::~KernelMessages() { +} + +void KernelMessages::clear() { + Scene &scene = _vm->_game->_scene; + + for (uint i = 0; i < _entries.size(); ++i) + _entries[i]._flags = 0; + + _talkFont = _vm->_font->getFont(FONT_CONVERSATION); + scene._textSpacing = -1; +} + +int KernelMessages::add(const Common::Point &pt, uint fontColor, uint8 flags, + uint8 abortTimers, uint32 timeout, const Common::String &msg) { + Scene &scene = _vm->_game->_scene; + + // Find a free slot + uint idx = 0; + while ((idx < _entries.size()) && ((_entries[idx]._flags & KMSG_ACTIVE) != 0)) + ++idx; + if (idx == _entries.size()) { + if (abortTimers == 0) + return -1; + + error("KernelMessages overflow"); + } + + KernelMessage &rec = _entries[idx]; + rec._msg = msg; + rec._flags = flags | KMSG_ACTIVE; + rec._color1 = fontColor & 0xff; + rec._color2 = fontColor >> 8; + rec._position = pt; + rec._textDisplayIndex = -1; + rec._timeout = timeout; + rec._frameTimer = _vm->_game->_priorFrameTimer; + rec._trigger = abortTimers; + rec._abortMode = _vm->_game->_triggerSetupMode; + + rec._actionDetails = scene._action._activeAction; + + if (flags & KMSG_PLAYER_TIMEOUT) + rec._frameTimer = _vm->_game->_player._ticksAmount + + _vm->_game->_player._priorTimer; + + return idx; +} + +int KernelMessages::addQuote(int quoteId, int abortTimers, uint32 timeout) { + Common::String quoteStr = _vm->_game->getQuote(quoteId); + return add(Common::Point(), 0x1110, KMSG_PLAYER_TIMEOUT | KMSG_CENTER_ALIGN, + abortTimers, timeout, quoteStr); +} + +void KernelMessages::scrollMessage(int msgIndex, int numTicks, bool quoted) { + if (msgIndex < 0) + return; + + _entries[msgIndex]._flags |= quoted ? (KMSG_SCROLL | KMSG_QUOTED) : KMSG_SCROLL; + _entries[msgIndex]._msgOffset = 0; + _entries[msgIndex]._numTicks = numTicks; + _entries[msgIndex]._frameTimer2 = _vm->_game->_priorFrameTimer; + + Common::String msg = _entries[msgIndex]._msg; + + if (_entries[msgIndex]._flags & KMSG_PLAYER_TIMEOUT) + _entries[msgIndex]._frameTimer2 = _vm->_game->_player._ticksAmount + + _vm->_game->_player._priorTimer; + + _entries[msgIndex]._frameTimer = _entries[msgIndex]._frameTimer2; +} + +void KernelMessages::setSeqIndex(int msgIndex, int seqIndex) { + if (msgIndex >= 0) { + _entries[msgIndex]._flags |= KMSG_SEQ_ENTRY; + _entries[msgIndex]._sequenceIndex = seqIndex; + } +} + +void KernelMessages::remove(int msgIndex) { + KernelMessage &rec = _entries[msgIndex]; + Scene &scene = _vm->_game->_scene; + + if (rec._flags & KMSG_ACTIVE) { + if (rec._flags & KMSG_SCROLL) { + // WORKAROUND: Code here no longer needed in ScummVM + } + + if (rec._textDisplayIndex >= 0) + scene._textDisplay.expire(rec._textDisplayIndex); + + rec._flags &= ~KMSG_ACTIVE; + } +} + +void KernelMessages::reset() { + for (uint i = 0; i < _entries.size(); ++i) + remove(i); + + _randomMessages.clear(); +} + +void KernelMessages::update() { + uint32 currentTimer = _vm->_game->_scene._frameStartTime; + + for (uint i = 0; i < _entries.size() && !_vm->_game->_trigger; ++i) { + KernelMessage &msg = _entries[i]; + + if (((msg._flags & KMSG_ACTIVE) != 0) && (currentTimer >= msg._frameTimer)) + processText(i); + } +} + +void KernelMessages::processText(int msgIndex) { + Scene &scene = _vm->_game->_scene; + KernelMessage &msg = _entries[msgIndex]; + uint32 currentTimer = _vm->_game->_priorFrameTimer; + bool flag = false; + + if ((msg._flags & KMSG_EXPIRE) != 0) { + scene._textDisplay.expire(msg._textDisplayIndex); + msg._flags &= ~KMSG_ACTIVE; + return; + } + + if ((msg._flags & KMSG_SCROLL) == 0) { + msg._timeout -= 3; + } + + if (msg._flags & KMSG_SEQ_ENTRY) { + SequenceEntry &seqEntry = scene._sequences[msg._sequenceIndex]; + if (seqEntry._doneFlag || !seqEntry._active) + msg._timeout = 0; + } + + if ((msg._timeout <= 0) && (_vm->_game->_trigger == 0)) { + msg._flags |= KMSG_EXPIRE; + if (msg._trigger != 0) { + _vm->_game->_trigger = msg._trigger; + _vm->_game->_triggerMode = msg._abortMode; + + if (_vm->_game->_triggerMode != SEQUENCE_TRIGGER_DAEMON) { + scene._action._activeAction = msg._actionDetails; + } + } + } + + msg._frameTimer = currentTimer + 3; + int x1 = 0, y1 = 0; + + if (msg._flags & KMSG_SEQ_ENTRY) { + SequenceEntry &seqEntry = scene._sequences[msg._sequenceIndex]; + if (!seqEntry._nonFixed) { + SpriteAsset &spriteSet = *scene._sprites[seqEntry._spritesIndex]; + MSprite *frame = spriteSet.getFrame(seqEntry._frameIndex - 1); + x1 = frame->getBounds().left; + y1 = frame->getBounds().top; + } else { + x1 = seqEntry._position.x; + y1 = seqEntry._position.y; + } + } + + Player &player = _vm->_game->_player; + if (msg._flags & KMSG_PLAYER_TIMEOUT) { + if (player._beenVisible) { + SpriteAsset &asset = *_vm->_game->_scene._sprites[player._spritesStart + player._spritesIdx]; + MSprite *frame = asset.getFrame(player._frameNumber - 1); + + int yAmount = player._currentScale * player._centerOfGravity / 100; + x1 = player._playerPos.x; + y1 = (frame->h * player._currentScale / -100) + yAmount + + player._playerPos.y - 15; + } else { + x1 = 160; + y1 = 78; + } + } + + x1 += msg._position.x; + y1 += msg._position.y; + + Common::String displayMsg = msg._msg; + + if ((msg._flags & KMSG_SCROLL) && (msg._frameTimer >= currentTimer)) { + ++msg._msgOffset; + + if (msg._msgOffset >= msg._msg.size()) { + // End of message + msg._flags &= ~KMSG_SCROLL; + } else { + displayMsg = Common::String(msg._msg.c_str(), msg._msg.c_str() + msg._msgOffset); + } + + msg._frameTimer = msg._frameTimer2 = currentTimer + msg._numTicks; + flag = true; + } + + int strWidth = _talkFont->getWidth(displayMsg, scene._textSpacing); + + if (msg._flags & (KMSG_RIGHT_ALIGN | KMSG_CENTER_ALIGN)) { + x1 -= (msg._flags & KMSG_CENTER_ALIGN) ? strWidth / 2 : strWidth; + } + + // Make sure text appears entirely on-screen + int x2 = x1 + strWidth; + if (x2 > MADS_SCREEN_WIDTH) + x1 -= x2 - MADS_SCREEN_WIDTH; + if (x1 > (MADS_SCREEN_WIDTH - 1)) + x1 = MADS_SCREEN_WIDTH - 1; + if (x1 < 0) + x1 = 0; + + if (y1 >(MADS_SCENE_HEIGHT - 1)) + y1 = MADS_SCENE_HEIGHT - 1; + if (y1 < 0) + y1 = 0; + + if (msg._textDisplayIndex >= 0) { + TextDisplay &textEntry = scene._textDisplay[msg._textDisplayIndex]; + + if (flag || (textEntry._bounds.left != x1) || (textEntry._bounds.top != y1)) { + // Mark the associated text entry as deleted, so it can be re-created + scene._textDisplay.expire(msg._textDisplayIndex); + msg._textDisplayIndex = -1; + } + } + + if (msg._textDisplayIndex < 0) { + // Need to create a new text display entry for this message + int idx = scene._textDisplay.add(x1, y1, msg._color1 | (msg._color2 << 8), + scene._textSpacing, displayMsg, _talkFont); + if (idx >= 0) + msg._textDisplayIndex = idx; + } +} + +void KernelMessages::delay(uint32 priorFrameTime, uint32 currentTime) { + for (uint i = 0; i < _entries.size(); ++i) { + _entries[i]._timeout += currentTime - priorFrameTime; + } +} + +void KernelMessages::setQuoted(int msgIndex, int numTicks, bool quoted) { + if (msgIndex >= 0) { + KernelMessage &msg = _entries[msgIndex]; + + msg._flags |= KMSG_SCROLL; + if (quoted) + msg._flags |= KMSG_QUOTED; + + msg._msgOffset = 0; + msg._numTicks = numTicks; + msg._frameTimer2 = _vm->_game->_scene._frameStartTime; + + if (msg._flags & KMSG_PLAYER_TIMEOUT) { + msg._frameTimer2 = _vm->_game->_player._priorTimer + + _vm->_game->_player._ticksAmount; + } + + msg._frameTimer = msg._frameTimer2; + } +} + +#define RANDOM_MESSAGE_TRIGGER 240 + +void KernelMessages::randomServer() { + if ((_vm->_game->_trigger >= RANDOM_MESSAGE_TRIGGER) && + (_vm->_game->_trigger < (RANDOM_MESSAGE_TRIGGER + (int)_randomMessages.size()))) { + _randomMessages[_vm->_game->_trigger - RANDOM_MESSAGE_TRIGGER]._handle = -1; + _randomMessages[_vm->_game->_trigger - RANDOM_MESSAGE_TRIGGER]._quoteId = -1; + } +} + +int KernelMessages::checkRandom() { + int total = 0; + + for (uint i = 0; i < _randomMessages.size(); ++i) { + if (_randomMessages[i]._handle >= 0) + ++total; + } + + return total; +} + +bool KernelMessages::generateRandom(int major, int minor) { + bool generatedMessage = false; + + // Scan through the random messages array + for (uint msgCtr = 0; msgCtr < _randomMessages.size(); msgCtr++) { + // Find currently active random messages + if (_randomMessages[msgCtr]._handle < 0) { + // Check whether there's any existing 'scrolling in' message + bool bad = false; + for (uint scanCtr = 0; scanCtr < _randomMessages.size(); ++scanCtr) { + if (_randomMessages[scanCtr]._handle >= 0) { + if (_entries[_randomMessages[scanCtr]._handle]._flags & KMSG_SCROLL) { + bad = true; + break; + } + } + } + + // Do a random check for a new message to appear + if (_vm->getRandomNumber(major) <= minor && !bad) { + int quoteId; + + // Pick a random quote to display from the available list + do { + int quoteIdx = _vm->getRandomNumber(_randomQuotes.size() - 1); + quoteId = _randomQuotes[quoteIdx]; + + // Ensure the quote isn't already in use + bad = false; + for (uint scanCtr = 0; scanCtr < _randomMessages.size(); ++scanCtr) { + if (quoteId == _randomMessages[scanCtr]._quoteId) { + bad = true; + break; + } + } + } while (bad); + + // Store the quote Id to be used + _randomMessages[msgCtr]._quoteId = quoteId; + + // Position the message at a random position + Common::Point textPos; + textPos.x = _vm->getRandomNumber(_randomMessages._bounds.left, + _randomMessages._bounds.right); + + // Figure out Y position, making sure not to be overlapping with + // any other on-screen message + int abortCounter = 0; + + do { + // Ensure we don't get stuck in an infinite loop if too many messages + // are alrady on-screen + if (abortCounter++ > 100) goto done; + bad = false; + + // Set potential new Y position + textPos.y = _vm->getRandomNumber(_randomMessages._bounds.top, + _randomMessages._bounds.bottom); + + // Ensure it doesn't overlap an existing on-screen message + for (uint msgCtr2 = 0; msgCtr2 < _randomMessages.size(); ++msgCtr2) { + if (_randomMessages[msgCtr2]._handle >= 0) { + int lastY = _entries[_randomMessages[msgCtr2]._handle]._position.y; + + if ((textPos.y >= (lastY - _randomMessages._randomSpacing)) && + (textPos.y <= (lastY + _randomMessages._randomSpacing))) { + bad = true; + } + } + } + } while (bad); + + // Add the message + _randomMessages[msgCtr]._handle = add(textPos, _randomMessages._color, 0, + RANDOM_MESSAGE_TRIGGER + msgCtr, _randomMessages._duration, + _vm->_game->getQuote(_randomMessages[msgCtr]._quoteId)); + + if (_randomMessages._scrollRate > 0) { + if (_randomMessages[msgCtr]._handle >= 0) { + setQuoted(_randomMessages[msgCtr]._handle, + _randomMessages._scrollRate, true); + } + } + + generatedMessage = true; + break; + } + } + } + +done: + return generatedMessage; +} + +void KernelMessages::initRandomMessages(int maxSimultaneousMessages, + const Common::Rect &bounds, int minYSpacing, int scrollRate, + int color, int duration, int quoteId, ...) { + // Reset the random messages list + _randomMessages.clear(); + _randomMessages.resize(maxSimultaneousMessages); + + // Store passed parameters + _randomMessages._bounds = bounds; + _randomMessages._randomSpacing = minYSpacing; + _randomMessages._scrollRate = scrollRate; + _randomMessages._color = color; + _randomMessages._duration = duration; + + // Store the variable length random quote list + va_list va; + va_start(va, quoteId); + _randomQuotes.clear(); + + while (quoteId > 0) { + _randomQuotes.push_back(quoteId); + assert(_randomQuotes.size() < 100); + quoteId = va_arg(va, int); + } + + va_end(va); +} + + +/*------------------------------------------------------------------------*/ + +TextDisplay::TextDisplay() { + _active = false; + _expire = 0; + _spacing = 0; + _color1 = 0; + _color2 = 0; + _font = nullptr; +} + +/*------------------------------------------------------------------------*/ + +TextDisplayList::TextDisplayList(MADSEngine *vm) : _vm(vm) { + for (int i = 0; i < TEXT_DISPLAY_SIZE; ++i) { + TextDisplay rec; + rec._active = false; + rec._expire = 0; + push_back(rec); + } +} + +void TextDisplayList::reset() { + for (int i = 0; i < TEXT_DISPLAY_SIZE; ++i) + (*this)[i]._active = false; +} + +int TextDisplayList::add(int xp, int yp, uint fontColor, int charSpacing, + const Common::String &msg, Font *font) { + int usedSlot = -1; + + for (int idx = 0; idx < TEXT_DISPLAY_SIZE; ++idx) { + TextDisplay &td = (*this)[idx]; + if (!td._active) { + usedSlot = idx; + + td._bounds.left = xp; + td._bounds.top = yp; + td._font = font; + td._msg = msg; + td._bounds.setWidth(font->getWidth(msg, charSpacing)); + td._bounds.setHeight(font->getHeight()); + td._color1 = fontColor & 0xff; + td._color2 = fontColor >> 8; + td._spacing = charSpacing; + td._expire = 1; + td._active = true; + break; + } + } + + return usedSlot; +} + +void TextDisplayList::setDirtyAreas() { + Scene &scene = _vm->_game->_scene; + + for (uint idx = 0, dirtyIdx = SPRITE_SLOTS_MAX_SIZE; dirtyIdx < size(); ++idx, ++dirtyIdx) { + if (((*this)[idx]._expire >= 0) || !(*this)[idx]._active) { + scene._dirtyAreas[dirtyIdx]._active = false; + } else { + scene._dirtyAreas[dirtyIdx]._textActive = true; + scene._dirtyAreas[dirtyIdx].setTextDisplay(&(*this)[idx]); + } + } +} + +void TextDisplayList::setDirtyAreas2() { + Scene &scene = _vm->_game->_scene; + + for (uint idx = 0, dirtyIdx = SPRITE_SLOTS_MAX_SIZE; idx < size(); ++idx, ++dirtyIdx) { + if ((*this)[idx]._active && ((*this)[idx]._expire >= 0)) { + scene._dirtyAreas[dirtyIdx].setTextDisplay(&(*this)[idx]); + scene._dirtyAreas[dirtyIdx]._textActive = ((*this)[idx]._expire <= 0) ? 0 : 1; + } + } +} + +void TextDisplayList::draw(MSurface *s) { + for (uint idx = 0; idx < size(); ++idx) { + TextDisplay &td = (*this)[idx]; + if (td._active && (td._expire >= 0)) { + td._font->setColors(0xFF, td._color1, td._color2, 0); + td._font->writeString(s, td._msg, + Common::Point(td._bounds.left, td._bounds.top), + td._spacing, td._bounds.width()); + } + } +} + +void TextDisplayList::cleanUp() { + for (uint idx = 0; idx < size(); ++idx) { + if ((*this)[idx]._expire < 0) { + (*this)[idx]._active = false; + (*this)[idx]._expire = 0; + } + } +} + +void TextDisplayList::expire(int idx) { + (*this)[idx]._expire = -1; +} + +} // End of namespace MADS diff --git a/engines/mads/messages.h b/engines/mads/messages.h new file mode 100644 index 0000000000..a7411d98d1 --- /dev/null +++ b/engines/mads/messages.h @@ -0,0 +1,192 @@ +/* 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. + * + */ + +#ifndef MADS_MESSAGES_H +#define MADS_MESSAGES_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "mads/action.h" +#include "mads/font.h" +#include "mads/msurface.h" + +namespace MADS { + +#define KERNEL_MESSAGES_SIZE 10 +#define INDEFINITE_TIMEOUT 9999999 +#define TEXT_DISPLAY_SIZE 40 +#define RANDOM_MESSAGE_SIZE 4 + +enum KernelMessageFlags { + KMSG_QUOTED = 1, KMSG_PLAYER_TIMEOUT = 2, KMSG_SEQ_ENTRY = 4, KMSG_SCROLL = 8, + KMSG_RIGHT_ALIGN = 0x10, KMSG_CENTER_ALIGN = 0x20, KMSG_EXPIRE = 0x40, + KMSG_ACTIVE = 0x80 +}; + +class MADSEngine; + +class KernelMessage { +public: + uint8 _flags; + int _sequenceIndex; + int _color1; + int _color2; + Common::Point _position; + int _textDisplayIndex; + uint32 _msgOffset; + int _numTicks; + uint32 _frameTimer2; + uint32 _frameTimer; + int32 _timeout; + int _trigger; + TriggerMode _abortMode; + ActionDetails _actionDetails; + Common::String _msg; + + KernelMessage(); +}; + +struct RandomEntry { + int _handle; + int _quoteId; + + RandomEntry() { _handle = _quoteId = -1; } +}; + +class RandomMessages : public Common::Array<RandomEntry> { +public: + Common::Rect _bounds; + int _randomSpacing; + int _color; + int _duration; + int _scrollRate; +public: + RandomMessages(); + + void reset(); +}; + +class KernelMessages { +private: + MADSEngine *_vm; + + Common::Array<int> _randomQuotes; + RandomMessages _randomMessages; +public: + Common::Array<KernelMessage> _entries; + Font *_talkFont; +public: + KernelMessages(MADSEngine *vm); + ~KernelMessages(); + + void clear(); + int add(const Common::Point &pt, uint fontColor, uint8 flags, uint8 abortTimers, + uint32 timeout, const Common::String &msg); + int addQuote(int quoteId, int abortTimers, uint32 timeout); + void scrollMessage(int msgIndex, int numTicks, bool quoted); + void setSeqIndex(int msgIndex, int seqIndex); + void remove(int msgIndex); + void reset(); + void update(); + void processText(int msgIndex); + void delay(uint32 priorFrameTime, uint32 currentTime); + void setQuoted(int msgIndex, int numTicks, bool quoted); + + void initRandomMessages(int maxSimultaneousMessages, + const Common::Rect &bounds, int minYSpacing, int scrollRate, + int color, int duration, int quoteId, ...); + + /** + * Handles expiring any active random messages as necessary + */ + void randomServer(); + + /** + * Return the number of currently active random messages + */ + int checkRandom(); + + /** + * Handles generating new random messages + */ + bool generateRandom(int major, int minor); +}; + +class TextDisplay { +public: + bool _active; + int _expire; + int _spacing; + Common::Rect _bounds; + uint8 _color1; + uint8 _color2; + Font *_font; + Common::String _msg; + + TextDisplay(); +}; + +#define TEXT_DISPLAY_SIZE 40 + +class TextDisplayList : public Common::Array<TextDisplay> { +private: + MADSEngine *_vm; +public: + TextDisplayList(MADSEngine *vm); + + /** + * Expire a given text display entry + */ + void expire(int idx); + + int add(int xp, int yp, uint fontColor, int charSpacing, const Common::String &, Font *font); + + /** + * Reset all of the text display entries in the list to inactive + */ + void reset(); + + /** + * Draw any text in the list to the specified surface + * @param surface Surface + */ + void draw(MSurface *s); + + /** + * Determine dirty areas for active text areas + */ + void setDirtyAreas(); + + /** + * Secondary setup dirty areas for the text areas + */ + void setDirtyAreas2(); + + /** + * Deactivates any text display entries that are finished + */ + void cleanUp(); +}; + +} // End of namespace MADS + +#endif /* MADS_MESSAGES_H */ diff --git a/engines/mads/module.mk b/engines/mads/module.mk new file mode 100644 index 0000000000..61e810e215 --- /dev/null +++ b/engines/mads/module.mk @@ -0,0 +1,58 @@ +MODULE := engines/mads + +MODULE_OBJS := \ + dragonsphere/game_dragonsphere.o \ + dragonsphere/dragonsphere_scenes.o \ + phantom/game_phantom.o \ + phantom/phantom_scenes.o \ + nebular/dialogs_nebular.o \ + nebular/game_nebular.o \ + nebular/globals_nebular.o \ + nebular/sound_nebular.o \ + nebular/nebular_scenes.o \ + nebular/nebular_scenes1.o \ + nebular/nebular_scenes2.o \ + nebular/nebular_scenes3.o \ + nebular/nebular_scenes4.o \ + nebular/nebular_scenes5.o \ + nebular/nebular_scenes6.o \ + nebular/nebular_scenes7.o \ + nebular/nebular_scenes8.o \ + action.o \ + animation.o \ + assets.o \ + audio.o \ + compression.o \ + debugger.o \ + detection.o \ + dialogs.o \ + events.o \ + font.o \ + game.o \ + game_data.o \ + globals.o \ + hotspots.o \ + inventory.o \ + mads.o \ + messages.o \ + msurface.o \ + palette.o \ + player.o \ + rails.o \ + resources.o \ + scene.o \ + scene_data.o \ + screen.o \ + sequence.o \ + sound.o \ + sprites.o \ + staticres.o \ + user_interface.o + +# This module can be built as a plugin +ifeq ($(ENABLE_MADS), DYNAMIC_PLUGIN) +PLUGIN := 1 +endif + +# Include common rules +include $(srcdir)/rules.mk diff --git a/engines/mads/msurface.cpp b/engines/mads/msurface.cpp new file mode 100644 index 0000000000..839882a354 --- /dev/null +++ b/engines/mads/msurface.cpp @@ -0,0 +1,572 @@ +/* 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. + * + */ + +#include "engines/util.h" +#include "mads/compression.h" +#include "mads/screen.h" +#include "mads/mads.h" +#include "mads/msurface.h" +#include "mads/resources.h" +#include "mads/sprites.h" + +namespace MADS { + +MADSEngine *MSurface::_vm = nullptr; + +MSurface::MSurface() { + pixels = nullptr; + _freeFlag = false; +} + +MSurface::MSurface(int width, int height) { + pixels = nullptr; + _freeFlag = false; + setSize(width, height); +} + +MSurface::~MSurface() { + if (_freeFlag) + Graphics::Surface::free(); +} + +void MSurface::setSize(int width, int height) { + if (_freeFlag) + Graphics::Surface::free(); + Graphics::Surface::create(width, height, Graphics::PixelFormat::createFormatCLUT8()); + _freeFlag = true; +} + +void MSurface::setPixels(byte *pData, int horizSize, int vertSize) { + _freeFlag = false; + pixels = pData; + w = pitch = horizSize; + h = vertSize; + format.bytesPerPixel = 1; +} + +int MSurface::scaleValue(int value, int scale, int err) { + int scaled = 0; + while (value--) { + err -= scale; + while (err < 0) { + scaled++; + err += 100; + } + } + return scaled; +} + +void MSurface::drawSprite(const Common::Point &pt, SpriteInfo &info, const Common::Rect &clipRect) { + + enum { + kStatusSkip, + kStatusScale, + kStatusDraw + }; + + // NOTE: The current clipping code assumes that the top left corner of the clip + // rectangle is always 0, 0 + assert(clipRect.top == 0 && clipRect.left == 0); + + // TODO: Put err* and scaled* into SpriteInfo + int errX = info.hotX * info.scaleX % 100; + int errY = info.hotY * info.scaleY % 100; + int scaledWidth = scaleValue(info.width, info.scaleX, errX); + int scaledHeight = scaleValue(info.height, info.scaleY, errY); + + int x = pt.x, y = pt.y; + int clipX = 0, clipY = 0; + // Clip the sprite's width and height according to the clip rectangle's dimensions + // This clips the sprite to the bottom and right + if (x >= 0) { + scaledWidth = MIN<int>(x + scaledWidth, clipRect.right) - x; + } else { + clipX = x; + scaledWidth = x + scaledWidth; + } + if (y >= 0) { + scaledHeight = MIN<int>(y + scaledHeight, clipRect.bottom) - y; + } else { + clipY = y; + scaledHeight = y + scaledHeight; + } + + // Check if sprite is inside the screen. If it's not, there's no need to draw it + if (scaledWidth + x <= 0 || scaledHeight + y <= 0) // check left and top (in case x,y are negative) + return; + if (scaledWidth <= 0 || scaledHeight <= 0) // check right and bottom + return; + int heightAmt = scaledHeight; + + byte *src = info.sprite->getData(); + byte *dst = getBasePtr(x - info.hotX - clipX, y - info.hotY - clipY); + + int status = kStatusSkip; + byte *scaledLineBuf = new byte[scaledWidth]; + + while (heightAmt > 0) { + + if (status == kStatusSkip) { + // Skip line + errY -= info.scaleY; + if (errY < 0) + status = kStatusScale; + else + src += info.width; + } else { + + if (status == kStatusScale) { + // Scale current line + byte *lineDst = scaledLineBuf; + int curErrX = errX; + int width = scaledWidth; + byte *tempSrc = src; + int startX = clipX; + while (width > 0) { + byte pixel = *tempSrc++; + curErrX -= info.scaleX; + while (curErrX < 0) { + if (startX == 0) { + *lineDst++ = pixel; + width--; + } else { + startX++; + } + curErrX += 100; + } + } + src += info.width; + status = kStatusDraw; + } + + if (status == kStatusDraw && clipY == 0) { + // Draw previously scaled line + // TODO Implement different drawing types (depth, shadow etc.) + byte *tempDst = dst; + for (int lineX = 0; lineX < scaledWidth; lineX++) { + byte pixel = scaledLineBuf[lineX]; + + if (info.encoding & 0x80) { + + if (pixel == 0x80) { + pixel = 0; + } else { + byte destPixel = *tempDst; + byte r, g, b; + r = CLIP((info.palette[destPixel * 3] * pixel) >> 10, 0, 31); + g = CLIP((info.palette[destPixel * 3 + 1] * pixel) >> 10, 0, 31); + b = CLIP((info.palette[destPixel * 3 + 2] * pixel) >> 10, 0, 31); + pixel = info.inverseColorTable[(b << 10) | (g << 5) | r]; + } + } + + if (pixel) + *tempDst = pixel; + + tempDst++; + } + dst += pitch; + heightAmt--; + // TODO depth etc. + //depthAddress += Destination -> Width; + + errY += 100; + if (errY >= 0) + status = kStatusSkip; + } else if (status == kStatusDraw && clipY < 0) { + clipY++; + + errY += 100; + if (errY >= 0) + status = kStatusSkip; + } + + } + + } + + delete[] scaledLineBuf; + +} + +void MSurface::empty() { + Common::fill(getBasePtr(0, 0), getBasePtr(0, h), 0); +} + +void MSurface::copyFrom(MSurface *src, const Common::Rect &srcBounds, + const Common::Point &destPos, int transparentColor) { + // Validation of the rectangle and position + int destX = destPos.x, destY = destPos.y; + if ((destX >= w) || (destY >= h)) + return; + + Common::Rect copyRect = srcBounds; + if (destX < 0) { + copyRect.left += -destX; + destX = 0; + } else if (destX + copyRect.width() > w) { + copyRect.right -= destX + copyRect.width() - w; + } + if (destY < 0) { + copyRect.top += -destY; + destY = 0; + } else if (destY + copyRect.height() > h) { + copyRect.bottom -= destY + copyRect.height() - h; + } + + if (!copyRect.isValidRect()) + return; + + // Copy the specified area + + byte *data = src->getData(); + byte *srcPtr = data + (src->getWidth() * copyRect.top + copyRect.left); + byte *destPtr = (byte *)pixels + (destY * getWidth()) + destX; + + for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) { + if (transparentColor == -1) { + // No transparency, so copy line over + Common::copy(srcPtr, srcPtr + copyRect.width(), destPtr); + } else { + // Copy each byte one at a time checking for the transparency color + for (int xCtr = 0; xCtr < copyRect.width(); ++xCtr) + if (srcPtr[xCtr] != transparentColor) destPtr[xCtr] = srcPtr[xCtr]; + } + + srcPtr += src->getWidth(); + destPtr += getWidth(); + } +} + +void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth, + DepthSurface *depthSurface, int scale, int transparentColor) { + + int destX = destPos.x, destY = destPos.y; + if (scale == 100) { + // Copy the specified area + Common::Rect copyRect(0, 0, src->getWidth(), src->getHeight()); + + if (destX < 0) { + copyRect.left += -destX; + destX = 0; + } + else if (destX + copyRect.width() > w) { + copyRect.right -= destX + copyRect.width() - w; + } + if (destY < 0) { + copyRect.top += -destY; + destY = 0; + } + else if (destY + copyRect.height() > h) { + copyRect.bottom -= destY + copyRect.height() - h; + } + + if (!copyRect.isValidRect()) + return; + + byte *data = src->getData(); + byte *srcPtr = data + (src->getWidth() * copyRect.top + copyRect.left); + byte *destPtr = (byte *)pixels + (destY * pitch) + destX; + + // 100% scaling variation + for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) { + // Copy each byte one at a time checking against the depth + for (int xCtr = 0; xCtr < copyRect.width(); ++xCtr) { + int pixelDepth = depthSurface == nullptr ? 15 : + depthSurface->getDepth(Common::Point(destX + xCtr, destY + rowCtr)); + if ((depth <= pixelDepth) && (srcPtr[xCtr] != transparentColor)) + destPtr[xCtr] = srcPtr[xCtr]; + } + + srcPtr += src->getWidth(); + destPtr += getWidth(); + } + + return; + } + + // Start of draw logic for scaled sprites + const byte *srcPixelsP = src->getData(); + + int destRight = this->getWidth() - 1; + int destBottom = this->getHeight() - 1; + bool normalFrame = true; + int frameWidth = src->getWidth(); + int frameHeight = src->getHeight(); + + int highestDim = MAX(frameWidth, frameHeight); + bool lineDist[MADS_SCREEN_WIDTH]; + int distIndex = 0; + int distXCount = 0, distYCount = 0; + + int distCtr = 0; + do { + distCtr += scale; + if (distCtr < 100) { + lineDist[distIndex] = false; + } else { + lineDist[distIndex] = true; + distCtr -= 100; + + if (distIndex < frameWidth) + ++distXCount; + + if (distIndex < frameHeight) + ++distYCount; + } + } while (++distIndex < highestDim); + + destX -= distXCount / 2; + destY -= distYCount - 1; + + // Check x bounding area + int spriteLeft = 0; + int spriteWidth = distXCount; + int widthAmount = destX + distXCount - 1; + + if (destX < 0) { + spriteWidth += destX; + spriteLeft -= destX; + } + widthAmount -= destRight; + if (widthAmount > 0) + spriteWidth -= widthAmount; + + int spriteRight = spriteLeft + spriteWidth; + if (spriteWidth <= 0) + return; + if (!normalFrame) { + destX += distXCount - 1; + spriteLeft = -(distXCount - spriteRight); + spriteRight = (-spriteLeft + spriteWidth); + } + + // Check y bounding area + int spriteTop = 0; + int spriteHeight = distYCount; + int heightAmount = destY + distYCount - 1; + + if (destY < 0) { + spriteHeight += destY; + spriteTop -= destY; + } + heightAmount -= destBottom; + if (heightAmount > 0) + spriteHeight -= heightAmount; + int spriteBottom = spriteTop + spriteHeight; + + if (spriteHeight <= 0) + return; + + byte *destPixelsP = this->getBasePtr(destX + spriteLeft, destY + spriteTop); + + spriteLeft = (spriteLeft * (normalFrame ? 1 : -1)); + + // Loop through the lines of the sprite + for (int yp = 0, sprY = -1; yp < frameHeight; ++yp, srcPixelsP += src->pitch) { + if (!lineDist[yp]) + // Not a display line, so skip it + continue; + // Check whether the sprite line is in the display range + ++sprY; + if ((sprY >= spriteBottom) || (sprY < spriteTop)) + continue; + + // Found a line to display. Loop through the pixels + const byte *srcP = srcPixelsP; + byte *destP = destPixelsP; + + for (int xp = 0, sprX = 0; xp < frameWidth; ++xp, ++srcP) { + if (xp < spriteLeft) + // Not yet reached start of display area + continue; + if (!lineDist[sprX++]) + // Not a display pixel + continue; + + // Get depth of current output pixel in depth surface + Common::Point pt((destP - (byte *)this->pixels) % this->pitch, + (destP - (byte *)this->pixels) / this->pitch); + int pixelDepth = (depthSurface == nullptr) ? 15 : depthSurface->getDepth(pt); + + if ((*srcP != transparentColor) && (depth <= pixelDepth)) + *destP = *srcP; + + ++destP; + } + + // Move to the next destination line + destPixelsP += this->pitch; + } +} + +void MSurface::copyFromScaled(MSurface *src, const Common::Point &destPos, int depth, + DepthSurface *depthSurface, int scale, int transparentColor) { + int distXCount = 0, distYCount = 0; + int highestDim = MAX(src->w, src->h); + int accum = 0; + + for (int idx = 0; idx < highestDim; ++idx) { + accum += scale; + if (accum >= 100) { + accum -= 100; + if (idx < src->w) + ++distXCount; + if (idx < src->h) + ++distYCount; + } + } + + Common::Point newPos(destPos.x - distXCount / 2, destPos.y - distYCount); + copyFrom(src, src->getBounds(), newPos, transparentColor); +} + +void MSurface::scrollX(int xAmount) { + if (xAmount == 0) + return; + + byte buffer[80]; + int direction = (xAmount > 0) ? -1 : 1; + int xSize = ABS(xAmount); + assert(xSize <= 80); + + byte *srcP = getBasePtr(0, 0); + + for (int y = 0; y < this->h; ++y, srcP += pitch) { + if (direction < 0) { + // Copy area to be overwritten + Common::copy(srcP, srcP + xSize, &buffer[0]); + // Shift the remainder of the line over the given area + Common::copy(srcP + xSize, srcP + this->w, srcP); + // Move buffered area to the end of the line + Common::copy(&buffer[0], &buffer[xSize], srcP + this->w - xSize); + } else { + // Copy area to be overwritten + Common::copy_backward(srcP + this->w - xSize, srcP + this->w, &buffer[80]); + // Shift the remainder of the line over the given area + Common::copy_backward(srcP, srcP + this->w - xSize, srcP + this->w); + // Move buffered area to the start of the line + Common::copy_backward(&buffer[80 - xSize], &buffer[80], srcP + xSize); + } + } +} + +void MSurface::scrollY(int yAmount) { + if (yAmount == 0) + return; + + int direction = (yAmount > 0) ? 1 : -1; + int ySize = ABS(yAmount); + assert(ySize < (this->h / 2)); + assert(this->w == pitch); + + int blockSize = ySize * this->w; + byte *tempData = new byte[blockSize]; + byte *pixelsP = getBasePtr(0, 0); + + if (direction > 0) { + // Buffer the lines to be overwritten + byte *srcP = (byte *)getBasePtr(0, this->h - ySize); + Common::copy(srcP, srcP + (pitch * ySize), tempData); + // Vertically shift all the lines + Common::copy_backward(pixelsP, pixelsP + (pitch * (this->h - ySize)), + pixelsP + (pitch * this->h)); + // Transfer the buffered lines top the top of the screen + Common::copy(tempData, tempData + blockSize, pixelsP); + } else { + // Buffer the lines to be overwritten + Common::copy(pixelsP, pixelsP + (pitch * ySize), tempData); + // Vertically shift all the lines + Common::copy(pixelsP + (pitch * ySize), pixelsP + (pitch * this->h), pixelsP); + // Transfer the buffered lines to the bottom of the screen + Common::copy(tempData, tempData + blockSize, pixelsP + (pitch * (this->h - ySize))); + } + + delete[] tempData; +} + + +void MSurface::translate(Common::Array<RGB6> &palette) { + for (int y = 0; y < this->h; ++y) { + byte *pDest = getBasePtr(0, y); + + for (int x = 0; x < this->w; ++x, ++pDest) { + if (*pDest < 255) // scene 752 has some palette indices of 255 + *pDest = palette[*pDest]._palIndex; + } + } +} + +void MSurface::translate(byte map[PALETTE_COUNT]) { + for (int y = 0; y < this->h; ++y) { + byte *pDest = getBasePtr(0, y); + + for (int x = 0; x < this->w; ++x, ++pDest) { + *pDest = map[*pDest]; + } + } +} + +MSurface *MSurface::flipHorizontal() const { + MSurface *dest = new MSurface(this->w, this->h); + + for (int y = 0; y < this->h; ++y) { + const byte *srcP = getBasePtr(this->w - 1, y); + byte *destP = dest->getBasePtr(0, y); + + for (int x = 0; x < this->w; ++x) + *destP++ = *srcP--; + } + + return dest; +} + +/*------------------------------------------------------------------------*/ + +int DepthSurface::getDepth(const Common::Point &pt) { + if (_vm->_game->_scene._sceneInfo->_depthStyle == 2) { + int bits = (3 - (pt.x % 4)) * 2; + byte v = *getBasePtr(pt.x >> 2, pt.y); + return v >> bits; + } else { + if (pt.x < 0 || pt.y < 0 || pt.x >= this->w || pt.y >= this->h) + return 0; + + return *getBasePtr(pt.x, pt.y) & 0xF; + } +} + +int DepthSurface::getDepthHighBit(const Common::Point &pt) { + if (_vm->_game->_scene._sceneInfo->_depthStyle == 2) { + int bits = (3 - (pt.x % 4)) * 2; + byte v = *getBasePtr(pt.x >> 2, pt.y); + return (v >> bits) & 2; + } else { + if (pt.x < 0 || pt.y < 0 || pt.x >= this->w || pt.y >= this->h) + return 0; + + return *getBasePtr(pt.x, pt.y) & 0x80; + } +} + + +} // End of namespace MADS diff --git a/engines/mads/msurface.h b/engines/mads/msurface.h new file mode 100644 index 0000000000..985a097d4a --- /dev/null +++ b/engines/mads/msurface.h @@ -0,0 +1,255 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 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. + * + */ + +#ifndef MADS_MSURFACE_H +#define MADS_MSURFACE_H + +#include "common/scummsys.h" +#include "common/rect.h" +#include "graphics/surface.h" +#include "mads/palette.h" + +namespace MADS { + +class MADSEngine; +class MSprite; +class DepthSurface; + +/** + * Basic sprite information + */ +struct SpriteInfo { + MSprite *sprite; + int hotX, hotY; + int width, height; + int scaleX, scaleY; + uint8 encoding; + byte *inverseColorTable; + byte *palette; +}; + +/* + * MADS graphics surface + */ +class MSurface : public Graphics::Surface { +private: + bool _freeFlag; +protected: + static MADSEngine *_vm; +public: + /** + * Sets the engine refrence used all surfaces + */ + static void setVm(MADSEngine *vm) { _vm = vm; } + + /** + * Helper method for calculating new dimensions when scaling a sprite + */ + static int scaleValue(int value, int scale, int err); +public: + /** + * Basic constructor + */ + MSurface(); + + /** + * Constructor for a surface with fixed dimensions + */ + MSurface(int width, int height); + + /** + * Destructor + */ + virtual ~MSurface(); + + /** + * Reinitializes a surface to have a given set of dimensions + */ + void setSize(int width, int height); + + /** + * Sets the pixels the surface is associated with + * @remarks The surface will not free the data block + */ + void setPixels(byte *pData, int horizSize, int vertSize); + + /** + * Draws an arbitrary line on the screen using a specified color + * @param startPos Starting position + * @param endPos Ending position + * @param color Color to use + */ + void line(const Common::Point &startPos, const Common::Point &endPos, byte color); + + /** + * Draws a sprite + * @param pt Position to draw sprite at + * @param info General sprite details + * @param clipRect Clipping rectangle to constrain sprite drawing within + */ + void drawSprite(const Common::Point &pt, SpriteInfo &info, const Common::Rect &clipRect); + + /** + * Returns the width of the surface + */ + int getWidth() const { return w; } + + /** + * Returns the height of the surface + */ + int getHeight() const { return h; } + + /** + * Returns the size of the surface as a Rect + */ + Common::Rect getBounds() const { + return Common::Rect(0, 0, w, h); + } + + /** + * Returns a pointer to the surface data + */ + byte *getData() { return (byte *)Graphics::Surface::getPixels(); } + + /** + * Returns a pointer to a given position within the surface + */ + byte *getBasePtr(int x, int y) { return (byte *)Graphics::Surface::getBasePtr(x, y); } + + /** + * Returns a pointer to a given position within the surface + */ + const byte *getBasePtr(int x, int y) const { return (const byte *)Graphics::Surface::getBasePtr(x, y); } + + /** + * Clears the surface + */ + void empty(); + + /** + * Copys a sub-section of another surface into the current one. + * @param src Source surface + * @param srcBounds Area of source surface to copy + * @param destPos Destination position to draw in current surface + * @param transparentColor Transparency palette index + */ + void copyFrom(MSurface *src, const Common::Rect &srcBounds, const Common::Point &destPos, + int transparentColor = -1); + + /** + * Copys a sub-section of another surface into the current one. + * @param src Source surface + * @param destPos Destination position to draw in current surface + * @param depth Depth of sprite + * @param depthSurface Depth surface to use with sprite depth + * @param scale Scale for image + * @param transparentColor Transparency palette index + */ + void copyFrom(MSurface *src, const Common::Point &destPos, int depth, DepthSurface *depthSurface, + int scale, int transparentColor = -1); + + /** + * Copys a sub-section of another surface into the current one, taking into + * account variation in the destination copy position based on item size + * and scaling. + * @param src Source surface + * @param destPos Destination position to draw in current surface + * @param depth Depth of sprite + * @param depthSurface Depth surface to use with sprite depth + * @param scale Scale for image + * @param transparentColor Transparency palette index + */ + void copyFromScaled(MSurface *src, const Common::Point &destPos, int depth, DepthSurface *depthSurface, + int scale, int transparentColor = -1); + + /** + * Copies the surface to a given destination surface + */ + void copyTo(MSurface *dest, int transparentColor = -1) { + dest->copyFrom(this, Common::Rect(w, h), Common::Point(), transparentColor); + } + + /** + * Copies the surface to a given destination surface + */ + void copyTo(MSurface *dest, const Common::Point &pt, int transparentColor = -1) { + dest->copyFrom(this, Common::Rect(w, h), pt, transparentColor); + } + + /** + * Copies the surface to a given destination surface + */ + void copyTo(MSurface *dest, const Common::Rect &srcBounds, const Common::Point &destPos, + int transparentColor = -1) { + dest->copyFrom(this, srcBounds, destPos, transparentColor); + } + + /** + * Scroll the screen horizontally by a given amount + * @param xAmount Horizontal amount + */ + void scrollX(int xAmount); + + /** + * Scroll the screen vertically by a given amount + * @param yAmount Vertical amount + */ + void scrollY(int yAmount); + + /** + * Translates the pixels of an image used the passed palette with RGB mapping + */ + void translate(Common::Array<RGB6> &palette); + + /** + * Translates the pixels of an image used the passed palette with RGB mapping + */ + void translate(byte map[PALETTE_COUNT]); + + /** + * Create a new surface which is a flipped horizontal copy of the current one + */ + MSurface *flipHorizontal() const; +}; + +class DepthSurface : public MSurface { +private: + MADSEngine *_vm; +public: + /** + * Constructor + */ + DepthSurface(MADSEngine *vm) : _vm(vm) {} + + /** + * Returns the depth at a given position + */ + int getDepth(const Common::Point &pt); + + /** + */ + int getDepthHighBit(const Common::Point &pt); +}; + +} // End of namespace MADS + +#endif /* MADS_MSURFACE_H */ diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp new file mode 100644 index 0000000000..d8a85d472d --- /dev/null +++ b/engines/mads/nebular/dialogs_nebular.cpp @@ -0,0 +1,698 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "common/config-manager.h" +#include "common/util.h" +#include "mads/mads.h" +#include "mads/screen.h" +#include "mads/msurface.h" +#include "mads/staticres.h" +#include "mads/nebular/dialogs_nebular.h" + +namespace MADS { + +namespace Nebular { + +bool DialogsNebular::show(int messageId, int objectId) { + MADSAction &action = _vm->_game->_scene._action; + Common::StringArray msg = _vm->_game->getMessage(messageId); + Common::String title; + Common::String commandText; + Common::String valStr; + Common::String dialogText; + bool result = true; + bool centerFlag = false; + bool underlineFlag = false; + bool commandFlag = false; + bool crFlag = false; + TextDialog *dialog = nullptr; + _dialogWidth = 17; + _capitalizationMode = kUppercase; + + // Loop through the lines of the returned text + for (uint idx = 0; idx < msg.size(); ++idx) { + Common::String srcLine = msg[idx]; + const char *srcP = srcLine.c_str(); + + // Loop through the text of the line + while (srcP < srcLine.c_str() + srcLine.size()) { + if (*srcP == '[') { + // Starting a command + commandText = ""; + commandFlag = true; + } else if (*srcP == ']') { + // Ending a command + if (commandFlag) { + if (commandCheck("CENTER", valStr, commandText)) { + centerFlag = true; + } else if (commandCheck("TITLE", valStr, commandText)) { + centerFlag = true; + underlineFlag = true; + crFlag = true; + int v = atoi(valStr.c_str()); + if (v != 0) + _dialogWidth = v; + } else if (commandCheck("CR", valStr, commandText)) { + if (centerFlag) { + crFlag = true; + } else { + if (objectId == -1) { + dialog = new TextDialog(_vm, FONT_INTERFACE, _defaultPosition, _dialogWidth); + } else { + dialog = new PictureDialog(_vm, _defaultPosition, _dialogWidth, objectId); + } + dialog->wordWrap(dialogText); + dialog->incNumLines(); + } + } else if (commandCheck("ASK", valStr, commandText)) { + dialog->addInput(); + } else if (commandCheck("VERB", valStr, commandText)) { + dialogText += getVocab(action._activeAction._verbId); + } else if (commandCheck("INDEX", valStr, commandText)) { + int idxLocal = atoi(valStr.c_str()); + if (_indexList[idxLocal]) + dialogText += getVocab(_indexList[idxLocal]); + } else if (commandCheck("NUMBER", valStr, commandText)) { + int idxLocal = atoi(valStr.c_str()); + dialogText += Common::String::format("%.4d", _indexList[idxLocal]); + } else if (commandCheck("NOUN1", valStr, commandText)) { + if (!textNoun(dialogText, 1, valStr)) + dialogText += getVocab(action._activeAction._objectNameId); + } else if (commandCheck("NOUN2", valStr, commandText)) { + if (!textNoun(dialogText, 2, valStr)) + dialogText += getVocab(action._activeAction._indirectObjectId); + } else if (commandCheck("PREP", valStr, commandText)) { + dialogText += kArticleList[action._savedFields._articleNumber]; + } else if (commandCheck("SENTENCE", valStr, commandText)) { + dialogText += action._sentence; + } else if (commandCheck("WIDTH", valStr, commandText)) { + _dialogWidth = atoi(valStr.c_str()); + } else if (commandCheck("BAR", valStr, commandText)) { + dialog->addBarLine(); + } else if (commandCheck("UNDER", valStr, commandText)) { + underlineFlag = true; + } else if (commandCheck("DOWN", valStr, commandText)) { + dialog->downPixelLine(); + } else if (commandCheck("TAB", valStr, commandText)) { + int xp = atoi(valStr.c_str()); + dialog->setLineXp(xp); + } + } + + commandFlag = false; + } else if (commandFlag) { + // Add the next character to the command + commandText += *srcP; + } else { + // Add to the text to be displayed in the dialog + dialogText += *srcP; + } + + ++srcP; + } + + if (!dialog) { + if (objectId == -1) { + dialog = new TextDialog(_vm, FONT_INTERFACE, _defaultPosition, _dialogWidth); + } else { + dialog = new PictureDialog(_vm, _defaultPosition, _dialogWidth, objectId); + } + } + + if (centerFlag) { + dialog->addLine(dialogText, underlineFlag); + if (crFlag) + dialog->incNumLines(); + } else { + dialog->wordWrap(dialogText); + } + + // Reset line processing flags in preparation for next line + dialogText = ""; + commandFlag = false; + underlineFlag = false; + centerFlag = false; + crFlag = false; + } + + if (!centerFlag) + dialog->incNumLines(); + + // Show the dialog + _vm->_events->setCursor(CURSOR_ARROW); + dialog->show(); + + delete dialog; + return result; +} + +void DialogsNebular::showItem(int objectId, int messageId, int speech) { + // MADS engine doesn't currently support speech + assert(!speech); + + show(messageId, objectId); +} + +Common::String DialogsNebular::getVocab(int vocabId) { + assert(vocabId > 0); + + Common::String vocab = _vm->_game->_scene.getVocab(vocabId); + + switch (_capitalizationMode) { + case kUppercase: + vocab.toUppercase(); + break; + case kLowercase: + vocab.toLowercase(); + break; + case kUpperAndLower: + vocab.toLowercase(); + vocab.setChar(toupper(vocab[0]), 0); + default: + break; + } + + return vocab; +} + +bool DialogsNebular::textNoun(Common::String &dest, int nounId, const Common::String &source) { + // Ensure the destination has parameter specifications + if (!source.hasPrefix(":")) + return false; + + // Extract the first (singular) result value + Common::String param1 = Common::String(source.c_str() + 1); + Common::String param2; + const char *sepChar = strchr(source.c_str() + 1, ':'); + if (sepChar) { + param1 = Common::String(source.c_str() + 1, sepChar); + + // Get the second, plural form + param2 = Common::String(sepChar + 1); + } + + // Get the vocab to use + MADSAction &action = _vm->_game->_scene._action; + Common::String vocab = _vm->_dialogs->getVocab(action._activeAction._verbId); + Common::String *str; + + if (vocab.hasSuffix("s") || vocab.hasSuffix("S")) { + str = ¶m2; + } else { + str = ¶m1; + + if (param1 == "a ") { + switch (toupper(vocab[0])) { + case 'A': + case 'E': + case 'I': + case 'O': + case 'U': + param1 = "an "; + break; + default: + break; + } + } + } + + dest += *str; + return true; +} + +bool DialogsNebular::commandCheck(const char *idStr, Common::String &valStr, + const Common::String &command) { + uint idLen = strlen(idStr); + + valStr = (command.size() <= idLen) ? "" : Common::String(command.c_str() + idLen); + + // Check whether the command starts with the given Id + int result = scumm_strnicmp(idStr, command.c_str(), idLen) == 0; + if (!result) + return false; + + // It does, so set the command case mode + if (Common::isUpper(command[0]) && Common::isUpper(command[1])) { + _capitalizationMode = kUppercase; + } else if (Common::isUpper(command[0])) { + _capitalizationMode = kUpperAndLower; + } else { + _capitalizationMode = kLowercase; + } + + return true; +} + +void DialogsNebular::showDialog() { + switch (_pendingDialog) { + case DIALOG_GAME_MENU: + //GameMenuDialog::show(); + break; + default: + break; + } +} + +/*------------------------------------------------------------------------*/ + +CopyProtectionDialog::CopyProtectionDialog(MADSEngine *vm, bool priorAnswerWrong) : +TextDialog(vm, FONT_INTERFACE, Common::Point(-1, -1), 32) { + getHogAnusEntry(_hogEntry); + + if (priorAnswerWrong) { + addLine("ANSWER INCORRECT!", true); + wordWrap("\n"); + addLine("(But we'll give you another chance!)"); + } + else { + addLine("REX NEBULAR version 8.43", true); + wordWrap("\n"); + addLine("(Copy Protection, for your convenience)"); + } + wordWrap("\n"); + + wordWrap("Now comes the part that everybody hates. But if we don't"); + wordWrap("do this, nasty rodent-like people will pirate this game"); + wordWrap("and a whole generation of talented designers, programmers,"); + wordWrap("artists, and playtesters will go hungry, and will wander"); + wordWrap("aimlessly through the land at night searching for peace."); + wordWrap("So let's grit our teeth and get it over with. Just get"); + + Common::String line = "out your copy of "; + line += _hogEntry._bookId == 103 ? "the GAME MANUAL" : "REX'S LOGBOOK"; + line += ". See! That was easy. "; + wordWrap(line); + + line = Common::String::format("Next, just turn to page %d. On line %d, find word number %d, ", + _hogEntry._pageNum, _hogEntry._lineNum, _hogEntry._wordNum); + wordWrap(line); + + wordWrap("and type it on the line below (we',27h,'ve even given you"); + wordWrap("first letter as a hint). As soon as you do that, we can get"); + wordWrap("right into this really COOL adventure game!\n"); + wordWrap("\n"); + wordWrap(" "); + addInput(); + wordWrap("\n"); +} + +void CopyProtectionDialog::show() { + draw(); + _vm->_events->showCursor(); + + // TODO: Replace with text input + while (!_vm->shouldQuit() && !_vm->_events->isKeyPressed() && + !_vm->_events->_mouseClicked) { + _vm->_events->delay(1); + } + + _vm->_events->_pendingKeys.clear(); +} + +bool CopyProtectionDialog::getHogAnusEntry(HOGANUS &entry) { + File f; + f.open("*HOGANUS.DAT"); + + // Read in the total number of entries, and randomly pick an entry to use + int numEntries = f.readUint16LE(); + int entryIndex = _vm->getRandomNumber(1, numEntries); + + // Read in the encrypted entry + f.seek(28 * entryIndex + 2); + byte entryData[28]; + f.read(entryData, 28); + + // Decrypt it + for (int i = 0; i < 28; ++i) + entryData[i] = ~entryData[i]; + + // Fill out the fields + entry._bookId = entryData[0]; + entry._pageNum = READ_LE_UINT16(&entryData[2]); + entry._lineNum = READ_LE_UINT16(&entryData[4]); + entry._wordNum = READ_LE_UINT16(&entryData[6]); + entry._word = Common::String((char *)&entryData[8]); + + f.close(); + return true; +} + +/*------------------------------------------------------------------------*/ + +PictureDialog::PictureDialog(MADSEngine *vm, const Common::Point &pos, + int maxChars, int objectId) : + TextDialog(vm, FONT_INTERFACE, pos, maxChars), _objectId(objectId) { + // Turn off cycling if active + Scene &scene = _vm->_game->_scene; + _cyclingActive = scene._cyclingActive; + scene._cyclingActive = false; +} + +PictureDialog::~PictureDialog() { + // Restore cycling flag + Scene &scene = _vm->_game->_scene; + scene._cyclingActive = _cyclingActive; +} + +void PictureDialog::save() { + Palette &palette = *_vm->_palette; + byte map[PALETTE_COUNT]; + + // Save the entire screen + _savedSurface = new MSurface(MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT); + _vm->_screen.copyTo(_savedSurface); + + // Save palette information + Common::copy(&palette._mainPalette[0], &palette._mainPalette[PALETTE_SIZE], &_palette[0]); + Common::copy(&palette._palFlags[0], &palette._palFlags[PALETTE_COUNT], &_palFlags[0]); + _rgbList.copy(palette._rgbList); + + // Set up palette allocation + Common::fill(&palette._colorFlags[0], &palette._colorFlags[3], true); + + uint32 *palFlagP = &palette._palFlags[0]; + for (int idx = 0; idx < PALETTE_COUNT; ++idx, ++palFlagP) { + if (idx < PALETTE_RESERVED_LOW_COUNT || + idx >= (PALETTE_COUNT - PALETTE_RESERVED_HIGH_COUNT - 10)) { + *palFlagP = 1; + map[idx] = idx; + } else { + *palFlagP = 0; + } + } + + // Reset the flag list + palette._rgbList.reset(); + + // Fade the screen to grey + int numColors = PALETTE_COUNT - PALETTE_RESERVED_LOW_COUNT - PALETTE_RESERVED_HIGH_COUNT; + palette.fadeOut(palette._mainPalette, &map[PALETTE_RESERVED_LOW_COUNT], + PALETTE_RESERVED_LOW_COUNT, numColors, 248, 8, 1, 16); + + // Remap the greyed out screen to use the small greyscale range + // at the top end of the palette + _vm->_screen.translate(map); + + // Load the inventory picture + Common::String setName = Common::String::format("*OB%.3d.SS", _objectId); + SpriteAsset *asset = new SpriteAsset(_vm, setName, 0x8000); + palette.setFullPalette(palette._mainPalette); + + // Get the inventory frame, and adjust the dialog position to allow for it + MSprite *frame = asset->getFrame(0); + _position.y = frame->h + 12; + + // Draw the inventory picture + frame->copyTo(&_vm->_screen, Common::Point(160 - frame->w / 2, 6), + frame->getTransparencyIndex()); + _vm->_screen.copyRectToScreen(_vm->_screen.getBounds()); + + // Adjust the dialog colors to use + TEXTDIALOG_CONTENT1 -= 10; + TEXTDIALOG_CONTENT2 -= 10; + TEXTDIALOG_EDGE -= 10; + TEXTDIALOG_BACKGROUND -= 10; + TEXTDIALOG_FC -= 10; + TEXTDIALOG_FD -= 10; + TEXTDIALOG_FE -= 10; +} + +void PictureDialog::restore() { + if (_savedSurface) { + _savedSurface->copyTo(&_vm->_screen); + delete _savedSurface; + _savedSurface = nullptr; + + _vm->_screen.copyRectToScreen(_vm->_screen.getBounds()); + + // Restore palette information + Palette &palette = *_vm->_palette; + Common::copy(&_palette[0], &_palette[PALETTE_SIZE], &palette._mainPalette[0]); + _vm->_palette->setFullPalette(palette._mainPalette); + Common::copy(&_palFlags[0], &_palFlags[PALETTE_COUNT], &palette._palFlags[0]); + palette._rgbList.copy(_rgbList); + + _vm->_dialogs->_defaultPosition.y = -1; + } +} + +/*------------------------------------------------------------------------*/ + +ScreenDialog::DialogLine::DialogLine() { + _state = 0; + _textDisplayIndex = -1; + _font = nullptr; + _widthAdjust = 0; +} + +ScreenDialog::DialogLine::DialogLine(const Common::String &s) { + _state = 0; + _textDisplayIndex = -1; + _font = nullptr; + _widthAdjust = -1; + _msg = s; +} + +/*------------------------------------------------------------------------*/ + +ScreenDialog::ScreenDialog(MADSEngine *vm) : _vm(vm), + _savedSurface(MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT) { + Game &game = *_vm->_game; + Scene &scene = game._scene; + + _v1 = 0; + _selectedLine = 0; + _dirFlag = false; + _textLineCount = 0; + _screenId = 920; + + game.loadQuoteSet(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 0); + game._kernelMode = KERNEL_ROOM_PRELOAD; + _vm->_events->waitCursor(); + scene.clearVocab(); + scene._dynamicHotspots.clear(); + _vm->_dialogs->_defaultPosition = Common::Point(-1, -1); + + bool palFlag = false; + int nextSceneId = scene._nextSceneId; + int currentSceneId = scene._currentSceneId; + int priorSceneId = scene._priorSceneId; + + if (_vm->_dialogs->_pendingDialog == DIALOG_DIFFICULTY) { + palFlag = true; + } else { + _vm->_palette->initPalette(); + } + scene.loadScene(_screenId, game._aaName, palFlag); + + scene._priorSceneId = priorSceneId; + scene._currentSceneId = currentSceneId; + scene._nextSceneId = nextSceneId; + _vm->_screen._offset.y = 22; + _vm->_sound->pauseNewCommands(); + _vm->_events->initVars(); + game._kernelMode = KERNEL_ROOM_INIT; + + SpriteAsset *menuSprites = new SpriteAsset(_vm, "*MENU", 0); + _menuSpritesIndex = scene._sprites.add(menuSprites); + + byte pal[768]; + if (_vm->_screenFade) { + Common::fill(&pal[0], &pal[PALETTE_SIZE], 0); + _vm->_palette->setFullPalette(pal); + } else { + _vm->_palette->getFullPalette(pal); + _vm->_palette->fadeOut(pal, nullptr, 0, PALETTE_COUNT, 0, 1, 1, 16); + } + + _vm->_screen.copyTo(&_savedSurface); + /* + _vm->_screen.hLine(0, 0, MADS_SCREEN_WIDTH, 2); + _vm->_screen.copyRectToScreen(Common::Rect(0, _vm->_screen._offset.y, + MADS_SCREEN_WIDTH, _vm->_screen._offset.y + 1)); + _vm->_screen.copyRectToScreen(Common::Rect(0, _vm->_screen._offset.y + 157, + MADS_SCREEN_WIDTH, _vm->_screen._offset.y + 157)); + */ + + game._fx = _vm->_screenFade == SCREEN_FADE_SMOOTH ? + kCenterVertTransition : kTransitionFadeIn; + game._trigger = 0; + _vm->_events->setCursor(CURSOR_ARROW); + + _vm->_palette->setEntry(10, 0, 63, 0); + _vm->_palette->setEntry(11, 0, 45, 0); + _vm->_palette->setEntry(12, 63, 63, 0); + _vm->_palette->setEntry(13, 45, 45, 0); + _vm->_palette->setEntry(14, 63, 63, 63); + _vm->_palette->setEntry(15, 45, 45, 45); + + _lineIndex = -1; +} + +void ScreenDialog::clearLines() { + Scene &scene = _vm->_game->_scene; + _lines.clear(); + scene._spriteSlots.fullRefresh(true); +} + +void ScreenDialog::addQuote(int id1, int id2, DialogTextAlign align, + const Common::Point &pt, Font *font) { + Common::String msg = _vm->_game->getQuote(id1); + + if (id2 > 0) { + msg += " "; + msg += _vm->_game->getQuote(id2); + } + + addLine(msg, align, pt, font); +} + +void ScreenDialog::addLine(const Common::String &msg, DialogTextAlign align, + const Common::Point &pt, Font *font) { + Scene &scene = _vm->_game->_scene; + DialogLine *line; + + if (_lineIndex < (int)_lines.size()) { + if (_lines.size() >= 20) { + ++_lineIndex; + return; + } + + _lines.push_back(msg); + line = &_lines[_lines.size() - 1]; + } else { + line = &_lines[_lineIndex]; + if (msg.compareToIgnoreCase(msg)) { + ++_lineIndex; + return; + } + + if (line->_textDisplayIndex >= 0) { + TextDisplay &textDisplay = scene._textDisplay[line->_textDisplayIndex]; + if (textDisplay._active) { + textDisplay._expire = -1; + if (_textLineCount < 20) { + textDisplay._msg = msg; + ++_textLineCount; + } + } + } + } + + line->_font = font; + line->_state = 0; + line->_pos = pt; + line->_widthAdjust = -1; + line->_textDisplayIndex = -1; + + int xOffset; + switch (align) { + case ALIGN_CENTER: + xOffset = (MADS_SCREEN_WIDTH / 2) - font->getWidth(msg, -1) / 2; + line->_pos.x += xOffset; + break; + + case ALIGN_AT_CENTER: { + const char *msgP = msg.c_str(); + const char *ch = strchr(msgP, '@'); + if (ch) { + xOffset = (MADS_SCREEN_WIDTH / 2) - font->getWidth( + Common::String(msgP, ch), line->_widthAdjust); + line->_pos.x += xOffset; + } + break; + } + + case ALIGN_RIGHT: + xOffset = font->getWidth(msg, -1); + line->_pos.x -= xOffset; + break; + + default: + break; + } + + ++_lineIndex; +} + +void ScreenDialog::initVars() { + _v1 = -1; + _selectedLine = -1; + _lineIndex = 0; + _textLineCount = 0; +} + +void ScreenDialog::chooseBackground() { + switch (_vm->_game->_currentSectionNumber) { + case 1: + case 2: + _screenId = 921; + break; + case 3: + case 4: + _screenId = 922; + break; + case 5: + case 6: + case 7: + _screenId = 923; + break; + case 8: + _screenId = 924; + break; + default: + _screenId = 920; + break; + } +} + +void ScreenDialog::setFrame(int frameNumber, int depth) { + Scene &scene = _vm->_game->_scene; + SpriteSlot &spriteSlot = scene._spriteSlots[scene._spriteSlots.add()]; + spriteSlot._flags = IMG_UPDATE; + spriteSlot._seqIndex = 1; + spriteSlot._spritesIndex = _menuSpritesIndex; + spriteSlot._frameNumber = frameNumber; + +} + +/*------------------------------------------------------------------------*/ + +GameMenuDialog::GameMenuDialog(MADSEngine *vm) : ScreenDialog(vm) { + clearLines(); + setFrame(1, 2); +} + +void GameMenuDialog::addLines() { + initVars(); + Font *font = _vm->_font->getFont(FONT_CONVERSATION); + int top = 78 - (font->getHeight() + 2) * 12; + addQuote(10, 0, ALIGN_CENTER, Common::Point(0, top), font); + // TODO +} + +} // End of namespace Nebular + +} // End of namespace MADS diff --git a/engines/mads/nebular/dialogs_nebular.h b/engines/mads/nebular/dialogs_nebular.h new file mode 100644 index 0000000000..0554becea4 --- /dev/null +++ b/engines/mads/nebular/dialogs_nebular.h @@ -0,0 +1,179 @@ +/* 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. + * + */ + +#ifndef MADS_DIALOGS_NEBULAR_H +#define MADS_DIALOGS_NEBULAR_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/dialogs.h" + +namespace MADS { + +namespace Nebular { + +enum CapitalizationMode { kUppercase = 0, kLowercase = 1, kUpperAndLower = 2 }; + +class DialogsNebular : public Dialogs { + friend class Dialogs; +private: + int _dialogWidth; + CapitalizationMode _capitalizationMode; + + DialogsNebular(MADSEngine *vm): Dialogs(vm), _capitalizationMode(kUppercase) {} + + virtual Common::String getVocab(int vocabId); + + bool textNoun(Common::String &dest, int nounId, const Common::String &source); + + bool commandCheck(const char *idStr, Common::String &valStr, const Common::String &command); +public: + virtual void showDialog(); + + virtual void showItem(int objectId, int messageId, int speech = -1); + + virtual bool show(int messageId, int objectId = -1); +}; + +struct HOGANUS { + int _bookId; + int _pageNum; + int _lineNum; + int _wordNum; + Common::String _word; +}; + +class CopyProtectionDialog : public TextDialog { +private: + HOGANUS _hogEntry; + + /** + * Get a random copy protection entry from the HOGANUS resource + */ + bool getHogAnusEntry(HOGANUS &entry); +public: + /** + * Constructor + */ + CopyProtectionDialog(MADSEngine *vm, bool priorAnswerWrong); + + /** + * Show the dialog + */ + virtual void show(); +}; + +class PictureDialog : public TextDialog { +private: + int _objectId; + bool _cyclingActive; + byte _palette[PALETTE_SIZE]; + uint32 _palFlags[PALETTE_COUNT]; + RGBList _rgbList; +protected: + virtual void save(); + + virtual void restore(); +public: + PictureDialog(MADSEngine *vm, const Common::Point &pos, int maxChars, int objectId); + + virtual ~PictureDialog(); +}; + +enum DialogTextAlign { ALIGN_CENTER = -1, ALIGN_AT_CENTER = -2, ALIGN_RIGHT = -3 }; + +class ScreenDialog { + struct DialogLine { + int _state; + Common::Point _pos; + int _textDisplayIndex; + Common::String _msg; + Font *_font; + int _widthAdjust; + + DialogLine(); + DialogLine(const Common::String &s); + }; +protected: + MADSEngine *_vm; + MSurface _savedSurface; + Common::Array<DialogLine> _lines; + int _v1; + int _selectedLine; + bool _dirFlag; + int _screenId; + int _menuSpritesIndex; + int _lineIndex; + int _textLineCount; + + /** + * Reset the lines list for the dialog + */ + void clearLines(); + + /** + * Add a quote to the lines list + */ + void addQuote(int id1, int id2, DialogTextAlign align, const Common::Point &pt, Font *font); + + /** + * Adds a line to the lines list + */ + void addLine(const Common::String &msg, DialogTextAlign align, const Common::Point &pt, Font *font); + + /** + * Initializes variables + */ + void initVars(); + + /** + * Sets the display for the screen background behind the dialog + */ + void setFrame(int frameNumber, int depth); + + /** + * Choose the background to display for the dialog + */ + void chooseBackground(); +public: + /** + * Constructor + */ + ScreenDialog(MADSEngine *vm); +}; + +class GameMenuDialog : public ScreenDialog { +private: + /** + * Add the lines for the Game Menu dialog + */ + void addLines(); +public: + GameMenuDialog(MADSEngine *vm); + +}; + +} // End of namespace Nebular + +} // End of namespace MADS + +#endif /* MADS_DIALOGS_NEBULAR_H */ diff --git a/engines/mads/nebular/game_nebular.cpp b/engines/mads/nebular/game_nebular.cpp new file mode 100644 index 0000000000..e5a59a0050 --- /dev/null +++ b/engines/mads/nebular/game_nebular.cpp @@ -0,0 +1,819 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "common/config-manager.h" +#include "mads/mads.h" +#include "mads/game.h" +#include "mads/screen.h" +#include "mads/msurface.h" +#include "mads/nebular/game_nebular.h" +#include "mads/nebular/dialogs_nebular.h" +#include "mads/nebular/globals_nebular.h" +#include "mads/nebular/nebular_scenes.h" + +namespace MADS { + +namespace Nebular { + +GameNebular::GameNebular(MADSEngine *vm) + : Game(vm) { + _surface = new MSurface(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT); + _storyMode = STORYMODE_NAUGHTY; + _difficulty = DIFFICULTY_EASY; +} + +ProtectionResult GameNebular::checkCopyProtection() { + /* + // DEBUG: Flag copy protection failure + _globals[kCopyProtectFailed] = -1; + + if (!ConfMan.getBool("copy_protection")) + return true; + + * DEBUG: Disabled for now + CopyProtectionDialog *dlg = new CopyProtectionDialog(_vm, false); + dlg->show(); + delete dlg; + */ + + // DEBUG: Return that copy protection failed + return PROTECTION_SUCCEED; +} + +void GameNebular::initializeGlobals() { + int count, count2; + int bad; + + _globals.reset(); + _globals[kTalkInanimateCount] = 8; + + /* Section #1 variables */ + _globals[kNeedToStandUp] = true; + _globals[kTurkeyExploded] = false; + _globals[kMedicineCabinetOpen] = false; + _globals[kMedicineCabinetVirgin] = true; + _globals[kWatchedViewScreen] = false; + _globals[kHoovicAlive] = true; + _globals[kWaterInAPuddle] = false; + + _globals[kFishIn105] = true; + _globals[kFishIn107] = true; + _globals[kFishIn108] = true; + + /* Section #2 variables */ + _globals[kLadderBroken] = false; + _globals[kBone202Status] = 0; + _globals[kRhotundaStatus] = RHOTUNDA_HUNGRY; + _globals[kMonkeyStatus] = MONKEY_AMBUSH_READY; + _globals[kMeteorologistStatus] = METEOROLOGIST_PRESENT; + _globals[kMeteorologistEverSeen] = false; + _globals[kMeteorologistWatch] = METEOROLOGIST_NORMAL; + _globals[kTeleporterCommand] = TELEPORTER_NONE; + _globals[kTeleporterUnderstood] = false; + _globals[kTwinklesStatus] = TWINKLES_AT_HOME; + _globals[kTwinklesApproached] = 0; + + /* Section #3 variables */ + _globals[kAfterHavoc] = false; + _globals[kKickedIn391Grate] = false; + + /* Section #4 variables */ + _globals[kBadFirstIngredient] = -1; + _objects[OBJ_CHARGE_CASES].setQuality(EXPLOSIVES_INSIDE, 0); + _globals[kHasPurchased] = false; + _globals[kBeenThruHelgaScene] = false; + _globals[kNextIngredient] = 0; + _globals[kHasSaidTimer] = false; + _globals[kHasSaidBinocs] = false; + _globals[kBottleDisplayed] = false; + _globals[kHasBeenScanned] = false; + _globals[kSomeoneHasExploded] = false; + + // Generate a random ingredient list + for (count = 0; count < 4; ++count) { + do { + _globals[kIngredientList + count] = _vm->getRandomNumber(3); + bad = false; + for (count2 = 0; count2 < count; ++count2) { + if (_globals[kIngredientList + count] == _globals[kIngredientList + count2]) { + bad = true; + } + } + } while (bad); + } + + // Generate random ingredient quantities + for (count = 0; count < 4; ++count) { + do { + _globals[kIngredientQuantity + count] = _vm->getRandomNumber(3); + bad = false; + for (count2 = 0; count2 < count; ++count2) { + if (_globals[kIngredientQuantity + count] == _globals[kIngredientQuantity + count2]) { + bad = true; + } + } + } while (bad); + } + + + /* Section #5 variables */ + _globals[kHoverCarLocation] = 501; + _globals[kHoverCarDestination] = -1; + _globals[kCityFlooded] = false; + _globals[kBoatRaised] = true; + _globals[kLaserHoleIsThere] = false; + _globals[kLineStatus] = LINE_NOT_DROPPED; + + + /* Section #6 variables */ + _globals[kHasTalkedToHermit] = false; + _globals[kHandsetCellStatus] = FIRST_TIME_PHONE_CELLS; + _globals[kTimebombStatus] = TIMEBOMB_DEACTIVATED; + _globals[kWarnedFloodCity] = false; + _globals._timebombClock = 0; + _globals._timebombTimer = 0; + + + /* Section #7 variables */ + _globals[kBottleStatus] = BOTTLE_EMPTY; + _globals[kBoatStatus] = BOAT_UNFLOODED; + + + /* Section #8 variables */ + _globals[kWindowFixed] = false; + _globals[kInSpace] = false; + _globals[kReturnFromCut] = false; + _globals[kBeamIsUp] = false; + _globals[kForceBeamDown] = false; + _globals[kCameFromCut] = false; + _globals[kDontRepeat] = false; + _globals[kHoppyDead] = false; + _globals[kHasWatchedAntigrav] = false; + _globals[kRemoteSequenceRan] = false; + _globals[kRemoteOnGround] = false; + _globals[kFromCockpit] = false; + _globals[kExitShip] = false; + _globals[kBetweenRooms] = false; + _globals[kTopButtonPushed] = false; + _globals[kShieldModInstalled] = false; + _globals[kTargetModInstalled] = false; + _globals[kUpBecauseOfRemote] = false; + + + /* Set up the game's teleporters */ + _globals[kTeleporterRoom] = 201; + _globals[kTeleporterRoom + 1] = 301; + _globals[kTeleporterRoom + 2] = 413; + _globals[kTeleporterRoom + 3] = 706; + _globals[kTeleporterRoom + 4] = 801; + _globals[kTeleporterRoom + 5] = 551; + _globals[kTeleporterRoom + 6] = 752; + _globals[kTeleporterRoom + 7] = 0; + _globals[kTeleporterRoom + 8] = 0; + _globals[kTeleporterRoom + 9] = 0; + + for (count = 0; count < TELEPORTER_COUNT; ++count) { + do { + _globals[kTeleporterCode + count] = _vm->getRandomNumber(9999); + bad = false; + for (count2 = 0; count2 < count; ++count2) { + if (_globals[kTeleporterCode + count] == _globals[kTeleporterCode + count2]) { + bad = true; + } + } + } while (bad); + } + + // Final setup based on selected difficulty level + switch (_difficulty) { + case DIFFICULTY_HARD: + _objects.setRoom(OBJ_PLANT_STALK, NOWHERE); + _objects.setRoom(OBJ_PENLIGHT, NOWHERE); + + _globals[kLeavesStatus] = LEAVES_ON_TRAP; + break; + + case DIFFICULTY_MEDIUM: + _objects.setRoom(OBJ_PLANT_STALK, NOWHERE); + + _globals[kLeavesStatus] = LEAVES_ON_GROUND; + _globals[kDurafailRecharged] = true; + _globals[kPenlightCellStatus] = FIRST_TIME_CHARGED_DURAFAIL; + break; + + case DIFFICULTY_EASY: + _objects.setRoom(OBJ_BLOWGUN, NOWHERE); + _objects.setRoom(OBJ_NOTE, NOWHERE); + + _globals[kLeavesStatus] = LEAVES_ON_GROUND; + _globals[kPenlightCellStatus] = FIRST_TIME_UNCHARGED_DURAFAIL; + _globals[kDurafailRecharged] = false; + break; + } + + _player._facing = FACING_NORTH; + _player._turnToFacing = FACING_NORTH; + + Player::preloadSequences("RXM", 1); + Player::preloadSequences("ROX", 1); +} + +void GameNebular::setSectionHandler() { + delete _sectionHandler; + + switch (_sectionNumber) { + case 1: + _sectionHandler = new Section1Handler(_vm); + break; + case 2: + _sectionHandler = new Section2Handler(_vm); + break; + case 3: + _sectionHandler = new Section3Handler(_vm); + break; + case 4: + _sectionHandler = new Section4Handler(_vm); + break; + case 5: + _sectionHandler = new Section5Handler(_vm); + break; + case 6: + _sectionHandler = new Section6Handler(_vm); + break; + case 7: + _sectionHandler = new Section7Handler(_vm); + break; + case 8: + _sectionHandler = new Section8Handler(_vm); + break; + default: + break; + } +} + +void GameNebular::checkShowDialog() { + if (_vm->_dialogs->_pendingDialog && _player._stepEnabled && !_globals[kCopyProtectFailed]) { + _player.releasePlayerSprites(); + _vm->_dialogs->showDialog(); + _vm->_dialogs->_pendingDialog = DIALOG_NONE; + } +} + +void GameNebular::showRecipe() { + Dialogs &dialogs = *_vm->_dialogs; + int count; + + for (count = 0; count < 4; count++) { + switch(_globals[kIngredientQuantity + count]) { + case 0: + dialogs._indexList[count] = NOUN_DROP; + break; + case 1: + dialogs._indexList[count] = NOUN_DOLLOP; + break; + case 2: + dialogs._indexList[count] = NOUN_DASH; + break; + case 3: + dialogs._indexList[count] = NOUN_SPLASH; + break; + default: + break; + } + } + + for (count = 0; count < 4; count++) { + switch(_globals[kIngredientList + count]) { + case 0: + dialogs._indexList[count + 4] = NOUN_ALCOHOL; + break; + case 1: + dialogs._indexList[count + 4] = NOUN_LECITHIN; + break; + case 2: + dialogs._indexList[count + 4] = NOUN_PETROX; + break; + case 3: + dialogs._indexList[count + 4] = NOUN_FORMALDEHYDE; + break; + default: + break; + } + } + + _vm->_dialogs->show(401); +} + +void GameNebular::doObjectAction() { + Scene &scene = _scene; + MADSAction &action = _scene._action; + Dialogs &dialogs = *_vm->_dialogs; + int id; + + if (action.isAction(VERB_SMELL) && scene._currentSceneId > 103 && scene._currentSceneId < 111) { + dialogs.show(440); + } else if (action.isAction(VERB_EAT) && scene._currentSceneId > 103 && scene._currentSceneId < 111) { + dialogs.show(441); + } else if (action.isAction(VERB_SMELL, NOUN_BURGER)) { + dialogs.show(442); + } else if (action.isAction(VERB_EAT, NOUN_BURGER)) { + dialogs.show(443); + } else if (action.isAction(VERB_SMELL, NOUN_STUFFED_FISH)) { + dialogs.show(444); + } else if (action.isAction(VERB_EAT, NOUN_STUFFED_FISH)) { + dialogs.show(445); + } else if (action.isAction(VERB_WEAR, NOUN_REBREATHER)) { + dialogs.show(scene._currentSceneId > 103 && scene._currentSceneId < 111 ? 446 : 447); + } else if (action.isAction(VERB_SET, NOUN_TIMER_MODULE)) { + dialogs.show(448); + } else if (action.isAction(VERB_NIBBLE_ON, NOUN_BIG_LEAVES)) { + dialogs.show(449); + } else if (action.isAction(VERB_LICK, NOUN_POISON_DARTS)) { + dialogs.show(450); + } else if (action.isAction(VERB_EAT, NOUN_TWINKIFRUIT)) { + _objects.setRoom(OBJ_TWINKIFRUIT, PLAYER_INVENTORY); + dialogs.show(451); + } else if (action.isAction(VERB_GORGE_ON, NOUN_TWINKIFRUIT)) { + _objects.setRoom(OBJ_TWINKIFRUIT, PLAYER_INVENTORY); + dialogs.show(452); + } else if (action.isAction(VERB_GNAW_ON)) { + dialogs.show(453); + } else if (action.isAction(VERB_MASSAGE, NOUN_AUDIO_TAPE)) { + dialogs.show(454); + } else if (action.isAction(VERB_MANGLE, NOUN_CREDIT_CHIP)) { + dialogs.show(455); + } else if (action.isAction(VERB_FONDLE, NOUN_CHARGE_CASES)) { + dialogs.show(456); + } else if (action.isAction(VERB_RUB, NOUN_BOMB)) { + dialogs.show(457); + } else if (action.isAction(VERB_SET, NOUN_TIMEBOMB)) { + dialogs.show(458); + } else if (action.isAction(VERB_GUZZLE, NOUN_ALIEN_LIQUOR)) { + dialogs.show(459); + } else if (action.isAction(VERB_SMASH, NOUN_TARGET_MODULE)) { + dialogs.show(460); + } else if (action.isAction(VERB_JUGGLE)) { + dialogs.show(461); + } else if (action.isAction(VERB_APPLY, NOUN_POLYCEMENT)) { + dialogs.show(462); + } else if (action.isAction(VERB_SNIFF, NOUN_POLYCEMENT)) { + dialogs.show(465); + } else if (action.isAction(VERB_TIE, NOUN_FISHING_LINE)) { + dialogs.show(463); + } else if (action.isAction(VERB_ATTACH, NOUN_FISHING_LINE)) { + dialogs.show(463); + } else if (action.isAction(VERB_UNLOCK)) { + dialogs.show(464); + } else if (action.isAction(VERB_REFLECT)) { + dialogs.show(466); + } else if (action.isAction(VERB_GAZE_INTO, NOUN_REARVIEW_MIRROR)) { + dialogs.show(467); + } else if (action.isAction(VERB_EAT, NOUN_CHICKEN_BOMB)) { + dialogs.show(469); + } else if (action.isAction(VERB_BREAK, NOUN_VASE)) { + dialogs.show(471); + } else if (action.isAction(VERB_SHAKE_HANDS, NOUN_GUARDS_ARM2)) { + dialogs.show(472); + } else if (action.isAction(VERB_READ, NOUN_LOG)) { + dialogs.show(473); + } else if (action.isAction(VERB_RUB, NOUN_BOMBS)) { + dialogs.show(474); + } else if (action.isAction(VERB_DRINK, NOUN_FORMALDEHYDE)) { + dialogs.show(475); + } else if (action.isAction(VERB_DRINK, NOUN_PETROX)) { + dialogs.show(476); + } else if (action.isAction(VERB_DRINK, NOUN_LECITHIN)) { + dialogs.show(477); + } else if (action.isAction(VERB_PUT, NOUN_POISON_DARTS, NOUN_PLANT_STALK) && _objects.isInInventory(OBJ_POISON_DARTS) + && _objects.isInInventory(OBJ_PLANT_STALK)) { + _objects.addToInventory(OBJ_BLOWGUN); + _objects.setRoom(OBJ_PLANT_STALK, NOWHERE); + _globals[kBlowgunStatus] = 0; + dialogs.showItem(OBJ_BLOWGUN, 809); + } else if (action.isAction(VERB_PUT, NOUN_POISON_DARTS, NOUN_BLOWGUN) && _objects.isInInventory(OBJ_POISON_DARTS) + && _objects.isInInventory(OBJ_BLOWGUN)) { + dialogs.show(433); + } else if (action.isAction(VERB_DEFACE) && action.isAction(VERB_FOLD) && action.isAction(VERB_MUTILATE)) { + dialogs.show(434); + } else if (action.isAction(VERB_SPINDLE)) { + dialogs.show(479); + } else if ((action.isAction(VERB_READ) || action.isAction(VERB_LOOK_AT) || action.isAction(VERB_LOOK)) && + action.isObject(NOUN_NOTE) && _objects.isInInventory(OBJ_NOTE)) { + _objects.setRoom(OBJ_NOTE, PLAYER_INVENTORY); + _objects.addToInventory(OBJ_COMBINATION); + dialogs.showItem(OBJ_COMBINATION, 851); + } else if ((action.isAction(VERB_LOOK) || action.isAction(VERB_READ)) && + ((id = _objects.getIdFromDesc(action._activeAction._objectNameId)) > 0 || + (action._activeAction._indirectObjectId > 0 && + (id = _objects.getIdFromDesc(action._activeAction._indirectObjectId)))) && + _objects.isInInventory(id)) { + if (id == OBJ_REPAIR_LIST) { + dialogs._indexList[0] = _globals[kTeleporterCode + 7]; + dialogs._indexList[1] = _globals[kTeleporterCode + 8]; + dialogs._indexList[2] = _globals[kTeleporterCode + 6]; + dialogs._indexList[3] = _globals[kTeleporterCode + 9]; + dialogs._indexList[4] = _globals[kTeleporterCode + 0]; + dialogs._indexList[5] = _globals[kTeleporterCode + 1]; + dialogs._indexList[6] = _globals[kTeleporterCode + 4]; + dialogs._indexList[7] = _globals[kTeleporterCode + 5]; + dialogs._indexList[8] = _globals[kTeleporterCode + 2]; + + dialogs.showItem(id, 402); + } else { + int messageId = 800 + id; + if ((id == OBJ_CHARGE_CASES) && _objects[OBJ_CHARGE_CASES].getQuality(3) != 0) { + messageId = 860; + } + + if (id == OBJ_TAPE_PLAYER && _objects[OBJ_AUDIO_TAPE]._roomNumber == OBJ_TAPE_PLAYER) + messageId = 867; + + if (id == 32 && _objects[OBJ_FISHING_LINE]._roomNumber == 3) + messageId = 862; + + if (id == OBJ_BOTTLE && _globals[kBottleStatus] != 0) + messageId = 862 + _globals[kBottleStatus]; + + if (id == OBJ_PHONE_HANDSET && _globals[kHandsetCellStatus]) + messageId = 861; + + dialogs.showItem(id, messageId); + } + } else if (action.isAction(VERB_PUT, NOUN_BURGER, NOUN_DEAD_FISH)) { + if (_objects.isInInventory(OBJ_BURGER) || _objects.isInInventory(OBJ_DEAD_FISH)) { + _objects.removeFromInventory(OBJ_DEAD_FISH, PLAYER_INVENTORY); + _objects.removeFromInventory(OBJ_BURGER, PLAYER_INVENTORY); + _objects.addToInventory(OBJ_STUFFED_FISH); + dialogs.showItem(OBJ_STUFFED_FISH, 803); + } + } else if (action.isAction(VERB_PUT, NOUN_AUDIO_TAPE, NOUN_TAPE_PLAYER) && _objects.isInInventory(OBJ_AUDIO_TAPE) && + _objects.isInInventory(OBJ_TAPE_PLAYER)) { + _objects.setRoom(OBJ_AUDIO_TAPE, OBJ_TAPE_PLAYER); + } else if (action.isAction(VERB_ACTIVATE, NOUN_TAPE_PLAYER) && _objects.isInInventory(OBJ_TAPE_PLAYER)) { + if (_objects[OBJ_AUDIO_TAPE]._roomNumber == OBJ_TAPE_PLAYER) { + showRecipe(); + } else { + dialogs.show(406); + } + } else if (action.isAction(VERB_EJECT, NOUN_TAPE_PLAYER) && _objects.isInInventory(OBJ_TAPE_PLAYER)) { + if (_objects[OBJ_AUDIO_TAPE]._roomNumber == OBJ_TAPE_PLAYER) { + _objects.addToInventory(OBJ_AUDIO_TAPE); + } else { + dialogs.show(407); + } + } else if (action.isAction(VERB_DISASSEMBLE, NOUN_TAPE_PLAYER)) { + dialogs.show(408); + } else if (action.isAction(VERB_ACTIVATE, NOUN_REMOTE)) { + dialogs.show(_globals[kTopButtonPushed] ? 502 : 501); + } else if ((action.isAction(VERB_ATTACH, NOUN_DETONATORS, NOUN_CHARGE_CASES) || action.isAction(VERB_PUT, NOUN_DETONATORS, NOUN_CHARGE_CASES)) && + _objects.isInInventory(OBJ_DETONATORS) && _objects.isInInventory(OBJ_CHARGE_CASES)) { + if (_objects[OBJ_CHARGE_CASES].getQuality(3)) { + _objects.setRoom(OBJ_CHARGE_CASES, 1); + _objects.setRoom(OBJ_DETONATORS, 1); + _objects.addToInventory(OBJ_BOMBS); + dialogs.showItem(OBJ_BOMBS, 403); + } else { + dialogs.show(405); + } + } else if (action.isAction(VERB_ATTACH, NOUN_DETONATORS)) { + dialogs.show(470); + } else if ((action.isAction(VERB_ATTACH, NOUN_TIMER_MODULE, NOUN_BOMBS) || action.isAction(VERB_PUT, NOUN_TIMER_MODULE, NOUN_BOMBS) || action.isAction(VERB_ATTACH, NOUN_TIMER_MODULE, NOUN_BOMB) + || action.isAction(VERB_PUT, NOUN_TIMER_MODULE, NOUN_BOMB)) && _objects.isInInventory(OBJ_TIMER_MODULE) && ( + _objects.isInInventory(OBJ_BOMBS) || _objects.isInInventory(OBJ_BOMB))) { + if (_objects.isInInventory(OBJ_BOMBS)) { + _objects.setRoom(OBJ_BOMBS, PLAYER_INVENTORY); + _objects.addToInventory(OBJ_BOMB); + } else { + _objects.setRoom(OBJ_BOMB, PLAYER_INVENTORY); + } + + _objects.setRoom(OBJ_TIMER_MODULE, PLAYER_INVENTORY); + _objects.addToInventory(OBJ_TIMEBOMB); + dialogs.showItem(OBJ_TIMEBOMB, 404); + } else if (action.isAction(VERB_FONDLE, NOUN_PLANT_STALK)) { + dialogs.show(410); + } else if (action.isAction(VERB_EMPTY, NOUN_BOTTLE)) { + _globals[kBottleStatus] = 0; + dialogs.show(432); + } else if (action.isAction(VERB_DISASSEMBLE, NOUN_FISHING_ROD)) { + if (_objects[OBJ_FISHING_LINE]._roomNumber == 3) { + _objects.addToInventory(OBJ_FISHING_LINE); + dialogs.showItem(OBJ_FISHING_LINE, 409); + } else { + dialogs.show(428); + } + } else if (action.isAction(VERB_DISASSEMBLE, NOUN_PENLIGHT)) { + switch (_globals[kPenlightCellStatus]) { + case 1: + case 2: + _objects.addToInventory(OBJ_DURAFAIL_CELLS); + dialogs.showItem(OBJ_DURAFAIL_CELLS, 412); + break; + case 3: + _objects.addToInventory(OBJ_PHONE_CELLS); + dialogs.showItem(OBJ_DURAFAIL_CELLS, 413); + break; + case 5: + _objects.addToInventory(OBJ_DURAFAIL_CELLS); + dialogs.showItem(OBJ_DURAFAIL_CELLS, 411); + break; + case 6: + _objects.addToInventory(OBJ_DURAFAIL_CELLS); + dialogs.showItem(OBJ_DURAFAIL_CELLS, 429); + break; + default: + dialogs.show(478); + break; + } + } else if (action.isAction(VERB_DISASSEMBLE, NOUN_PHONE_HANDSET)) { + switch (_globals[kHandsetCellStatus]) { + case 1: + _objects.addToInventory(OBJ_DURAFAIL_CELLS); + dialogs.showItem(OBJ_DURAFAIL_CELLS, + _difficulty != 1 || _globals[kDurafailRecharged] ? 415 : 414); + break; + case 2: + _objects.addToInventory(OBJ_DURAFAIL_CELLS); + if (_difficulty == 1) { + dialogs.showItem(OBJ_DURAFAIL_CELLS, 416); + } else { + _globals[kHandsetCellStatus] = 0; + } + break; + case 3: + _objects.addToInventory(OBJ_PHONE_CELLS); + dialogs.showItem(OBJ_PHONE_CELLS, 418); + break; + case 4: + _objects.addToInventory(OBJ_PHONE_CELLS); + dialogs.showItem(OBJ_PHONE_CELLS, 417); + break; + default: + dialogs.show(478); + break; + } + } else if (action.isAction(VERB_PUT, NOUN_PHONE_CELLS, NOUN_PENLIGHT)) { + if (_globals[kPenlightCellStatus] == 0) { + _globals[kPenlightCellStatus] = 3; + _objects.setRoom(OBJ_PHONE_CELLS, PLAYER_INVENTORY); + dialogs.show(419); + } else { + dialogs.show(420); + } + } else if (action.isAction(VERB_PUT, NOUN_PHONE_CELLS, NOUN_PHONE_HANDSET)) { + if (_globals[kHandsetCellStatus] == 0) { + _globals[kHandsetCellStatus] = 3; + _objects.setRoom(OBJ_PHONE_CELLS, PLAYER_INVENTORY); + dialogs.show(421); + } else { + dialogs.show(422); + } + } else if (action.isAction(VERB_PUT, NOUN_DURAFAIL_CELLS, NOUN_PENLIGHT)) { + if (_globals[kPenlightCellStatus]) { + dialogs.show(424); + } else { + _objects.setRoom(OBJ_DURAFAIL_CELLS, PLAYER_INVENTORY); + _globals[kPenlightCellStatus] = _difficulty != 1 || _globals[kDurafailRecharged] ? 1 : 2; + dialogs.show(423); + } + } else if (action.isAction(VERB_PUT, NOUN_DURAFAIL_CELLS, NOUN_PHONE_HANDSET)) { + if (_globals[kHandsetCellStatus]) { + dialogs.show(424); + } else { + _objects.setRoom(OBJ_DURAFAIL_CELLS, PLAYER_INVENTORY); + _globals[kDurafailRecharged] = _difficulty != 1 || _globals[kHandsetCellStatus] ? 1 : 2; + dialogs.show(425); + } + } else if (action.isAction(VERB_SET, NOUN_TIMEBOMB)) { + dialogs.show(427); + } else if (action.isAction(VERB_PUT, NOUN_BOMB, NOUN_CHICKEN) || action.isAction(VERB_PUT, NOUN_BOMBS, NOUN_CHICKEN)) { + _objects.setRoom(OBJ_CHICKEN, PLAYER_INVENTORY); + if (_objects.isInInventory(OBJ_BOMBS)) { + _objects.setRoom(OBJ_BOMBS, PLAYER_INVENTORY); + _objects.addToInventory(OBJ_BOMB); + } else { + _objects.setRoom(OBJ_BOMB, PLAYER_INVENTORY); + } + + _objects.addToInventory(OBJ_CHICKEN_BOMB); + dialogs.showItem(OBJ_CHICKEN_BOMB, 430); + } else { + return; + } + + action._inProgress = false; +} + +void GameNebular::unhandledAction() { + int randVal = _vm->getRandomNumber(1, 1000); + MADSAction &action = _scene._action; + + if (action.isAction(VERB_THROW, NOUN_BOMB) || action.isAction(VERB_THROW, NOUN_BOMBS) + || action.isAction(VERB_THROW, NOUN_TIMEBOMB) || action.isAction(VERB_THROW, NOUN_CHICKEN_BOMB)) + _vm->_dialogs->show(42); + else if (action.isAction(VERB_DISASSEMBLE)) + _vm->_dialogs->show(435); + else if ((action.isAction(VERB_EAT, NOUN_DEAD_FISH) || action.isAction(VERB_EAT, NOUN_STUFFED_FISH)) && _vm->_game->_objects.isInInventory(_vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId))) + _vm->_dialogs->show(12); + else if ((action.isAction(VERB_SMELL, NOUN_DEAD_FISH) || action.isAction(VERB_SMELL, NOUN_STUFFED_FISH)) && _vm->_game->_objects.isInInventory(_vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId))) + _vm->_dialogs->show(13); + else if (action.isAction(VERB_EAT, NOUN_CHICKEN) && _vm->_game->_objects.isInInventory(OBJ_CHICKEN)) + _vm->_dialogs->show(912); + else if ((action.isAction(VERB_SHOOT) || action.isAction(VERB_HOSE_DOWN)) && action.isObject(NOUN_BLOWGUN)) { + if ((_scene._currentSceneId >= 104) && (_scene._currentSceneId <= 111)) + _vm->_dialogs->show(38); + else if (action.isObject(NOUN_PIRANHA)) + _vm->_dialogs->show(41); + else if (action.isObject(NOUN_CHICKEN) || action.isObject(NOUN_VULTURE) || action.isObject(NOUN_SPIDER) + || action.isObject(NOUN_YELLOW_BIRD) || action.isObject(NOUN_SWOOPING_CREATURE) || action.isObject(NOUN_CAPTIVE_CREATURE)) { + _vm->_dialogs->show(40); + } else + _vm->_dialogs->show(39); + } else if (action.isAction(VERB_TALKTO)) { + _globals[kTalkInanimateCount] = (_globals[kTalkInanimateCount] + 1) % 16; + if (!_globals[kTalkInanimateCount]) { + _vm->_dialogs->show(2); + } else { + Common::String tmpMsg = "\"Greetings, "; + tmpMsg += _vm->_game->_scene.getVocab(action._activeAction._objectNameId); + tmpMsg += "!\""; + _scene._kernelMessages.reset(); + _scene._kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, tmpMsg); + } + } else if (action.isAction(VERB_GIVE, NOUN_DOOR, NOUN_CEILING) || action.isAction(VERB_CLOSE, NOUN_CHAIR)) + _vm->_dialogs->show(3); + else if (action.isAction(VERB_THROW)) { + int objId = _vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId); + if (objId < 0) + _vm->_dialogs->show(4); + else if (_vm->_game->_objects[objId]._roomNumber != 2) + _vm->_dialogs->show(5); + else + _vm->_dialogs->show(6); + } else if (action.isAction(VERB_LOOK)) { + if (action.isObject(NOUN_BINOCULARS) && (action._activeAction._indirectObjectId > 0)) + _vm->_dialogs->show(10); + else if (randVal < 600) + _vm->_dialogs->show(7); + else + _vm->_dialogs->show(21); + } else if (action.isAction(VERB_TAKE)) { + int objId = _vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId); + if (_vm->_game->_objects.isInInventory(objId)) + _vm->_dialogs->show(16); + else if (randVal <= 333) + _vm->_dialogs->show(8); + else if (randVal <= 666) + _vm->_dialogs->show(22); + else + _vm->_dialogs->show(23); + } else if (action.isAction(VERB_CLOSE)) { + if (randVal <= 333) + _vm->_dialogs->show(9); + else + _vm->_dialogs->show(33); + } else if (action.isAction(VERB_OPEN)) { + if (randVal <= 500) + _vm->_dialogs->show(30); + else if (randVal <= 750) + _vm->_dialogs->show(31); + else + _vm->_dialogs->show(32); + } else if (action.isAction(VERB_PULL)) + _vm->_dialogs->show(18); + else if (action.isAction(VERB_PUSH)) { + if (randVal < 750) + _vm->_dialogs->show(19); + else + _vm->_dialogs->show(20); + } else if (action.isAction(VERB_PUT)) { + int objId = _vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId); + if (_vm->_game->_objects.isInInventory(objId)) + _vm->_dialogs->show(25); + else + _vm->_dialogs->show(24); + } else if (action.isAction(VERB_GIVE)) { + int objId = _vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId); + if (!_vm->_game->_objects.isInInventory(objId)) + _vm->_dialogs->show(26); + else if (randVal <= 500) + _vm->_dialogs->show(28); + else + _vm->_dialogs->show(29); + } else if (!action.isAction(VERB_WALKTO) && !action.isAction(VERB_WALK_ACROSS) && !action.isAction(VERB_WALK_TOWARDS) && !action.isAction(VERB_WALK_DOWN) + && !action.isAction(VERB_SWIM_TO) && !action.isAction(VERB_SWIM_ACROSS) && !action.isAction(VERB_SWIM_INTO) && !action.isAction(VERB_SWIM_THROUGH) + && !action.isAction(VERB_SWIM_UNDER)) { + if (randVal <= 100) + _vm->_dialogs->show(36); + else if (randVal <= 200) + _vm->_dialogs->show(1); + else if (randVal <= 475) + _vm->_dialogs->show(34); + else if (randVal <= 750) + _vm->_dialogs->show(35); + else + _vm->_dialogs->show(37); + } +} + +void GameNebular::step() { + if (_player._visible && _player._stepEnabled && !_player._moving && + (_player._facing == _player._turnToFacing)) { + if (_scene._frameStartTime >= *((uint32 *)&_globals[kWalkerTiming])) { + if (!_player._stopWalkerIndex) { + int randomVal = _vm->getRandomNumber(29999);; + if (_globals[kSexOfRex] == REX_MALE) { + switch (_player._facing) { + case FACING_SOUTHWEST: + case FACING_SOUTHEAST: + case FACING_NORTHWEST: + case FACING_NORTHEAST: + if (randomVal < 200) { + _player.addWalker(-1, 0); + _player.addWalker(1, 0); + } + break; + + case FACING_WEST: + case FACING_EAST: + if (randomVal < 500) { + for (int count = 0; count < 10; ++count) { + _player.addWalker(1, 0); + } + } + break; + + case FACING_SOUTH: + if (randomVal < 500) { + for (int count = 0; count < 10; ++count) { + _player.addWalker((randomVal < 250) ? 1 : 2, 0); + } + } else if (randomVal < 750) { + for (int count = 0; count < 5; ++count) { + _player.addWalker(1, 0); + } + + _player.addWalker(0, 0); + _player.addWalker(0, 0); + + for (int count = 0; count < 5; ++count) { + _player.addWalker(2, 0); + } + } + break; + + default: + break; + } + } + } + + *((uint32 *)&_globals[kWalkerTiming]) += 6; + } + } + + // Below is countdown to set the timebomb off in room 604 + if (_globals[kTimebombStatus] == TIMEBOMB_ACTIVATED) { + int diff = _scene._frameStartTime - *((uint32 *)&_globals[kTimebombClock]); + if ((diff >= 0) && (diff <= 60)) { + *((uint32 *)&_globals[kTimebombTimer]) += diff; + } else { + ++*((uint32 *)&_globals[kTimebombTimer]); + } + *((uint32 *)&_globals[kTimebombClock]) = _scene._frameStartTime; + } +} + +void GameNebular::synchronize(Common::Serializer &s, bool phase1) { + Game::synchronize(s, phase1); + + if (phase1) { + _globals.synchronize(s); + s.syncAsByte(_storyMode); + s.syncAsByte(_difficulty); + } +} + +} // End of namespace Nebular + +} // End of namespace MADS diff --git a/engines/mads/nebular/game_nebular.h b/engines/mads/nebular/game_nebular.h new file mode 100644 index 0000000000..6620deaea6 --- /dev/null +++ b/engines/mads/nebular/game_nebular.h @@ -0,0 +1,153 @@ +/* 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. + * + */ + +#ifndef MADS_GAME_NEBULAR_H +#define MADS_GAME_NEBULAR_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/globals.h" +#include "mads/nebular/globals_nebular.h" + +namespace MADS { + +namespace Nebular { + +enum StoryMode { STORYMODE_NAUGHTY = 1, STORYMODE_NICE = 2 }; + +enum Difficulty { + DIFFICULTY_HARD = 1, DIFFICULTY_MEDIUM = 2, DIFFICULTY_EASY = 3 +}; + +enum InventoryObject { + OBJ_NONE = -1, + OBJ_BINOCULARS = 0, + OBJ_BURGER = 1, + OBJ_DEAD_FISH = 2, + OBJ_STUFFED_FISH = 3, + OBJ_REBREATHER = 4, + OBJ_TIMER_MODULE = 5, + OBJ_BIG_LEAVES = 6, + OBJ_POISON_DARTS = 7, + OBJ_PLANT_STALK = 8, + OBJ_BLOWGUN = 9, + OBJ_TWINKIFRUIT = 10, + OBJ_BONE = 11, + OBJ_CHICKEN = 12, + OBJ_SCALPEL = 13, + OBJ_AUDIO_TAPE = 14, + OBJ_CREDIT_CHIP = 15, + OBJ_SECURITY_CARD = 16, + OBJ_CHARGE_CASES = 17, + OBJ_ESTROTOXIN = 18, + OBJ_BOMB = 19, + OBJ_TIMEBOMB = 20, + OBJ_REPAIR_LIST = 21, + OBJ_ALIEN_LIQUOR = 22, + OBJ_TARGET_MODULE = 23, + OBJ_SHIELD_MODULATOR = 24, + OBJ_TAPE_PLAYER = 25, + OBJ_PHONE_CELLS = 26, + OBJ_PENLIGHT = 27, + OBJ_DURAFAIL_CELLS = 28, + OBJ_FAKE_ID = 29, + OBJ_ID_CARD = 30, + OBJ_POLYCEMENT = 31, + OBJ_FISHING_ROD = 32, + OBJ_FISHING_LINE = 33, + OBJ_PADLOCK_KEY = 34, + OBJ_DOOR_KEY = 35, + OBJ_REARVIEW_MIRROR = 36, + OBJ_COMPACT_CASE = 37, + OBJ_DETONATORS = 39, + OBJ_BOTTLE = 40, + OBJ_CHICKEN_BOMB = 41, + OBJ_VASE = 42, + OBJ_REMOTE = 43, + OBJ_COMPUTER_GAME = 44, + OBJ_PHONE_HANDSET = 45, + OBJ_BONES = 46, + OBJ_GUARDS_ARM = 47, + OBJ_LOG = 48, + OBJ_BOMBS = 49, + OBJ_NOTE = 50, + OBJ_COMBINATION = 51, + OBJ_FORMALDEHYDE = 52, + OBJ_PETROX = 53, + OBJ_LECITHIN = 54 +}; + +class GameNebular : public Game { + friend class Game; +protected: + GameNebular(MADSEngine *vm); + + virtual ProtectionResult checkCopyProtection(); + + virtual void initializeGlobals(); + + virtual void setSectionHandler(); + + virtual void checkShowDialog(); +public: + NebularGlobals _globals; + StoryMode _storyMode; + Difficulty _difficulty; + + virtual Globals &globals() { return _globals; } + + virtual void doObjectAction(); + + void showRecipe(); + + virtual void unhandledAction(); + + virtual void step(); + + virtual void synchronize(Common::Serializer &s, bool phase1); +}; + + +class Section1Handler : public SectionHandler { +public: + Section1Handler(MADSEngine *vm) : SectionHandler(vm) {} + + // TODO: Properly implement handler methods + virtual void preLoadSection() {} + virtual void sectionPtr2() {} + virtual void postLoadSection() {} +}; + +// TODO: Properly implement handler classes +typedef Section1Handler Section2Handler; +typedef Section1Handler Section3Handler; +typedef Section1Handler Section4Handler; +typedef Section1Handler Section5Handler; +typedef Section1Handler Section6Handler; +typedef Section1Handler Section7Handler; +typedef Section1Handler Section8Handler; + +} // End of namespace Nebular + +} // End of namespace MADS + +#endif /* MADS_GAME_NEBULAR_H */ diff --git a/engines/mads/nebular/globals_nebular.cpp b/engines/mads/nebular/globals_nebular.cpp new file mode 100644 index 0000000000..9f8b8a7888 --- /dev/null +++ b/engines/mads/nebular/globals_nebular.cpp @@ -0,0 +1,55 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 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. + * + */ + +#include "common/scummsys.h" +#include "common/config-manager.h" +#include "mads/nebular/globals_nebular.h" + +namespace MADS { + +namespace Nebular { + +NebularGlobals::NebularGlobals() + : Globals() { + // Initialize lists + resize(210); + _spriteIndexes.resize(30); + _sequenceIndexes.resize(30); + + // Initialize game flags + _timebombClock = 0; + _timebombTimer = 0; +} + +void NebularGlobals::synchronize(Common::Serializer &s) { + Globals::synchronize(s); + + s.syncAsUint32LE(_timebombClock); + s.syncAsUint32LE(_timebombTimer); + _spriteIndexes.synchronize(s); + _sequenceIndexes.synchronize(s); +} + + +} // End of namespace Nebular + +} // End of namespace MADS diff --git a/engines/mads/nebular/globals_nebular.h b/engines/mads/nebular/globals_nebular.h new file mode 100644 index 0000000000..88605a290e --- /dev/null +++ b/engines/mads/nebular/globals_nebular.h @@ -0,0 +1,305 @@ +/* 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. + * + */ + +#ifndef MADS_GLOBALS_NEBULAR_H +#define MADS_GLOBALS_NEBULAR_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "mads/game.h" +#include "mads/resources.h" + +namespace MADS { + +namespace Nebular { + +enum GlobalId { + kSexOfRex = 0, + kOldSexOfRex = 1, + kWalkerTiming = 2, +// kWalkerTiming0 = 3, + kTalkInanimateCount = 4, + kCopyProtectFailed = 5, + + /* Section #1 variables */ + kNeedToStandUp = 10, + kTurkeyExploded = 11, + kMedicineCabinetOpen = 12, + kMedicineCabinetVirgin = 13, + kWatchedViewScreen = 14, + kHoovicAlive = 15, + kHoovicSated = 16, + kHoovicFishEaten = 17, + kWaterInAPuddle = 18, + kFishIn105 = 19, + kFishIn107 = 20, + kFishIn108 = 21, + kRandomNumber = 29, + + /* Section #2 variables */ + kCurtainOpen = 30, + kLadderBroken = 31, + kBone202Status = 32, + kMeteorologistStatus = 33, + kRhotundaStatus = 34, + kLeavesStatus = 35, + kMonkeyStatus = 36, + kMeteorologistEverSeen = 37, + kMeteorologistWatch = 38, + kTeleporterCommand = 39, + + kTeleporterDestination = 40, + kTeleporterUnderstood = 41, + kConv205 = 42, + kChickenPermitted = 43, + kTwinklesStatus = 44, + kTwinklesApproached = 45, + kConvTwinkles1 = 46, + kConvTwinkles2 = 47, + kConvTwinkles3 = 48, + kConvTwinkles5 = 49, + + kConvTwinkles6 = 50, + kConvTwinkles7 = 51, + kConvTwinkles8 = 52, + kBlowgunStatus = 53, + + /* Section #3 Variables */ + kAfterHavoc = 60, + kHaveYourStuff = 61, + kRightView320 = 62, + kConvBuddy1 = 63, + kConvBuddy2 = 64, + kMetBuddyBeast = 65, + kKnowsBuddyBeast = 66, + kConvSlache1 = 67, + kConvSlache2 = 68, + kConvSlache3 = 69, + + kRexHasMetSlache = 70, + kConvIntern = 71, + kHasSeenProfPyro = 72, + kKickedIn391Grate = 73, + + /* Section #4 Variables */ + kArmoryDoorOpen = 80, + kStorageDoorOpen = 81, + kNextIngredient = 82, + kIngredientList = 83, + kIngredientList1 = 84, + kIngredientList2 = 85, + kIngredientList3 = 86, + kIngredientQuantity = 87, + kIngredientQuantity1 = 88, + kIngredientQuantity2 = 89, + + kIngredientQuantity3 = 90, + kconvPyro_1 = 91, + kconvPyro_2 = 92, + kconvPyro_3 = 93, + kconvPyro_4 = 94, + kBadFirstIngredient = 95, + kConvBartender1 = 96, + kConvBartender2 = 97, + kConvBartender3 = 98, + kConvBartender4 = 99, + + kHasPurchased = 100, + kBeenThruHelgaScene = 101, + kHasSaidBinocs = 102, + kHasSaidTimer = 103, + kBottleDisplayed = 104, + kHasBeenScanned = 105, + kSomeoneHasExploded = 106, + + /* Section #5 Variables */ + kBoatRaised = 110, + kCarStatus = 111, + kCityFlooded = 112, + kLaserOn = 113, + kLaserHoleIsThere = 114, + kCarIsGone = 115, + kRegisterOpen = 116, + kSafeStatus = 117, + kDogStatus = 118, + kLineStatus = 119, + + kHoverCarLocation = 120, + kHoverCarDestination = 121, + + /* Section #6 Variables */ + kConvHermit1 = 130, + kconvHermit2 = 131, + kHasTalkedToHermit = 132, + kExecuted_1_11 = 133, + kHandsetCellStatus = 134, + kBeenInVideoStore = 135, + kDurafailRecharged = 136, + kPenlightCellStatus = 137, + kTimebombStatus = 138, + kCheckDaemonTimebomb = 140, + + kResurrectRoom = 141, + + /* Section #6 Time-Bomb Variables */ + kTimebombClock = 142, +// kTimebombClock0 = 143, + kTimebombTimer = 144, +// kTimebombTimer0 = 145, + kWarnedFloodCity = 146, + + /* Section #7 Variables */ + kBottleStatus = 150, + kMonsterAlive = 151, + kConvBottleFillNode = 152, + kBoatStatus = 153, + + /* Section #8 Variables */ + kAntigravClock = 160, +// kAntigravClock0 = 161, + kAntigravTiming = 162, +// kAntigravTiming0 = 163, + kWindowFixed = 164, + kInSpace = 165, + kReturnFromCut = 166, + kBeamIsUp = 167, + kForceBeamDown = 168, + kCameFromCut = 169, + + kCutX = 170, + kCutY = 171, + kCutFacing = 172, + kDontRepeat = 173, + kHoppyDead = 174, + kHasWatchedAntigrav = 175, + kRemoteSequenceRan = 176, + kRemoteOnGround = 177, + kFromCockpit = 178, + kExitShip = 179, + + kBetweenRooms = 180, + kTopButtonPushed = 181, + kTargetModInstalled = 182, + kShieldModInstalled = 183, + kUpBecauseOfRemote = 184, + + kTeleporterRoom = 190, + kTeleporterCode = 200 +}; + +/* Enums used for specific individual globals */ +/* Section #1 */ +// Rex's sex/swimming state +enum { REX_MALE = 0, REX_MALE_SWIMMER = 1, REX_FEMALE = 2 }; +// State of Meteorologist in the outpost +enum { METEOROLOGIST_ABSENT = 0, METEOROLOGIST_PRESENT = 1, METEOROLOGIST_GONE = 2 }; + +// State of watching the Meteorologist +enum { METEOROLOGIST_NORMAL = 0, METEOROLOGIST_GROUND = 1, METEOROLOGIST_TOWER = 2 }; + +// The fat bouncy lady that can squish you on the plains +enum { RHOTUNDA_HUNGRY = 0, RHOTUNDA_STUCK = 1, RHOTUNDA_GONE = 2 }; + +// Flags for the bones you can take +enum { BONE_202_LEFT_GONE = 1, BONE_202_RIGHT_GONE = 2 }; + +// Leaves used to cover the trap +enum { LEAVES_ON_GROUND = 0, LEAVES_WITH_PLAYER = 1, LEAVES_ON_TRAP = 2 }; + +// Monkey ambush state +enum { MONKEY_AMBUSH_READY = 0, MONKEY_HAS_BINOCULARS = 1, MONKEY_IS_GONE = 2 }; + +// Teleporter status flags +enum { + TELEPORTER_NONE = 0, TELEPORTER_BEAM_IN = 1, TELEPORTER_BEAM_OUT = 2, + TELEPORTER_STEP_OUT = 3, TELEPORTER_WRONG = 4 +}; + +// TWinkies status +enum { TWINKLES_AT_HOME = 0, TWINKLES_GONE = 1 }; + +/* Section #4 */ +// Status of the explosives +enum { EXPLOSIVES_INSIDE = 3 }; + +/* Section # 5 */ +enum { LINE_NOT_DROPPED = 1, LINE_DROPPED = 2, LINE_TIED = 3, LINE_NOW_UNTIED = 4 }; + +/* Section #6 */ +enum { + NO_CELLS = 0, // Handset doesn't contain any cells + CHARGED_DURAFAIL = 1, // Handset has charged durafail cells + UNCHARGED_DURAFAIL = 2, // Handset has uncharged durafail cells */ + PHONE_CELLS = 3, // Handset has already charged phone cells + FIRST_TIME_PHONE_CELLS = 4, // First time phone cells are in the handset + FIRST_TIME_UNCHARGED_DURAFAIL = 5, // First time uncharged cells are in penlight + FIRST_TIME_CHARGED_DURAFAIL = 6 // First time charged cells are in penlight +}; + +// Time bomb status +enum { + TIMEBOMB_DEACTIVATED = 0, TIMEBOMB_ACTIVATED = 1, + TIMEBOMB_BLOW_UP = 2, TIMEBOMB_DEAD = 3 +}; + +/* Section #7 */ +// Status of the the bottle +enum { + BOTTLE_EMPTY = 0, BOTTLE_ONE_QUARTER_FULL = 1, BOTTLE_HALF_FULL = 2, + BOTTLE_THREE_QUARTERS_FULL = 3, BOTTLE_FULL = 4 +}; + +// Status of the boat +enum { + BOAT_UNFLOODED = 0, BOAT_ADRIFT = 1, BOAT_TIED_FLOATING = 2, + BOAT_TIED = 3, BOAT_GONE = 4 +}; + + +/* Miscellaneous defines */ +#define TELEPORTER_COUNT 10 // Total number of teleporters +#define TELEPORTER_WORK_COUNT 6 // Total number that actually work + + +class NebularGlobals : public Globals { +public: + SynchronizedList _spriteIndexes; + SynchronizedList _sequenceIndexes; + + int _timebombClock, _timebombTimer; +public: + /** + * Constructor + */ + NebularGlobals(); + + /** + * Synchronize the globals data + */ + virtual void synchronize(Common::Serializer &s); +}; + +} // End of namespace Nebular + +} // End of namespace MADS + +#endif /* MADS_GLOBALS_NEBULAR_H */ diff --git a/engines/mads/nebular/nebular_scenes.cpp b/engines/mads/nebular/nebular_scenes.cpp new file mode 100644 index 0000000000..52b565016f --- /dev/null +++ b/engines/mads/nebular/nebular_scenes.cpp @@ -0,0 +1,628 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "common/config-manager.h" +#include "mads/mads.h" +#include "mads/compression.h" +#include "mads/resources.h" +#include "mads/scene.h" +#include "mads/nebular/game_nebular.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/nebular/nebular_scenes1.h" +#include "mads/nebular/nebular_scenes2.h" +#include "mads/nebular/nebular_scenes3.h" +#include "mads/nebular/nebular_scenes4.h" +#include "mads/nebular/nebular_scenes5.h" +#include "mads/nebular/nebular_scenes6.h" +#include "mads/nebular/nebular_scenes7.h" +#include "mads/nebular/nebular_scenes8.h" + +namespace MADS { + +namespace Nebular { + +SceneLogic *SceneFactory::createScene(MADSEngine *vm) { + Scene &scene = vm->_game->_scene; + + scene.addActiveVocab(NOUN_DROP); + scene.addActiveVocab(NOUN_DOLLOP); + scene.addActiveVocab(NOUN_DASH); + scene.addActiveVocab(NOUN_SPLASH); + scene.addActiveVocab(NOUN_ALCOHOL); + + switch (scene._nextSceneId) { + // Scene group #1 (ship, ocean, cave) + case 101: // Ship, cockpit + return new Scene101(vm); + case 102: // Ship, dining room + return new Scene102(vm); + case 103: // Ship, engine room + return new Scene103(vm); + case 104: // Ocean, northwest cliff + return new Scene104(vm); + case 105: // Ocean, northeast cliff with mine + return new Scene105(vm); + case 106: // Ocean, outside ship + return new Scene106(vm); + case 107: // Ocean, bushes + return new Scene107(vm); + case 108: // Ocean, southwest cliff + return new Scene108(vm); + case 109: // Ocean, tunnel + return new Scene109(vm); + case 110: // Ocean, cave with tunnel + return new Scene110(vm); + case 111: // Cave with pool and opening + return new Scene111(vm); + case 112: // cutscene, looking at view screen + return new Scene112(vm); + + // Scene group #2 (island) + case 201: // outside teleporter + return new Scene201(vm); + case 202: // village + return new Scene202(vm); + case 203: // tree with Rhotunda (fat woman) + return new Scene203(vm); + case 205: // village + return new Scene205(vm); + case 207: // outside witch doctor's hut + return new Scene207(vm); + case 208: // pit with leaves (trap) + return new Scene208(vm); + case 209: // palm tree and bamboo plant + return new Scene209(vm); + case 210: // outside native woman's hut + return new Scene210(vm); + case 211: // palm tree with monkey + return new Scene211(vm); + case 212: // outside cave + return new Scene212(vm); + case 213: // inside teleporter + return new Scene213(vm); + case 214: // inside witch doctor's hut + return new Scene214(vm); + case 215: // inside native woman's hut + return new Scene215(vm); + case 216: // cutscene, monitor showing Rex and native woman + return new Scene216(vm); + + // Scene group #3 (women's base, cell block) + case 301: // outside teleporter (before chaos) + return new Scene301(vm); + case 302: // room with statue (before chaos) + return new Scene302(vm); + case 303: // western corridor (before chaos) + return new Scene303(vm); + case 304: // crossing with traffic light (before chaos) + return new Scene304(vm); + case 307: // Rex's cell (before chaos) + return new Scene307(vm); + case 308: // sauropod's cell (before chaos) + return new Scene308(vm); + case 309: // multihand monster's cell (before chaos) + return new Scene309(vm); + case 310: // empty cell (before chaos) + return new Scene310(vm); + case 311: // warden's desk (before chaos) + return new Scene311(vm); + case 313: // air shaft overview + return new Scene313(vm); + case 316: // Gender Bender + return new Scene316(vm); + case 318: // doctor's gurney + return new Scene318(vm); + case 319: // doctor Slache closeup (lying on the gurney) + return new Scene319(vm); + case 320: // warden's desk closeup / monitors + return new Scene320(vm); + case 321: // gender bender sex change sequence + return new Scene321(vm); + case 322: // inside teleporter + return new Scene322(vm); + case 351: // outside teleporter (after chaos) + return new Scene351(vm); + case 352: // room with statue (after chaos) + return new Scene352(vm); + case 353: // western corridor (after chaos) + return new Scene353(vm); + case 354: // crossing with traffic light (after chaos) + return new Scene354(vm); + case 357: // Rex's cell (after chaos) + return new Scene357(vm); + case 358: // sauropod's cell (after chaos) + return new Scene358(vm); + case 359: // multihand monster's cell (after chaos) + return new Scene359(vm); + case 360: // empty cell (after chaos) + return new Scene360(vm); + case 361: // warden's desk (after chaos) + return new Scene361(vm); + case 366: // air shaft ending at Gender Bender + return new Scene366(vm); + case 387: // air shaft ending at cell + return new Scene387(vm); + case 388: // air shaft ending at sauropod's cell + return new Scene388(vm); + case 389: // air shaft ending at multihand monster's cell (before chaos) + return new Scene389(vm); + case 390: // air shaft ending at cell + return new Scene390(vm); + case 391: // air shaft ending at warden's desk + return new Scene391(vm); + case 399: // air shaft ending at multihand monster's cell (after chaos) + return new Scene399(vm); + + // Scene group #4 (women's base) + case 401: // outside bar + return new Scene401(vm); + case 402: // inside bar + return new Scene402(vm); + case 405: // outside armory + return new Scene405(vm); + case 406: // outside storage room + return new Scene406(vm); + case 407: // eastern corridor + return new Scene407(vm); + case 408: // inside armory + return new Scene408(vm); + case 409: // inside female only teleporter + return new Scene409(vm); + case 410: // inside storage room + return new Scene410(vm); + case 411: // lab + return new Scene411(vm); + case 413: // outside female only teleporter + return new Scene413(vm); + + // Scene group #5 (men's city, lower floor) + case 501: // outside car + return new Scene501(vm); + case 502: // inside male only teleporter + return new Scene502(vm); + case 503: // guard tower + return new Scene503(vm); + case 504: // inside car + return new Scene504(vm); + case 505: // car view screen + return new Scene505(vm); + case 506: // shopping street + return new Scene506(vm); + case 507: // inside software house + return new Scene507(vm); + case 508: // laser cannon + return new Scene508(vm); + case 511: // outside pleasure dome + return new Scene511(vm); + case 512: // inside pleasure dome + return new Scene512(vm); + case 513: // outside mall + return new Scene513(vm); + case 515: // overview + return new Scene515(vm); + case 551: // outside teleporter (with skeleton) + return new Scene551(vm); + + // Scene group #6 (men's city, upper floor) + case 601: // outside Bruce's house + return new Scene601(vm); + case 602: // Bruce's house, living room + return new Scene602(vm); + case 603: // Bruce's house, bedroom + return new Scene603(vm); + case 604: // viewport + return new Scene604(vm); + case 605: // viewport closeup + return new Scene605(vm); + case 607: // outside Abdul's garage + return new Scene607(vm); + case 608: // inside Abdul's garage + return new Scene608(vm); + case 609: // outside Buckluster video store + return new Scene609(vm); + case 610: // inside Buckluster video store + return new Scene610(vm); + case 611: // back alley + return new Scene611(vm); + case 612: // expressway / maintenance building + return new Scene612(vm); + case 620: // cutscene, viewport glass breaking + return new Scene620(vm); + + // Scene group #7 (submerged men's city / upper floor) + case 701: // outside elevator (after city is submerged) + return new Scene701(vm); + case 702: // outside teleporter (after city is submerged) + return new Scene702(vm); + case 703: // water + return new Scene703(vm); + case 704: // water, building in the distance + return new Scene704(vm); + case 705: // water, outside building + return new Scene705(vm); + case 706: // inside building, pedestral room, outside teleporter + return new Scene706(vm); + case 707: // teleporter + return new Scene707(vm); + case 710: // looking at pedestral room through binoculars + return new Scene710(vm); + case 711: // inside teleporter + return new Scene711(vm); + case 751: // outside elevator (before city is submerged) + return new Scene751(vm); + case 752: // outside teleporter (before city is submerged) + return new Scene752(vm); + + // Scene group #8 + case 801: // control room, outside teleporter + return new Scene801(vm); + case 802: // launch pad with destroyed ship + return new Scene802(vm); + case 803: // empty launch pad + return new Scene803(vm); + case 804: // inside Rex's ship - cockpit + return new Scene804(vm); + case 805: // service panel + return new Scene805(vm); + case 807: // teleporter + return new Scene807(vm); + case 808: // antigrav control + return new Scene808(vm); + case 810: // cutscene: Rex's ship leaving the planet + return new Scene810(vm); + + default: + error("Invalid scene %d called", scene._nextSceneId); + } +} + +/*------------------------------------------------------------------------*/ + +NebularScene::NebularScene(MADSEngine *vm) : SceneLogic(vm), + _globals(static_cast<GameNebular *>(vm->_game)->_globals), + _game(*static_cast<GameNebular *>(vm->_game)), + _action(vm->_game->_scene._action) { +} + +Common::String NebularScene::formAnimName(char sepChar, int suffixNum) { + return Resources::formatName(_scene->_currentSceneId, sepChar, suffixNum, + EXT_NONE, ""); +} + +/*------------------------------------------------------------------------*/ + +void SceneInfoNebular::loadCodes(MSurface &depthSurface, int variant) { + File f(Resources::formatName(RESPREFIX_RM, _sceneId, ".DAT")); + MadsPack codesPack(&f); + Common::SeekableReadStream *stream = codesPack.getItemStream(variant + 1); + + loadCodes(depthSurface, stream); + + delete stream; + f.close(); +} + +void SceneInfoNebular::loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream) { + byte *destP = depthSurface.getData(); + byte *endP = depthSurface.getBasePtr(0, depthSurface.h); + + byte runLength = stream->readByte(); + while (destP < endP && runLength > 0) { + byte runValue = stream->readByte(); + + // Write out the run length + Common::fill(destP, destP + runLength, runValue); + destP += runLength; + + // Get the next run length + runLength = stream->readByte(); + } + + if (destP < endP) + Common::fill(destP, endP, 0); +} + +/*------------------------------------------------------------------------*/ + +SceneTeleporter::SceneTeleporter(MADSEngine *vm) : NebularScene(vm) { + _buttonTyped = -1; + _curCode = -1; + _digitCount = -1; + _curMessageId = -1; + _handSpriteId = -1; + _handSequenceId = -1; + _finishedCodeCounter = -1; + _meteorologistNextPlace = -1; + _meteorologistCurPlace = -1; + _teleporterSceneId = -1; +} + +int SceneTeleporter::teleporterAddress(int code, bool working) { + int limit = working ? 6 : 10; + + for (int i = 0; i < limit; i++) { + if (code == _globals[kTeleporterCode + i]) + return _globals[kTeleporterRoom + i]; + } + + return -1; +} + +Common::Point SceneTeleporter::teleporterComputeLocation() { + Common::Point result; + + switch (_buttonTyped) { + case 0: + result = Common::Point(179, 200); + break; + + case 1: + result = Common::Point(166, 170); + break; + + case 2: + result = Common::Point(179, 170); + break; + + case 3: + result = Common::Point(192, 170); + break; + + case 4: + result = Common::Point(166, 180); + break; + + case 5: + result = Common::Point(179, 180); + break; + + case 6: + result = Common::Point(192, 180); + break; + + case 7: + result = Common::Point(166, 190); + break; + + case 8: + result = Common::Point(179, 190); + break; + + case 9: + result = Common::Point(192, 190); + break; + + case 10: + result = Common::Point(194, 200); + break; + + case 11: + result = Common::Point(164, 200); + break; + + default: + error("teleporterComputeLocation() - Unexpected button pressed"); + } + + return result; +} + +void SceneTeleporter::teleporterHandleKey() { + switch (_game._trigger) { + case 0: { + _game._player._stepEnabled = false; + Common::Point msgPos = teleporterComputeLocation(); + _handSequenceId = _scene->_sequences.startReverseCycle(_handSpriteId, false, 4, 2, 0, 0); + _scene->_sequences.setPosition(_handSequenceId, msgPos); + _scene->_sequences.setDepth(_handSequenceId, 2); + _scene->_sequences.addSubEntry(_handSequenceId, SEQUENCE_TRIGGER_LOOP, 0, 1); + _scene->_sequences.addSubEntry(_handSequenceId, SEQUENCE_TRIGGER_EXPIRE, 0, 2); + + if (_globals[kMeteorologistWatch] == METEOROLOGIST_NORMAL) + _vm->_events->hideCursor(); + + } + break; + + case 1: + _scene->_sequences.addSubEntry(_handSequenceId, SEQUENCE_TRIGGER_SPRITE, 3, 3); + if (_buttonTyped <= 9) { + if (_digitCount < 4) { + _curCode *= 10; + _curCode += _buttonTyped; + _digitCount++; + _msgText = Common::String::format("%d", _curCode); + if (_digitCount < 4) + _msgText += "_"; + + if (_scene->_currentSceneId != 711) + _vm->_sound->command(32); + } + } else if (_buttonTyped == 11) { + _digitCount = 0; + _curCode = 0; + _msgText = "_"; + if (_scene->_currentSceneId != 711) + _vm->_sound->command(33); + } else if (_digitCount == 4) { + if (_scene->_currentSceneId != 711) + _finishedCodeCounter = 1; + + if (teleporterAddress(_curCode, true) > 0) { + _vm->_palette->setEntry(252, 0, 63, 0); + if (_scene->_currentSceneId != 711) + _vm->_sound->command(34); + } else { + _vm->_palette->setEntry(252, 63, 0, 0); + if (_scene->_currentSceneId != 711) + _vm->_sound->command(35); + } + } + + if (_scene->_currentSceneId != 711) { + if (_curMessageId >= 0) + _scene->_kernelMessages.remove(_curMessageId); + _curMessageId = _scene->_kernelMessages.add(Common::Point(143, 61), 0xFDFC, 16, 0, 9999999, _msgText); + } + break; + + case 2: + if (_finishedCodeCounter == 1) { + _finishedCodeCounter++; + + if (_globals[kMeteorologistWatch] != METEOROLOGIST_NORMAL) + _scene->_nextSceneId = 202; + else { + _vm->_events->showCursor(); + int destination = teleporterAddress(_curCode, true); + + if (destination > 0) { + _globals[kTeleporterCommand] = 2; + _scene->_nextSceneId = _teleporterSceneId; + _globals[kTeleporterDestination] = destination; + } else { + _globals[kTeleporterCommand] = 4; + _scene->_nextSceneId = _teleporterSceneId; + } + } + } else if (_globals[kMeteorologistWatch] != METEOROLOGIST_NORMAL) + _scene->_sequences.addTimer(30, 230 + _meteorologistCurPlace); + + break; + + case 3: + if (!_finishedCodeCounter) { + if (_globals[kMeteorologistWatch] == METEOROLOGIST_NORMAL) { + _game._player._stepEnabled = true; + _vm->_events->showCursor(); + } + } + break; + + default: + break; + } +} + +void SceneTeleporter::teleporterEnter() { + _game._player._visible = false; + _game._player._stepEnabled = (_globals[kMeteorologistWatch] == METEOROLOGIST_NORMAL); + _scene->_kernelMessages._talkFont = _vm->_font->getFont(FONT_TELE); + _scene->_textSpacing = 0; + _curCode = 0; + _digitCount = 0; + _finishedCodeCounter = 0; + _curMessageId = -1; + _msgText = "_"; + + if (_scene->_priorSceneId == -2) + _scene->_priorSceneId = _globals[kTeleporterDestination]; + + if (_scene->_priorSceneId < 101) + _scene->_priorSceneId = 201; + + _globals[kTeleporterDestination] = _scene->_priorSceneId; + _vm->_palette->setEntry(252, 63, 63, 0); + _vm->_palette->setEntry(253, 0, 0, 0); + _teleporterSceneId = _scene->_priorSceneId; + if (_teleporterSceneId == 202) + _teleporterSceneId = 201; + + int tmpVal = 0; + for (int i = 0; i < 10; i++) { + if (_teleporterSceneId == _globals[kTeleporterRoom + i]) + tmpVal = _globals[kTeleporterRoom + i]; + + if (_globals[kTeleporterRoom + i] == 301) + _meteorologistNextPlace = _globals[kTeleporterCode + i]; + } + + Common::String msgText2 = Common::String::format("#%.4d", tmpVal); + + if (_scene->_currentSceneId != 711) { + _scene->_kernelMessages.add(Common::Point(133, 34), 0, 32, 0, 9999999, msgText2); + _scene->_kernelMessages.add(Common::Point(143, 61), 0xFDFC, 16, 0, 9999999, _msgText); + } + + _meteorologistCurPlace = 0; + + if (_globals[kMeteorologistWatch] != METEOROLOGIST_NORMAL) + _scene->_sequences.addTimer(30, 230); + + _vm->_sound->command(36); +} + +bool SceneTeleporter::teleporterActions() { + bool retVal = false; + static int _buttonList[12] = { NOUN_0_KEY, NOUN_1_KEY, NOUN_2_KEY, NOUN_3_KEY, NOUN_4_KEY, NOUN_5_KEY, NOUN_6_KEY, NOUN_7_KEY, NOUN_8_KEY, NOUN_9_KEY, NOUN_SMILE_KEY, NOUN_FROWN_KEY }; + + if (_action.isAction(VERB_PRESS) || _action.isAction(VERB_PUSH)) { + for (int i = 0; i < 12; i++) { + if (_action._activeAction._objectNameId == _buttonList[i]) + _buttonTyped = i; + } + teleporterHandleKey(); + retVal = true; + } + + if (_action.isAction(VERB_EXIT_FROM, NOUN_DEVICE)) { + _globals[kTeleporterCommand] = 3; + _scene->_nextSceneId = _teleporterSceneId; + retVal = true; + } + + return (retVal); +} + +void SceneTeleporter::teleporterStep() { + if (_globals[kMeteorologistWatch] == METEOROLOGIST_NORMAL) + return; + + if (_game._trigger >= 230) { + int place = _game._trigger - 230; + int digit; + + if (place < 4) { + digit = _meteorologistNextPlace; + for (int i = 0; i < (3 - place); i++) + digit = digit / 10; + + digit = digit % 10; + } else { + digit = 10; + } + _buttonTyped = digit; + _meteorologistCurPlace = place + 1; + _game._trigger = -1; + } + + if (_game._trigger) { + if (_game._trigger == -1) + _game._trigger = 0; + teleporterHandleKey(); + } +} + +} // End of namespace Nebular + +} // End of namespace MADS diff --git a/engines/mads/nebular/nebular_scenes.h b/engines/mads/nebular/nebular_scenes.h new file mode 100644 index 0000000000..6195395fd6 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes.h @@ -0,0 +1,1417 @@ +/* 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. + * + */ + +#ifndef MADS_NEBULAR_SCENES_H +#define MADS_NEBULAR_SCENES_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/scene.h" +#include "mads/nebular/game_nebular.h" +#include "mads/nebular/globals_nebular.h" + + +namespace MADS { + +namespace Nebular { + +enum { + SEX_MALE = 0, SEX_UNKNOWN = 1, SEX_FEMALE = 2 +}; + +enum Verb { + VERB_ACTIVATE = 0x00E, + VERB_ATTACH = 0x019, + VERB_BREAK = 0x032, + VERB_BREATHE_AIR = 0x033, + VERB_CAST = 0x03D, + VERB_CLIMB_DOWN = 0x04E, + VERB_CLIMB_THROUGH = 0x04F, + VERB_CLIMB_UP = 0x050, + VERB_CUT = 0x061, + VERB_DAMPEN = 0x064, + VERB_DISASSEMBLE = 0x06C, + VERB_DIVE_INTO = 0x06D, + VERB_DRINK = 0x072, + VERB_EAT = 0x075, + VERB_EJECT = 0x076, + VERB_EMPTY = 0x077, + VERB_EXAMINE = 0x07D, + VERB_FILL = 0x085, + VERB_FONDLE = 0x08C, + VERB_HOSE_DOWN = 0x0A6, + VERB_IGNITE = 0x0B4, + VERB_INFLATE = 0x0B5, + VERB_INSERT = 0x0B6, + VERB_INSPECT = 0x0B7, + VERB_GNAW_ON = 0x098, + VERB_GORGE_ON = 0x099, + VERB_HURL = 0x0A9, + VERB_LICK = 0x0CB, + VERB_LOOK_AT = 0x0D1, + VERB_LOOK_IN = 0x0D2, + VERB_LOOK_THROUGH = 0x0D3, + VERB_PEER_THROUGH = 0x103, + VERB_PLAY = 0x112, + VERB_PRESS = 0x11A, + VERB_PRY = 0x11C, + VERB_READ = 0x11F, + VERB_SET = 0x132, + VERB_SHAKE_HANDS = 0x133, + VERB_SHARPEN = 0x134, + VERB_SHOOT = 0x13A, + VERB_SIT_IN = 0x13F, + VERB_SMELL = 0x147, + VERB_SNIFF = 0x149, + VERB_STARE_AT = 0x155, + VERB_SWIM_ACROSS = 0x159, + VERB_SWIM_INTO = 0x15A, + VERB_SWIM_THROUGH = 0x15B, + VERB_SWIM_TO = 0x15C, + VERB_SWIM_TOWARDS = 0x15D, + VERB_SWIM_UNDER = 0x15E, + VERB_TIE = 0x170, + VERB_UNLOCK = 0x17B, + VERB_WALK_ACROSS = 0x187, + VERB_WALK_INSIDE = 0x188, + VERB_WALK_OUTSIDE = 0x18A, + VERB_WALK_THROUGH = 0x18B, + VERB_WALK_TOWARDS = 0x18C, + VERB_WEAR = 0x191, + VERB_WALK_DOWN = 0x1AD, + VERB_LEAVE = 0x1CD, + VERB_EXIT_FROM = 0x1CE, + VERB_USE = 0x20C, + VERB_GAZE_INTO = 0x212, + VERB_SIT_AT = 0x21F, + VERB_WALK_UP = 0x227, + VERB_WALK_INTO = 0x242, + VERB_EXIT = 0x298, + VERB_WALK_ONTO = 0x2B5, + VERB_RETURN_TO = 0x2D5, + VERB_CLIMB_INTO = 0x2F7, + VERB_STEP_INTO = 0x2F9, + VERB_CRAWL_TO = 0x2FB, + VERB_CRAWL_DOWN = 0x301, + VERB_SIT_ON = 0x30B, + VERB_WALK_ALONG = 0x312, + VERB_GET_INSIDE = 0x325, + VERB_WALK = 0x32F, + VERB_REFLECT = 0x365, + VERB_GET_INTO = 0x36A, + VERB_APPLY = 0x3A6, + VERB_STEER_TOWARDS = 0x3B1, + VERB_NIBBLE_ON = 0x3B7, + VERB_ENTER = 0x3B8, + VERB_PUT_DOWN = 0x46F, + VERB_INSTALL = 0x474, + VERB_REMOVE = 0x476, + VERB_DEFACE = 0x489, + VERB_MASSAGE = 0x4A3, + VERB_MANGLE = 0x4A4, + VERB_RUB = 0x4A5, + VERB_JUGGLE = 0x4A6, + VERB_SMASH = 0x4A7, + VERB_GUZZLE = 0x4A8, + VERB_FOLD = 0x4AB, + VERB_SPINDLE = 0x4AC, + VERB_MUTILATE = 0x4AD +}; + +enum Noun { + //NOUN_GAME = 0x1, + //NOUN_QSAVE = 0x2, + //NOUN_LOOK = 0x3, + //NOUN_TAKE = 0x4, + //NOUN_PUSH = 0x5, + //NOUN_OPEN = 0x6, + //NOUN_PUT = 0x7, + //NOUN_TALK_TO = 0x8, + //NOUN_GIVE = 0x9, + //NOUN_PULL = 0xA, + //NOUN_CLOSE = 0xB, + //NOUN_THROW = 0xC, + //NOUN_WALK_TO = 0xD, + //NOUN_ACTIVATE = 0xE, + //NOUN_ADMIRE = 0xF, + NOUN_ADSM = 0x10, + NOUN_AIR_VENT = 0x11, + NOUN_ALOE_PLANT = 0x12, + NOUN_ANEMONE = 0x13, + NOUN_ANOMOMETER = 0x14, + NOUN_AREA_AROUND_HUT = 0x15, + NOUN_AREA_TO_SOUTH = 0x16, + NOUN_AREA_TO_WEST = 0x17, + NOUN_AROMATIC_MEAT = 0x18, + //NOUN_ATTACH = 0x19, + NOUN_AUDIO_TAPE = 0x1A, + NOUN_AUXILIARY_POWER = 0x1B, + NOUN_BADMITTON_BRAT = 0x1C, + NOUN_BAG = 0x1D, + NOUN_BAMBOO_TREE = 0x1E, + NOUN_BATS = 0x1F, + NOUN_BAWLEMER_ORIOLE_HUN = 0x20, + NOUN_BEAR_RUG = 0x21, + NOUN_BEASTLY_TROPHY = 0x22, + NOUN_BIG_LEAVES = 0x23, + NOUN_BIG_PIPES = 0x24, + NOUN_BIG_SKY = 0x25, + NOUN_BIG_STONE = 0x26, + NOUN_BINOCULARS = 0x27, + NOUN_BIRDIES = 0x28, + NOUN_BLOWGUN = 0x29, + NOUN_BOMB = 0x2A, + NOUN_BOMBS = 0x2B, + NOUN_BONE = 0x2C, + NOUN_BONES = 0x2D, + NOUN_BOTTLE = 0x2E, + NOUN_BOULDER = 0x2F, + NOUN_BOULDERS = 0x30, + NOUN_BRA = 0x31, + //NOUN_BREAK = 0x32, + //NOUN_BREATHE_AIR = 0x33, + NOUN_BULKHEAD = 0x34, + NOUN_BURGER = 0x35, + NOUN_BURN = 0x36, + NOUN_BURNT_OUT_WARP_COIL = 0x37, + NOUN_BUSH_LIKE_FORMATION = 0x38, + NOUN_BUSHES = 0x39, + NOUN_BUSHY_FERN = 0x3A, + NOUN_CACTUS = 0x3B, + NOUN_CARD = 0x3C, + //NOUN_CAST = 0x3D, + NOUN_CAULDRON = 0x3E, + NOUN_CAVE = 0x3F, + NOUN_CAVE_CEILING = 0x40, + NOUN_CAVE_ENTRANCE = 0x41, + NOUN_CAVE_EXIT = 0x42, + NOUN_CAVE_FLOOR = 0x43, + NOUN_CAVE_TO_EAST = 0x44, + NOUN_CAVE_WALL = 0x45, + NOUN_CEILING = 0x46, + NOUN_CHAIR = 0x47, + NOUN_CHARGE_CASES = 0x48, + NOUN_CHICKEN = 0x49, + NOUN_CHICKEN_BOMB = 0x4A, + NOUN_CLEARING_TO_EAST = 0x4B, + NOUN_CLEARING_TO_SOUTH = 0x4C, + NOUN_CLIFF_FACE = 0x4D, + NOUN_CLIMB_DOWN = 0x4E, + NOUN_CLIMB_THROUGH = 0x4F, + NOUN_CLIMB_UP = 0x50, + NOUN_CLOCK = 0x51, + NOUN_CLOSET = 0x52, + NOUN_CLOTHESLINE = 0x53, + NOUN_CLUMP_OF_TREES = 0x54, + NOUN_COAL = 0x55, + NOUN_COCOANUT = 0x56, + NOUN_COMPACT_CASE = 0x57, + NOUN_COMPUTER_GAME = 0x58, + NOUN_CONTROL_PANEL = 0x59, + NOUN_CORAL = 0x5A, + NOUN_CRAB = 0x5B, + NOUN_CREDIT_CHIP = 0x5C, + NOUN_CUMULOUS_CLOUD = 0x5D, + NOUN_CURIOUS_WEED_PATCH = 0x5E, + NOUN_CURTAIN = 0x5F, + NOUN_CURTAINS = 0x60, + //NOUN_CUT = 0x61, + NOUN_DAMAGE_CONTROL = 0x62, + NOUN_DAMAGE_CONTROL_PANEL = 0x63, + //NOUN_DAMPEN = 0x64, + NOUN_DEAD_FISH = 0x65, + NOUN_DEAD_PURPLE_MONSTER = 0x66, + NOUN_DECLIVITOUS_CHASM = 0x67, + NOUN_DEEP_DARK_FOREST = 0x68, + NOUN_DENSE_FOREST = 0x69, + NOUN_DETONATORS = 0x6A, + NOUN_DINO_MITE = 0x6B, + //NOUN_DISASSEMBLE = 0x6C, + //NOUN_DIVE_INTO = 0x6D, + NOUN_DOOR = 0x6E, + NOUN_DOOR_KEY = 0x6F, + NOUN_DOORWAY = 0x70, + NOUN_DRAWER = 0x71, + //NOUN_DRINK = 0x72, + NOUN_DURAFAIL_CELLS = 0x73, + NOUN_EASTERN_CLIFF_FACE = 0x74, + //NOUN_EAT = 0x75, + //NOUN_EJECT = 0x76, + //NOUN_EMPTY = 0x77, + NOUN_ENGINEERING_CONTROLS = 0x78, + NOUN_ENGINEERING_SECTION = 0x79, + NOUN_ENTER_KEY = 0x7A, + NOUN_ESCAPE_HATCH = 0x7B, + NOUN_ESTROTOXIN = 0x7C, + //NOUN_EXAMINE = 0x7D, + NOUN_EXPERIMENT_CAGE = 0x7E, + NOUN_EXTINGUISH = 0x7F, + NOUN_FACE_ID = 0x80, + NOUN_FERN = 0x81, + NOUN_FIELD_TO_NORTH = 0x82, + NOUN_FIELD_TO_SOUTH = 0x83, + NOUN_FIELD_TO_WEST = 0x84, + //NOUN_FILL = 0x85, + NOUN_FIRE_PIT = 0x86, + NOUN_FISHING_LINE = 0x87, + NOUN_FISHING_ROD = 0x88, + NOUN_FLOOR = 0x89, + NOUN_FLOOR_OF_HUT = 0x8A, + NOUN_FLOOR_TILE = 0x8B, + //NOUN_FONDLE = 0x8C, + NOUN_FOREST_TO_EAST = 0x8D, + NOUN_FRONT_WINDOW = 0x8E, + NOUN_FUNGOIDS = 0x8F, + NOUN_FURNACE = 0x90, + NOUN_FUZZY_DICE = 0x91, + //NOUN_GAZE = 0x92, + //NOUN_GAZE_AT = 0x93, + //NOUN_GAZE_IN = 0x94, + //NOUN_GLANCE_AT = 0x95, + NOUN_GLOVE = 0x96, + NOUN_GNARLY_SHRUB = 0x97, + //NOUN_GNAW_ON = 0x98, + //NOUN_GORGE_ON = 0x99, + NOUN_GRAIN_ALCHOHOL = 0x9A, + NOUN_GRASSLAND_TO_EAST = 0x9B, + NOUN_GRASSLAND_TO_SOUTH = 0x9C, + NOUN_GRASSY_AREA = 0x9D, + NOUN_GRASSY_AREA_TO_NORTH = 0x9E, + NOUN_GRASSY_KNOLL = 0x9F, + //NOUN_GRIND = 0xA0, + NOUN_GROOVILACTIC_TREE = 0xA1, + NOUN_GUARDS_ARM = 0xA2, + NOUN_HATCHWAY = 0xA3, + //NOUN_HOOK_UP = 0xA4, + NOUN_HORIZON = 0xA5, + //NOUN_HOSE_DOWN = 0xA6, + NOUN_HOTPANTS = 0xA7, + NOUN_HULL = 0xA8, + //NOUN_HURL = 0xA9, + NOUN_HUT = 0xAA, + NOUN_HUT_AREA = 0xAB, + NOUN_HUT_TO_EAST = 0xAC, + NOUN_HUT_TO_SOUTH = 0xAD, + NOUN_HUT_TO_THE_SOUTH = 0xAE, + NOUN_HUT_TO_WEST = 0xAF, + NOUN_HUTS_TO_NORTH = 0xB0, + NOUN_HYDROSPANNER = 0xB1, + NOUN_HYPERDRIVE_JUMP_UNIT = 0xB2, + NOUN_ID_CARD = 0xB3, + //NOUN_IGNITE = 0xB4, + //NOUN_INFLATE = 0xB5, + //NOUN_INSERT = 0xB6, + //NOUN_INSPECT = 0xB7, + NOUN_JUNGLE = 0xB8, + NOUN_JUNGLE_TO_EAST = 0xB9, + NOUN_JUNGLE_TO_WEST = 0xBA, + NOUN_KEY_1 = 0xBB, + NOUN_KEY_2 = 0xBC, + NOUN_KEY_3 = 0xBD, + NOUN_KEY_4 = 0xBE, + NOUN_KEY_5 = 0xBF, + NOUN_KEY_6 = 0xC0, + NOUN_KEY_7 = 0xC1, + NOUN_KEY_8 = 0xC2, + NOUN_KEY_9 = 0xC3, + NOUN_KEYPAD = 0xC4, + NOUN_KNEELING_WOMAN = 0xC5, + NOUN_KNIFE = 0xC6, + NOUN_LADDER = 0xC7, + NOUN_LARGE_STALAGMITE = 0xC8, + //NOUN_LEER_AT = 0xC9, + NOUN_LIBRARY_COMPUTER = 0xCA, + //NOUN_LICK = 0xCB, + NOUN_LIFE_SUPPORT_SECTION = 0xCC, + NOUN_LIGHT = 0xCD, + //NOUN_LOAD = 0xCE, + //NOUN_LOCK = 0xCF, + NOUN_LOG = 0xD0, + //NOUN_LOOK_AT = 0xD1, + //NOUN_LOOK_IN = 0xD2, + //NOUN_LOOK_THROUGH = 0xD3, + NOUN_LOUNGE_AREA = 0xD4, + NOUN_LOVE_ALTAR = 0xD5, + NOUN_LOWLANDS = 0xD6, + NOUN_MACHINE = 0xD7, + NOUN_MAGNET = 0xD8, + NOUN_MAIN_AIRLOCK = 0xD9, + NOUN_MANTA_RAY = 0xDA, + NOUN_MARSHY_WETLANDS = 0xDB, + NOUN_MATCH = 0xDC, + NOUN_MEDICAL_WASTE = 0xDD, + NOUN_MEDICINE_CABINET = 0xDE, + NOUN_MEN_WHO_CAME_BEFORE = 0xDF, + NOUN_MINE = 0xE0, + NOUN_MIRROR = 0xE1, + NOUN_MONITOR = 0xE2, + NOUN_MONKEY = 0xE3, + NOUN_MONKEY_LIVER_JUICE = 0xE4, + NOUN_MONSTER_SLUDGE = 0xE5, + NOUN_MOUNTAIN = 0xE6, + NOUN_MOUNTAIN_RANGE = 0xE7, + NOUN_MOUNTAINS = 0xE8, + NOUN_MTAM = 0xE9, + NOUN_MUSHROOMS = 0xEA, + NOUN_NAVIGATION_CONTROLS = 0xEB, + NOUN_NORTH_PATH = 0xEC, + NOUN_NORTHERN_EXPOSURE = 0xED, + NOUN_NORTHERN_SEA_CLIFF = 0xEE, + NOUN_OBSTACLE = 0xEF, + NOUN_OCEAN_FLOOR = 0xF0, + NOUN_ODD_ROCK_FORMATION = 0xF1, + NOUN_OOGLY_BOOGLY_JUICE = 0xF2, + NOUN_OPEN_AREA_TO_EAST = 0xF3, + NOUN_OPEN_AREA_TO_NORTH = 0xF4, + NOUN_OPEN_AREA_TO_SOUTH = 0xF5, + NOUN_OPEN_AREA_TO_WEST = 0xF6, + NOUN_OPEN_FIELD = 0xF7, + NOUN_OUTER_HULL = 0xF8, + NOUN_OUTSIDE = 0xF9, + NOUN_OVEN = 0xFA, + NOUN_OVERHANG_TO_EAST = 0xFB, + NOUN_OVERHANG_TO_WEST = 0xFC, + NOUN_OVERHEAD_LAMP = 0xFD, + NOUN_PAD_OF_PAPER = 0xFE, + NOUN_PADLOCK_KEY = 0xFF, + NOUN_PALM_TREE = 0x100, + NOUN_PASSAGE_WAY_TO_SOUTH = 0x101, + NOUN_PASSION_PUSS = 0x102, + NOUN_PEER_THROUGH = 0x103, + NOUN_PENCIL = 0x104, + NOUN_PENDULOUS_CRAG = 0x105, + NOUN_PENLIGHT = 0x106, + NOUN_PHONE_CELLS = 0x107, + NOUN_PHONE_HANDSET = 0x108, + NOUN_PILE_OF_ROCKS = 0x109, + NOUN_PILLOW = 0x10A, + NOUN_PILOTS_CHAIR = 0x10B, + NOUN_PIPE = 0x10C, + NOUN_PIRANHA = 0x10D, + NOUN_PLANT = 0x10E, + NOUN_PLANT_STALK = 0x10F, + NOUN_PLANTS = 0x110, + NOUN_PLASTIC_JESUS = 0x111, + //NOUN_PLAY = 0x112, + NOUN_PLUNGER = 0x113, + NOUN_POISON_DARTS = 0x114, + NOUN_POLYCEMENT = 0x115, + NOUN_POOL = 0x116, + NOUN_POSTER = 0x117, + NOUN_POWER_STATUS_PANEL = 0x118, + NOUN_PRECIPICE = 0x119, + //NOUN_PRESS = 0x11A, + NOUN_PRESSURE_GAUGE = 0x11B, + //NOUN_PRY = 0x11C, + NOUN_RAGING_RIVER = 0x11D, + NOUN_RAMOLYAN_RUGBY_RATS = 0x11E, + //NOUN_READ = 0x11F, + NOUN_REARVIEW_MIRROR = 0x120, + NOUN_REBREATHER = 0x121, + NOUN_REFRIGERATOR = 0x122, + NOUN_REMOTE = 0x123, + NOUN_REPAIR_LIST = 0x124, + NOUN_RIVER = 0x125, + NOUN_RIVER_TO_WEST = 0x126, + NOUN_ROBO_KITCHEN = 0x127, + NOUN_ROCK = 0x128, + NOUN_ROCKS = 0x129, + NOUN_ROCKY_AREA = 0x12A, + NOUN_ROLLING_HILL = 0x12B, + NOUN_SCALPEL = 0x12C, + NOUN_SCENIC_MOUNTAINS = 0x12D, + NOUN_SEA_CLIFF = 0x12E, + NOUN_SEAWEED = 0x12F, + NOUN_SEAWEED_BANK = 0x130, + NOUN_SECURITY_CARD = 0x131, + //NOUN_SET = 0x132, + //NOUN_SHAKE_HANDS = 0x133, + //NOUN_SHARPEN = 0x134, + NOUN_SHIELD_ACCESS_PANEL = 0x135, + NOUN_SHIELD_GENERATOR = 0x136, + NOUN_SHIELD_MODULATOR = 0x137, + NOUN_SHIELD_STATUS_PANEL = 0x138, + NOUN_SHIP = 0x139, + //NOUN_SHOOT = 0x13A, + NOUN_SHOVEL = 0x13B, + //NOUN_SHRED = 0x13C, + NOUN_SHRUNKEN_HEADS = 0x13D, + NOUN_SINGED_MEAT = 0x13E, + //NOUN_SIT_IN = 0x13F, + NOUN_SKULL = 0x140, + NOUN_SKULL_AND_CROSSBONES = 0x141, + NOUN_SKY = 0x142, + //NOUN_SLEEP_ON = 0x143, + NOUN_SLITHERING_SNAKE = 0x144, + NOUN_SLUG_SECRETION = 0x145, + NOUN_SMALL_HOLE = 0x146, + //NOUN_SMELL = 0x147, + NOUN_SNAKE = 0x148, + //NOUN_SNIFF = 0x149, + //NOUN_SOAK = 0x14A, + NOUN_SPECIAL_KEY_1 = 0x14B, + NOUN_SPECIAL_KEY_2 = 0x14C, + NOUN_SPIDER = 0x14D, + NOUN_SPILT_MILK = 0x14E, + NOUN_SPIT_FIRE = 0x14F, + //NOUN_SPRAY = 0x150, + //NOUN_STAB = 0x151, + NOUN_STAIRS = 0x152, + NOUN_STALAGMITES = 0x153, + //NOUN_STAND_INSIDE = 0x154, + //NOUN_STARE_AT = 0x155, + NOUN_STEPS = 0x156, + NOUN_STUFFED_FISH = 0x157, + NOUN_SURFACE = 0x158, + //NOUN_SWIM_ACROSS = 0x159, + //NOUN_SWIM_INTO = 0x15A, + //NOUN_SWIM_THROUGH = 0x15B, + //NOUN_SWIM_TO = 0x15C, + //NOUN_SWIM_TOWARDS = 0x15D, + //NOUN_SWIM_UNDER = 0x15E, + NOUN_SWOOPING_CREATURE = 0x15F, + NOUN_TABLE = 0x160, + //NOUN_TAKE_LIVER = 0x161, + //NOUN_TAKE_OFF = 0x162, + //NOUN_TAKE_PAGE = 0x163, + NOUN_TALL_GRASS = 0x164, + NOUN_TAPE_PLAYER = 0x165, + NOUN_TARGET_COMPUTER = 0x166, + NOUN_TARGET_MODULE = 0x167, + NOUN_TARGETTING_COMPUTER = 0x168, + NOUN_TASMANIAN_DEVIL = 0x169, + NOUN_TASTY_TURKEY = 0x16A, + NOUN_TELEPORT_DEVICE = 0x16B, + NOUN_TELEPORTER = 0x16C, + NOUN_THATCHED_ROOF = 0x16D, + NOUN_THORNS = 0x16E, + NOUN_THORNY_BUSH = 0x16F, + //NOUN_TIE = 0x170, + NOUN_TIMEBOMB = 0x171, + NOUN_TIMER = 0x172, + NOUN_TIMER_MODULE = 0x173, + NOUN_TREE = 0x174, + NOUN_TREES = 0x175, + NOUN_TRODDEN_PATH = 0x176, + NOUN_TUBE = 0x177, + NOUN_TUNNEL = 0x178, + NOUN_TWINKIE_BUSH = 0x179, + NOUN_TWINKIFRUIT = 0x17A, + //NOUN_UNLOCK = 0x17B, + NOUN_UZI = 0x17C, + NOUN_VASE = 0x17D, + NOUN_VIDEO_GAME = 0x17E, + //NOUN_VIEW = 0x17F, + NOUN_VIEW_SCREEN = 0x180, + NOUN_VIEWPORT = 0x181, + NOUN_VILLAGE_AREA = 0x182, + NOUN_VILLAGE_TO_WEST = 0x183, + NOUN_VOLCANO = 0x184, + NOUN_VULTURE = 0x185, + NOUN_WAD_OF_CATTLE_PARTS = 0x186, + //NOUN_WALK_ACROSS = 0x187, + //NOUN_WALK_INSIDE = 0x188, + //NOUN_WALK_ON = 0x189, + //NOUN_WALK_OUTSIDE = 0x18A, + //NOUN_WALK_THROUGH = 0x18B, + //NOUN_WALK_TOWARDS = 0x18C, + NOUN_WALL = 0x18D, + NOUN_WATCH_TOWER = 0x18E, + NOUN_WATER = 0x18F, + NOUN_WEAPONS_DISPLAY = 0x190, + //NOUN_WEAR = 0x191, + NOUN_WEATHER_STATION = 0x192, + NOUN_WEATHER_VANE = 0x193, + NOUN_WEIGHT_MACHINE = 0x194, + NOUN_WESTERN_CLIFF_FACE = 0x195, + NOUN_WHEEL = 0x196, + NOUN_WINDOW = 0x197, + NOUN_WITCHDOCTOR_HUT = 0x198, + NOUN_WORKBENCH = 0x199, + //NOUN_WRITE_ON = 0x19A, + NOUN_YELLOW_BIRDY = 0x19B, + NOUN_GRASS = 0x19C, + NOUN_BOUNCING_REPTILE = 0x19D, + NOUN_DEEP_PIT = 0x19E, + NOUN_LOWLANDS_TO_NORTH = 0x19F, + NOUN_SMALL_BUSH = 0x1A0, + NOUN_SMALL_CACTUS = 0x1A1, + NOUN_ROCKY_AREA_TO_NORTH = 0x1A2, + NOUN_BAMBOO_LIKE_PLANT = 0x1A3, + NOUN_MOUNTAINSIDE = 0x1A4, + NOUN_FIELD = 0x1A5, + NOUN_GRASSY_FIELD = 0x1A6, + NOUN_CRAG = 0x1A7, + NOUN_HUGE_LEGS = 0x1A8, + NOUN_LEAF_COVERED_PIT = 0x1A9, + NOUN_PILE_OF_LEAVES = 0x1AA, + NOUN_OPEN_FIELD_TO_EAST = 0x1AB, + NOUN_LAWN = 0x1AC, + //NOUN_WALK_DOWN = 0x1AD, + NOUN_PATH_TO_WEST = 0x1AE, + NOUN_HEDGE = 0x1AF, + NOUN_VILLAGE_PATH = 0x1B0, + NOUN_PATH_TO_NORTHEAST = 0x1B1, + NOUN_JUNGLE_PATH = 0x1B2, + NOUN_THICK_UNDERGROWTH = 0x1B3, + NOUN_OCEAN = 0x1B4, + NOUN_OCEAN_IN_DISTANCE = 0x1B5, + NOUN_STRANGE_DEVICE = 0x1B6, + NOUN_BUSH = 0x1B7, + NOUN_ANEMOMETER = 0x1B8, + NOUN_ISLAND_IN_DISTANCE = 0x1B9, + NOUN_PATH = 0x1BA, + NOUN_TROPHY = 0x1BB, + NOUN_SPECIMEN_JARS = 0x1BC, + NOUN_BOWL = 0x1BD, + NOUN_LARGE_BOWL = 0x1BE, + NOUN_PATH_TO_NORTH = 0x1BF, + NOUN_HUT_TO_NORTH = 0x1C0, + NOUN_PATH_TO_EAST = 0x1C1, + NOUN_CHICKEN_ON_SPIT = 0x1C2, + NOUN_CAPTIVE_CREATURE = 0x1C3, + NOUN_TWINKIFRUIT_BUSH = 0x1C4, + NOUN_STREAM = 0x1C5, + NOUN_OPPOSITE_SHORE = 0x1C6, + NOUN_PATH_TO_SOUTH = 0x1C7, + NOUN_OPPOSITE_BANK = 0x1C8, + NOUN_BROKEN_LADDER = 0x1C9, + NOUN_BAG_OF_TWINKIFRUITS = 0x1CA, + NOUN_BED = 0x1CB, + NOUN_DISPLAY = 0x1CC, + //NOUN_LEAVE = 0x1CD, + //NOUN_EXIT_FROM = 0x1CE, + NOUN_DEVICE = 0x1CF, + NOUN_0_KEY = 0x1D0, + NOUN_1_KEY = 0x1D1, + NOUN_2_KEY = 0x1D2, + NOUN_3_KEY = 0x1D3, + NOUN_4_KEY = 0x1D4, + NOUN_5_KEY = 0x1D5, + NOUN_6_KEY = 0x1D6, + NOUN_7_KEY = 0x1D7, + NOUN_8_KEY = 0x1D8, + NOUN_9_KEY = 0x1D9, + NOUN_FROWN_KEY = 0x1DA, + NOUN_SMILE_KEY = 0x1DB, + NOUN_NATIVE_WOMAN = 0x1DC, + NOUN_YELLOW_BIRD = 0x1DD, + NOUN_BLEEPER = 0x1DE, + NOUN_SIZEMOMETER = 0x1DF, + NOUN_PANEL = 0x1E0, + NOUN_PRINTER = 0x1E1, + NOUN_HARD_DRIVE = 0x1E2, + NOUN_BATHROOM = 0x1E3, + NOUN_DESK = 0x1E4, + NOUN_PASSAGEWAY = 0x1E5, + NOUN_FIRE_HYDRANT = 0x1E6, + NOUN_FREEZER = 0x1E7, + NOUN_EQUIDIGITIZER = 0x1E8, + NOUN_VISION_VIEW = 0x1E9, + NOUN_TELEDETECTOR = 0x1EA, + NOUN_POLE = 0x1EB, + NOUN_TRANSPOSITION_DEVICE = 0x1EC, + NOUN_STATUESQUE = 0x1ED, + NOUN_TEMPERATURE_GAUGE = 0x1EE, + NOUN_CHECK = 0x1EF, + NOUN_WATCH = 0x1F0, + NOUN_ELECTRO_SCANNER = 0x1F1, + NOUN_HALL = 0x1F2, + NOUN_SCANNER = 0x1F3, + //NOUN_PLACE_HAND_ON = 0x1F4, + NOUN_SECURITY_MONITOR = 0x1F5, + NOUN_DIGITORAMA = 0x1F6, + NOUN_RAIL_BEAM = 0x1F7, + NOUN_VAULT = 0x1F8, + NOUN_HALLWAY = 0x1F9, + NOUN_PIPES = 0x1FA, + NOUN_AIR_VENT_GRATE = 0x1FB, + NOUN_SECURITY_OFFICE = 0x1FC, + NOUN_SIGNAL = 0x1FD, + NOUN_BLEEP = 0x1FE, + NOUN_BLIP = 0x1FF, + NOUN_LOFT = 0x200, + NOUN_ELECTRONIC_ANT_FARM = 0x201, + NOUN_ELECTRIC_WIRING = 0x202, + NOUN_SECURITY_PANEL = 0x203, + NOUN_CORRIDOR = 0x204, + NOUN_CIRCUIT_CONTROLS = 0x205, + NOUN_AIR_DUCT = 0x206, + NOUN_CELL_WALL = 0x207, + NOUN_LIGHTS = 0x208, + //NOUN_STARE_INTO = 0x209, + NOUN_CELL_CONTROLS = 0x20A, + NOUN_COMMODE = 0x20B, + //NOUN_USE = 0x20C, + NOUN_BASIN = 0x20D, + //NOUN_JUMP_INSIDE = 0x20E, + NOUN_PREVIOUS_CELL = 0x20F, + NOUN_NEXT_ROOM = 0x210, + NOUN_ZINK = 0x211, + //NOUN_GAZE_INTO = 0x212, + NOUN_THRONE = 0x213, + NOUN_SACK = 0x214, + NOUN_LIMB = 0x215, + NOUN_SINK = 0x216, + NOUN_JOHNNY_ON_THE_SPOT = 0x217, + NOUN_DEBRIS = 0x218, + NOUN_BUNK = 0x219, + NOUN_NEXT_CELL = 0x21A, + NOUN_TOILET = 0x21B, + NOUN_MONITOR_AREA = 0x21C, + NOUN_SIDEWALL = 0x21D, + NOUN_COFFEE_MUG = 0x21E, + //NOUN_SIT_AT = 0x21F, + NOUN_LIGHTING_FIXTURE = 0x220, + NOUN_MONITORS = 0x221, + NOUN_GENDER_CONTROLS = 0x222, + NOUN_NEURO_ANALYZER = 0x223, + NOUN_MOLECULAR_RECORDER = 0x224, + NOUN_MAINTENANCE_PANEL = 0x225, + NOUN_RAMP = 0x226, + //NOUN_WALK_UP = 0x227, + NOUN_SUBSONIC_ATOMIZER = 0x228, + NOUN_EIGHT_BALL = 0x229, + NOUN_DNA_INVERTER = 0x22A, + NOUN_DNA_CONVERTER = 0x22B, + NOUN_PLATFORM = 0x22C, + NOUN_GUINEA_PIG_TEST_BOX = 0x22D, + NOUN_GASEOUS_PROBE_WARPER = 0x22E, + NOUN_TOOL_CABINET = 0x22F, + NOUN_SURGICAL_BOXES = 0x230, + NOUN_FETAL_HEART_MONITOR = 0x231, + NOUN_XRAY_CABINET = 0x232, + NOUN_STERILIZATION_SINK = 0x233, + NOUN_DRIPOLATOR = 0x234, + NOUN_SHOCK_MACHINE = 0x235, + NOUN_INTERROGATION_TABLE = 0x236, + NOUN_LIE_DOWN_ON = 0x237, + //NOUN_DECIPHER = 0x238, + NOUN_GUARD = 0x239, + NOUN_RIP_IN_FLOOR = 0x23A, + NOUN_TELEPORT_AREA = 0x23B, + NOUN_BROKEN_BEAM = 0x23C, + NOUN_ROCK_CHUNK = 0x23D, + NOUN_BLOODY_CELL_WALL = 0x23E, + NOUN_WALL_BOARD = 0x23F, + NOUN_GENDER_SCANNER = 0x240, + NOUN_BAR = 0x241, + //NOUN_WALK_INTO = 0x242, + NOUN_HALLWAY_TO_SOUTH = 0x243, + NOUN_SIGN = 0x244, + NOUN_HALLWAY_TO_NORTH = 0x245, + NOUN_BOTTLES = 0x246, + NOUN_UPPER_DANCE_FLOOR = 0x247, + NOUN_DANCE_FLOOR = 0x248, + NOUN_RAILING = 0x249, + NOUN_BAR_STOOL = 0x24A, + NOUN_LADY = 0x24B, + NOUN_UPPER_LEVEL = 0x24C, + NOUN_ALCOVE = 0x24D, + NOUN_DISCO_BALL = 0x24E, + NOUN_LADIES = 0x24F, + NOUN_COACH_LAMP = 0x250, + NOUN_CARD_SLOT = 0x251, + NOUN_HOOP = 0x252, + NOUN_CANNONBALLS = 0x253, + NOUN_WATER_FOUNTAIN = 0x254, + NOUN_HALLWAY_TO_EAST = 0x255, + NOUN_HALLWAY_TO_WEST = 0x256, + NOUN_SUPPORT = 0x257, + NOUN_BACKBOARD = 0x258, + NOUN_WIDE_DOOR = 0x259, + NOUN_SIGN_POST = 0x25A, + NOUN_FIRE_EXTINGUISHER = 0x25B, + NOUN_TRASH = 0x25C, + NOUN_MISSILES = 0x25D, + NOUN_TANK = 0x25E, + NOUN_TWO_TON_WEIGHT = 0x25F, + NOUN_ONE_TON_TOMATO = 0x260, + NOUN_ANVIL = 0x261, + NOUN_MINUTEMAN_IV_ICBM = 0x262, + NOUN_CHEST = 0x263, + NOUN_ARMOR = 0x264, + NOUN_CARTON = 0x265, + NOUN_POWDER = 0x266, + NOUN_RAFT = 0x267, + NOUN_WHATZIT = 0x268, + NOUN_CATAPULT = 0x269, + NOUN_HAND_GRENADE = 0x26A, + NOUN_BARRELS = 0x26B, + NOUN_LOADING_RAMP = 0x26C, + NOUN_BLIMP = 0x26D, + NOUN_FLOUR = 0x26E, + NOUN_FLY_PAPER = 0x26F, + NOUN_RUG = 0x270, + NOUN_CARPET = 0x271, + NOUN_CAN = 0x272, + NOUN_RUBBER_DUCKIE = 0x273, + NOUN_GOLF_CLUBS = 0x274, + NOUN_RAT = 0x275, + NOUN_BARREL = 0x276, + NOUN_BUCKET_OF_TAR = 0x277, + NOUN_SACKS = 0x278, + NOUN_STORAGE = 0x279, + NOUN_120V_3_PHASE_400HZ = 0x27A, + NOUN_LAB_EQUIPMENT = 0x27B, + NOUN_AIR_HORN = 0x27C, + NOUN_JAR = 0x27D, + NOUN_SEVERED_CABLE = 0x27E, + NOUN_PROBE_ASSEMBLY = 0x27F, + NOUN_KNIFE_SWITCH = 0x280, + NOUN_WORK_BENCH = 0x281, + NOUN_HEATER = 0x282, + NOUN_TOXIC_WASTE = 0x283, + NOUN_EXPERIMENT = 0x284, + NOUN_DRAWING_BOARD = 0x285, + NOUN_MISHAP = 0x286, + NOUN_AIR_PURIFIER = 0x287, + NOUN_DUMMY = 0x288, + NOUN_PICTURE = 0x289, + NOUN_BAGGAGE_CHECK = 0x28A, + NOUN_DEPARTURE_SCHEDULE = 0x28B, + NOUN_SHADE_OF_PALE = 0x28C, + NOUN_ITINERARY = 0x28D, + NOUN_BARGAIN_VAT = 0x28E, + NOUN_PENCILS = 0x28F, + NOUN_PAD_IF_PAPER = 0x290, + NOUN_DEEPEST_DEPTHS = 0x291, + NOUN_ROLODEX = 0x292, + NOUN_MONA_TISA = 0x293, + NOUN_ABSTRACT_ART = 0x294, + NOUN_SPACE_QUESTING_VIII = 0x295, + NOUN_THEATRICAL_ART = 0x296, + NOUN_METAL_POLE = 0x297, + NOUN_EXIT = 0x298, + NOUN_SWIRLING_LIGHT = 0x299, + NOUN_REGISTER = 0x29A, + NOUN_PEACHY_BUNS = 0x29B, + NOUN_OUR_TOWN = 0x29C, + NOUN_EMBROIDERED_ART = 0x29D, + NOUN_GEORGE_BUSH_ALIKE = 0x29E, + NOUN_COUNTER = 0x29F, + NOUN_SENSOR = 0x2A0, + NOUN_SOFTWARE_INFORMATION = 0x2A1, + NOUN_WALK_BEHIND = 0x2A2, + NOUN_BARGAINS = 0x2A3, + NOUN_SCAN_LIGHT = 0x2A4, + NOUN_OLD_SOFTWARE_STAND = 0x2A5, + NOUN_SOFTWARE_SHELF = 0x2A6, + NOUN_HOTTEST_SOFTWARE = 0x2A7, + NOUN_GREAT_PAINTBALL_ART = 0x2A8, + NOUN_SCENIC_VISTA = 0x2A9, + NOUN_LASER = 0x2AA, + NOUN_LASER_JET = 0x2AB, + NOUN_LEVER = 0x2AC, + NOUN_BULLSEYE = 0x2AD, + NOUN_STAND = 0x2AE, + NOUN_CONTROL_STATION = 0x2AF, + NOUN_STRANGE_MONSTER = 0x2B0, + NOUN_GHASTLY_BEAST = 0x2B1, + //NOUN_GAWK_AT = 0x2B2, + NOUN_CORRIDOR_TO_SOUTH = 0x2B3, + NOUN_CORRIDOR_TO_NORTH = 0x2B4, + NOUN_WALK_ONTO = 0x2B5, + NOUN_ROCK_WALL = 0x2B6, + NOUN_WOMAN = 0x2B7, + NOUN_WOMEN = 0x2B8, + NOUN_CORRIDOR_TO_EAST = 0x2B9, + NOUN_CORRIDOR_TO_WEST = 0x2BA, + NOUN_AMMUNITION = 0x2BB, + NOUN_ARMORED_VEHICLE = 0x2BC, + NOUN_TOMATO = 0x2BD, + NOUN_MISSILE = 0x2BE, + NOUN_SUIT_OF_ARMOR = 0x2BF, + NOUN_POWDER_CONTAINER = 0x2C0, + NOUN_INFLATABLE_RAFT = 0x2C1, + NOUN_GRENADE = 0x2C2, + NOUN_FENCE = 0x2C3, + NOUN_WOODEN_STATUE = 0x2C4, + NOUN_CONVEYER_BELT = 0x2C5, + NOUN_CONTROLS = 0x2C6, + NOUN_EQUIPMENT = 0x2C7, + NOUN_SHELF = 0x2C8, + NOUN_CABINETS = 0x2C9, + NOUN_CONTROL_CONSOLE = 0x2CA, + NOUN_FAUCET = 0x2CB, + NOUN_PANEL_BOX = 0x2CC, + NOUN_STATUE = 0x2CD, + NOUN_GAUGE = 0x2CE, + NOUN_CIRCUIT_PANEL = 0x2CF, + NOUN_CATWALK = 0x2D0, + NOUN_CIRCUITS = 0x2D1, + NOUN_BLOOD_STAIN = 0x2D2, + NOUN_GRATE = 0x2D3, + NOUN_AIR_SHAFT = 0x2D4, + //NOUN_RETURN_TO = 0x2D5, + NOUN_FORMALDEHYDE = 0x2D6, + NOUN_PETROX = 0x2D7, + NOUN_SODIUM_BENZOATE = 0x2D8, + NOUN_GURNEY = 0x2D9, + NOUN_IRONING_BOARD = 0x2DA, + NOUN_LEFT_MONITOR = 0x2DB, + NOUN_RIGHT_MONITOR = 0x2DC, + NOUN_RED_BUTTON = 0x2DD, + NOUN_GREEN_BUTTON = 0x2DE, + NOUN_RIGHT_ONE_KEY = 0x2DF, + NOUN_RIGHT_1_KEY = 0x2E0, + NOUN_RIGHT_2_KEY = 0x2E1, + NOUN_RIGHT_3_KEY = 0x2E2, + NOUN_RIGHT_4_KEY = 0x2E3, + NOUN_RIGHT_5_KEY = 0x2E4, + NOUN_RIGHT_6_KEY = 0x2E5, + NOUN_RIGHT_7_KEY = 0x2E6, + NOUN_RIGHT_8_KEY = 0x2E7, + NOUN_LEFT_1_KEY = 0x2E8, + NOUN_LEFT_2_KEY = 0x2E9, + NOUN_LEFT_3_KEY = 0x2EA, + NOUN_LEFT_4_KEY = 0x2EB, + NOUN_CORRIDOR_WALL = 0x2EC, + NOUN_MUG = 0x2ED, + NOUN_DOUGHNUT = 0x2EE, + NOUN_SECURITY_STATION = 0x2EF, + NOUN_NEWSPAPER = 0x2F0, + NOUN_MAGAZINE = 0x2F1, + NOUN_CLIPBOARD = 0x2F2, + NOUN_PAPER_FOOTBALL = 0x2F3, + NOUN_YOUR_STUFF = 0x2F4, + NOUN_OTHER_STUFF = 0x2F5, + NOUN_LAMP = 0x2F6, + NOUN_CLIMB_INTO = 0x2F7, + NOUN_LIGHT_BULB = 0x2F8, + //NOUN_STEP_INTO = 0x2F9, + NOUN_ROOM = 0x2FA, + //NOUN_CRAWL_TO = 0x2FB, + NOUN_FOURTH_CELL = 0x2FC, + NOUN_THIRD_CELL = 0x2FD, + NOUN_SECOND_CELL = 0x2FE, + NOUN_FIRST_CELL = 0x2FF, + NOUN_EQUIPMENT_ROOM = 0x300, + //NOUN_CRAWL_DOWN = 0x301, + NOUN_DESCENDING_SHAFT = 0x302, + NOUN_SAUROPOD = 0x303, + NOUN_MONSTER = 0x304, + NOUN_FAKE_ID = 0x305, + NOUN_ALIEN_LIQUOR = 0x306, + NOUN_INTERN = 0x307, + NOUN_INSTRUMENT_TABLE = 0x308, + NOUN_WOMAN_ON_BALCONY = 0x309, + NOUN_WOMAN_IN_CHAIR = 0x30A, + //NOUN_SIT_ON = 0x30B, + NOUN_WOMAN_IN_ALCOVE = 0x30C, + NOUN_KETTLE = 0x30D, + NOUN_BARTENDER = 0x30E, + NOUN_WHISKEY = 0x30F, + NOUN_ALCOHOL = 0x310, + NOUN_RIM = 0x311, + //NOUN_WALK_ALONG = 0x312, + NOUN_SUBMERGED_CITY = 0x313, + NOUN_GOVERNORS_HOUSE = 0x314, + NOUN_RIM_TOWARDS_EAST = 0x315, + NOUN_CEMENT_PYLON = 0x316, + NOUN_ELEVATOR = 0x317, + NOUN_ELEVATOR_SHAFT = 0x318, + NOUN_CONVEYOR_BELT = 0x319, + NOUN_CANNON_BALLS = 0x31A, + NOUN_ELECTRICAL_OVERHANG = 0x31B, + NOUN_GUTTER_PIPE = 0x31C, + NOUN_SIDEWALK = 0x31D, + NOUN_STREET = 0x31E, + NOUN_BARRICADE = 0x31F, + NOUN_DOOR_CONTROL_SLOT = 0x320, + NOUN_STREET_TO_EAST = 0x321, + NOUN_SIDEWALK_TO_EAST = 0x322, + NOUN_BUILDING = 0x323, + NOUN_CAR = 0x324, + //NOUN_GET_INSIDE = 0x325, + NOUN_MARQUEE = 0x326, + NOUN_BUILDING_ENTRANCE = 0x327, + NOUN_GUARD_STATION = 0x328, + NOUN_TECHNICAL_EQUIPMENT = 0x329, + NOUN_GUARD_TURRET = 0x32A, + NOUN_PILLAR = 0x32B, + NOUN_PAPERS = 0x32C, + NOUN_FILE_CABINET = 0x32D, + NOUN_WINDOWS = 0x32E, + //NOUN_WALK = 0x32F, + NOUN_STORAGE_BOX = 0x330, + NOUN_WATER_COOLER = 0x331, + NOUN_BOX = 0x332, + NOUN_RIFLES = 0x333, + NOUN_SLINGSHOT = 0x334, + NOUN_MAUSOLEUM = 0x335, + NOUN_SOFTWARE_STORE = 0x336, + NOUN_CONCRETE_BUILDING = 0x337, + NOUN_HUMONGOUS_MONITOR = 0x338, + NOUN_SPACE_BIKE = 0x339, + NOUN_BILLBOARD = 0x33A, + NOUN_LACK_OF_NOOKIE_MOTEL = 0x33B, + NOUN_BIDETS_XCREETZA_HUT = 0x33C, + NOUN_BUILDINGS = 0x33D, + NOUN_SKYSCRAPER = 0x33E, + NOUN_SOFTWARE_LOGO = 0x33F, + NOUN_GIANT_TELESCOPE = 0x340, + NOUN_HANDLE = 0x341, + NOUN_HOLE = 0x342, + NOUN_LASER_BEAM = 0x343, + NOUN_PEDESTAL = 0x344, + NOUN_BOAT = 0x345, + NOUN_GIANT_MONUMENT = 0x346, + NOUN_ROPE = 0x347, + NOUN_SAND_BAR_RESTAURANT = 0x348, + NOUN_PORTHOLE = 0x349, + NOUN_TICKET_BOOTH = 0x34A, + NOUN_POLLYS_ENTRANCE = 0x34B, + NOUN_RESTAURANT_ENTRANCE = 0x34C, + NOUN_THE_PLEASURE_DOME = 0x34D, + NOUN_STARFISH = 0x34E, + NOUN_FLIPPER = 0x34F, + NOUN_SAND_DOLLAR = 0x350, + NOUN_SHELL = 0x351, + NOUN_GUEST_LIST = 0x352, + NOUN_WEIRD_ANIMAL_HEAD = 0x353, + NOUN_SHIPS_WHEEL = 0x354, + NOUN_HANDICAP_SIGN = 0x355, + NOUN_ELEVATOR_CONTROLS = 0x356, + NOUN_BRICK_WALL = 0x357, + NOUN_BIKE_RACK = 0x358, + NOUN_ODONALDS_SIGN = 0x359, + NOUN_ELEVATOR_ENTRANCE = 0x35A, + NOUN_SPECIAL_SALE_SIGN = 0x35B, + NOUN_ATTORNEYS_AT_LAW = 0x35C, + NOUN_SLEDGE_MALL = 0x35D, + NOUN_SKELETON = 0x35E, + NOUN_STRANGE_EQUIPMENT = 0x35F, + NOUN_STREET_TO_WEST = 0x360, + NOUN_SIDEWALK_TO_WEST = 0x361, + NOUN_TELEPORTER_ENTRANCE = 0x362, + NOUN_SOFTWARE_DOOR = 0x363, + NOUN_SPINACH_PATCH_DOLL = 0x364, + //NOUN_REFLECT = 0x365, + NOUN_REGISTER_DRAWER = 0x366, + NOUN_ELEVATOR_DOOR = 0x367, + NOUN_HYDRAULIC_SUPPORT = 0x368, + NOUN_EQUIPMENT_OVERHEAD = 0x369, + //NOUN_GET_INTO = 0x36A, + NOUN_WARNING_LABEL = 0x36B, + NOUN_NUCLEAR_SLINGSHOT = 0x36C, + NOUN_DISPLAY_CASE = 0x36D, + NOUN_PHOTON_RIFLES = 0x36E, + NOUN_MONITORING_EQUIPMENT = 0x36F, + NOUN_TELESCOPE = 0x370, + NOUN_MOTEL = 0x371, + NOUN_RESTAURANT = 0x372, + NOUN_SOFTWARE_STORE_SIGN = 0x373, + NOUN_ADVERTISING_POSTER = 0x374, + NOUN_ADVERTISEMENT = 0x375, + NOUN_OLD_SOFTWARE = 0x376, + NOUN_CASH_REGISTER = 0x377, + NOUN_ENTRANCE = 0x378, + NOUN_LASER_CANNON = 0x379, + NOUN_SAND_BAGS = 0x37A, + NOUN_PLEASURE_DOME = 0x37B, + NOUN_DOME_ENTRANCE = 0x37C, + NOUN_LABORATORY = 0x37D, + NOUN_STREET_TO_SOUTH = 0x37E, + NOUN_ELEVATOR_ACCESS_SLOT = 0x37F, + NOUN_CAR_CONTROLS = 0x380, + NOUN_SCENT_PACKET = 0x381, + NOUN_KITTY = 0x382, + NOUN_GLOVE_COMPARTMENT = 0x383, + NOUN_MOLDY_SOCK = 0x384, + NOUN_SODA_CANS = 0x385, + NOUN_WINDSHIELD = 0x386, + NOUN_DASHBOARD = 0x387, + NOUN_INTERIOR_OF_CAR = 0x388, + NOUN_VIEW_RIGHT_BUTTON = 0x389, + NOUN_BLACK_BUTTON = 0x38A, + NOUN_WHITE_BUTTON = 0x38B, + NOUN_INSIDE_OF_CAR = 0x38C, + NOUN_RIM_TOWARDS_WEST = 0x38D, + NOUN_CEMENT_BLOCK = 0x38E, + NOUN_CITY = 0x38F, + NOUN_SPEAKER = 0x390, + NOUN_EYE_CHART = 0x391, + NOUN_LAUNCH_PAD = 0x392, + NOUN_BUILDING_TO_WEST = 0x393, + NOUN_PAD_TO_EAST = 0x394, + NOUN_PAD_TO_WEST = 0x395, + NOUN_TOWER = 0x396, + NOUN_LOOK_OUT = 0x397, + NOUN_SERVICE_PANEL = 0x398, + NOUN_CRACK = 0x399, + NOUN_THROTTLE = 0x39A, + NOUN_GRAB = 0x39B, + NOUN_INSTRUMENTATION = 0x39C, + NOUN_TP = 0x39D, + NOUN_SEAT = 0x39E, + NOUN_STATUS_PANEL = 0x39F, + NOUN_SHIPS_CONTROLS = 0x3A0, + NOUN_PROFESSOR = 0x3A1, + NOUN_PROFESSORS_GURNEY = 0x3A2, + NOUN_WELCOME_MAT = 0x3A3, + NOUN_MELON_MUSH = 0x3A4, + NOUN_BADMINTON_BRAT = 0x3A5, + //NOUN_APPLY = 0x3A6, + NOUN_COMBINATION = 0x3A7, + NOUN_NOTE = 0x3A8, + NOUN_LECITHIN = 0x3A9, + NOUN_REPAIR_WOMAN = 0x3AA, + NOUN_EXPLOSIVES = 0x3AB, + NOUN_DOLLOP = 0x3AC, + NOUN_DROP = 0x3AD, + NOUN_DASH = 0x3AE, + NOUN_SPLASH = 0x3AF, + NOUN_DOCK_TO_SOUTH = 0x3B0, + //NOUN_STEER_TOWARDS = 0x3B1, + NOUN_BUILDING_TO_NORTH = 0x3B2, + NOUN_VOLCANO_RIM = 0x3B3, + NOUN_OPEN_WATER_TO_SOUTH = 0x3B4, + NOUN_PROJECTOR = 0x3B5, + NOUN_GUARDS_ARM2 = 0x3B6, + //NOUN_NIBBLE_ON = 0x3B7, + //NOUN_ENTER = 0x3B8, + NOUN_ = 0x3B9, + NOUN_TIMER_BUTTON_1 = 0x3BA, + NOUN_REMOTE_BUTTON_1 = 0x3BB, + NOUN_START_BUTTON_2 = 0x3BC, + NOUN_REMOTE_BUTTON_2 = 0x3BD, + NOUN_TIMER_BUTTON_2 = 0x3BE, + NOUN_START_BUTTON_1 = 0x3BF, + NOUN_ANTIGRAV_CONTROLS = 0x3C0, + NOUN_BRUCES_TREE = 0x3C1, + NOUN_COLISEUM = 0x3C2, + NOUN_BRUCES_GARDEN_ROOM = 0x3C3, + NOUN_FOUNTAIN = 0x3C4, + NOUN_HOUSE_OF_BRUCE = 0x3C5, + NOUN_CITY_BACKDROP = 0x3C6, + NOUN_BRUCES_BALCONY = 0x3C7, + NOUN_BRUCES_ENTRANCE = 0x3C8, + NOUN_BRUCES_LOGO = 0x3C9, + NOUN_LOUNGE_CHAIR = 0x3CA, + NOUN_LIVING_ROOM_FLOOR = 0x3CB, + NOUN_LIVINGROOM_FLOOR = 0x3CC, + NOUN_PERFUME_BOTTLE = 0x3CD, + NOUN_COOL_NEON_LIGHT = 0x3CE, + NOUN_FLOWER_POT = 0x3CF, + NOUN_COFFEE_TABLE = 0x3D0, + NOUN_FLOWERS = 0x3D1, + NOUN_ART_DECO_CHAIR = 0x3D2, + NOUN_SAFE = 0x3D3, + NOUN_SPLASHY_DECOR = 0x3D4, + NOUN_THEATRICAL_FACES = 0x3D5, + NOUN_ART_DECO_PIECE = 0x3D6, + NOUN_END_OF_ROOM = 0x3D7, + NOUN_FIREPLACE = 0x3D8, + NOUN_ARTWORK = 0x3D9, + NOUN_COOL_NEON_LIGHTS = 0x3DA, + NOUN_GLASS_PLATED_WINDOW = 0x3DB, + NOUN_BEDROOM_FLOOR = 0x3DC, + NOUN_BAUBLE = 0x3DD, + NOUN_SNAPSHOT = 0x3DE, + NOUN_PERFUME = 0x3DF, + NOUN_CLAPBOARD = 0x3E0, + NOUN_BERET = 0x3E1, + NOUN_HORSE_WHIP = 0x3E2, + NOUN_CORNER_TABLE = 0x3E3, + NOUN_BOA = 0x3E4, + NOUN_WIG_STAND = 0x3E5, + NOUN_PARTITION = 0x3E6, + NOUN_MEGAPHONE = 0x3E7, + NOUN_SLIP = 0x3E8, + NOUN_SCONCE = 0x3E9, + NOUN_VANITY = 0x3EA, + NOUN_BEDBOARD = 0x3EB, + NOUN_LOVE_SEAT = 0x3EC, + NOUN_SOUVENIR_TICKETS = 0x3ED, + NOUN_REVIEW = 0x3EE, + NOUN_BRUCE_AT_THE_GALA = 0x3EF, + NOUN_ART_DECO_RUG = 0x3F0, + NOUN_LIVINGROOM = 0x3F1, + NOUN_SCULPTURE = 0x3F2, + NOUN_SPECIMEN_EPITHET = 0x3F3, + NOUN_VENT = 0x3F4, + NOUN_FLOWER_BOX = 0x3F5, + NOUN_LEDGE = 0x3F6, + NOUN_BOLT = 0x3F7, + NOUN_OBSERVATION_WINDOW = 0x3F8, + NOUN_AIR_HOSE = 0x3F9, + NOUN_AUTO_SHOP = 0x3FA, + NOUN_MANHOLE = 0x3FB, + NOUN_AUTO_SHOP_ENTRANCE = 0x3FC, + NOUN_BROKEN_WINDOW = 0x3FD, + NOUN_WOMANHOLE = 0x3FE, + NOUN_GARAGE_DOOR = 0x3FF, + NOUN_SCRATCH_PAD = 0x400, + NOUN_GAS_PRICES = 0x401, + NOUN_UP_BUTTON = 0x402, + NOUN_DOWN_BUTTON = 0x403, + NOUN_SPARE_PARTS_LIST = 0x404, + NOUN_SKYLIGHT = 0x405, + NOUN_TOOL_BOX = 0x406, + NOUN_CAR_LIFT = 0x407, + NOUN_CAR_SEAT = 0x408, + NOUN_GARAGE_FLOOR = 0x409, + NOUN_GARAGE_DOOR_CONTROLS = 0x40A, + NOUN_AMISH_HAT = 0x40B, + NOUN_JACK = 0x40C, + NOUN_COILS = 0x40D, + NOUN_OIL_CAN = 0x40E, + NOUN_FAN_BELTS = 0x40F, + NOUN_REAR_OF_GARAGE = 0x410, + NOUN_FRONT_OF_GARAGE = 0x411, + NOUN_MUFFLER = 0x412, + NOUN_SPARE_PART = 0x413, + NOUN_HUBCAP = 0x414, + NOUN_CANDLE = 0x415, + NOUN_RATES = 0x416, + NOUN_GREASE_CAN = 0x417, + NOUN_CALENDAR = 0x418, + NOUN_FORK_LIFT = 0x419, + NOUN_TRASH_CAN = 0x41A, + NOUN_SHAKER_CHAIR = 0x41B, + NOUN_QUARTER_PANEL = 0x41C, + NOUN_AREA_BEHIND_CAR = 0x41D, + NOUN_DANGER_ZONE = 0x41E, + NOUN_NEWSSTAND = 0x41F, + NOUN_LADY_GODIVA_MONUMENT = 0x420, + NOUN_SPOT_A_POT = 0x421, + NOUN_GUARD_RAIL = 0x422, + NOUN_ALLEY = 0x423, + NOUN_DITCH = 0x424, + NOUN_VIDEO_STORE_DOOR = 0x425, + NOUN_BUCKLUSTER_MARQUEE = 0x426, + NOUN_VIDEO_STORE = 0x427, + NOUN_HORMONE_BILLBOARD = 0x428, + NOUN_PHONE_ANTENNA = 0x429, + NOUN_RETURN_SLOT = 0x42A, + NOUN_NOOSE = 0x42B, + NOUN_COMEDY_VIDEOS = 0x42C, + NOUN_SMELLY_SNEAKER = 0x42D, + NOUN_PIPPYS_STOCKING = 0x42E, + NOUN_PHONE_CRADLE = 0x42F, + NOUN_DRAMA_VIDEOS = 0x430, + NOUN_SPOTLIGHT = 0x431, + NOUN_STOREROOM_FLOOR = 0x432, + NOUN_ALL_SALES_FINAL = 0x433, + NOUN_MACHOPROSE_TEE_SHIRT = 0x434, + NOUN_UNKNOWN_COMIC_HANDS = 0x435, + NOUN_WET_CEMENT = 0x436, + NOUN_PIPPYS_TINY_IMPRINT = 0x437, + NOUN_OBNOXIOUS_DOG_PAWS = 0x438, + NOUN_LEG_AND_A_LEG_JEANS = 0x439, + NOUN_VIDEO_STORE_EXIT = 0x43A, + NOUN_AISLE = 0x43B, + NOUN_VIDEO_MONITOR = 0x43C, + NOUN_POLLY_PIGS_IMPRINT = 0x43D, + NOUN_JOHN_WYNNS_IMPRINT = 0x43E, + NOUN_MR_NEDS_IMPRINT = 0x43F, + NOUN_PEG_LEG_PETE_IMPRINT = 0x440, + NOUN_MARX_BROS_POSTER = 0x441, + NOUN_PIPPY_BILLBOARD = 0x442, + NOUN_VIDEOS_NOONE_WANTS = 0x443, + NOUN_MORE_CLASSIC_VIDEOS = 0x444, + NOUN_JOIN_OUR_PRICE_CLUB = 0x445, + NOUN_EDUCATIONAL_VIDEOS = 0x446, + NOUN_DEEP_DISCOUNT_TITLES = 0x447, + NOUN_WORLD_CHAMPS_POSTER = 0x448, + NOUN_WORKOUT_VIDEOS = 0x449, + NOUN_20_PERCENT_OFF_SIGN = 0x44A, + NOUN_CIVILIZATION_AD = 0x44B, + NOUN_NEW_RELEASE_VIDEOS = 0x44C, + NOUN_PORNO_VIDEOS = 0x44D, + NOUN_FOREIGN_VIDEOS = 0x44E, + NOUN_CLASSIC_VIDEOS = 0x44F, + NOUN_ADVENTURE_VIDEOS = 0x450, + NOUN_BUCKLUSTER_LOGO = 0x451, + NOUN_WINE_BOTTLE = 0x452, + NOUN_DIRT_PILE = 0x453, + NOUN_MAMMOTH_PENCIL_HEAD = 0x454, + NOUN_WREAKY_PUMPKIN = 0x455, + NOUN_MILK_CARTON = 0x456, + NOUN_BUCKET = 0x457, + NOUN_EMPTY_BOX = 0x458, + NOUN_DIAPER_BOX = 0x459, + NOUN_HERMIT = 0x45A, + NOUN_METAL_PIPE = 0x45B, + NOUN_CONCRETE_SUPPORT = 0x45C, + NOUN_VARIOUS_TRASH = 0x45D, + NOUN_ARMATURE = 0x45E, + NOUN_CONTROL_BOX = 0x45F, + NOUN_TOP_OF_DOME = 0x460, + NOUN_EXPRESSWAY_TO_EAST = 0x461, + NOUN_GO_TOWARDS = 0x462, + NOUN_EXPRESSWAY_TO_WEST = 0x463, + NOUN_DOME = 0x464, + NOUN_VIEW_OF_CITY = 0x465, + NOUN_EXPRESSWAY = 0x466, + NOUN_HOOK = 0x467, + NOUN_SEA_MONSTER = 0x468, + NOUN_EDGE_OF_VOLCANO = 0x469, + NOUN_JUMP_THROUGH = 0x46A, + NOUN_OLD_TEA_CUP = 0x46B, + NOUN_NAME_PLATE = 0x46C, + NOUN_OLD_VASE = 0x46D, + NOUN_PORTRAIT = 0x46E, + //NOUN_PUT_DOWN = 0x46F, + NOUN_TALL_BUILDING = 0x470, + NOUN_OBNOXIOUS_DOG = 0x471, + NOUN_GUTS = 0x472, + NOUN_BIG_HEADS = 0x473, + NOUN_INSTALL = 0x474, + NOUN_LIFE_SUPPORT_MODULE = 0x475, + //NOUN_REMOVE = 0x476, + NOUN_LARGE_BLADE = 0x477, + NOUN_SIDE_ENTRANCE = 0x478, + NOUN_INDICATOR = 0x479, + NOUN_SIGNPOST = 0x47A, + NOUN_PIN = 0x47B, + NOUN_POWDER_PUFF = 0x47C, + NOUN_SHELVES = 0x47D, + NOUN_ELECTRODES = 0x47E, + NOUN_MISHAP2 = 0x47F, + NOUN_ISLD_SUPERSTRUCTURE = 0x480, + NOUN_FILE_CABINETS = 0x481, + NOUN_CYCLE_SHOP = 0x482, + NOUN_AIR_BIKE = 0x483, + NOUN_EMERGENCY_LIGHT = 0x484, + NOUN_TARGET_AREA = 0x485, + NOUN_ICE_CHESTS = 0x486, + NOUN_BIRDS = 0x487, + NOUN_DOCTORS_OFFICE = 0x488, + //NOUN_DEFACE = 0x489, + NOUN_LARGE_HEADS = 0x48A, + NOUN_SMALL_TABLE = 0x48B, + NOUN_COLLOSSEUM = 0x48C, + NOUN_HOUSE = 0x48D, + NOUN_BALCONY = 0x48E, + NOUN_GARDEN_ROOM = 0x48F, + NOUN_COVE_LIGHTS = 0x490, + NOUN_MASKS = 0x491, + NOUN_NEON_LIGHTS = 0x492, + NOUN_GLASS_BLOCK_WALL = 0x493, + NOUN_SCREEN = 0x494, + NOUN_SPARE_RIBS = 0x495, + NOUN_BANNER = 0x496, + NOUN_INSTRUCTIONAL_VIDEOS = 0x497, + NOUN_CEMENT = 0x498, + NOUN_STORE = 0x499, + NOUN_CARDBOARD_BOX = 0x49A, + NOUN_GRAFFITTI = 0x49B, + NOUN_GRAFFITI = 0x49C, + NOUN_PHOTOGRAPH = 0x49D, + NOUN_DIRECTORS_SLATE = 0x49E, + NOUN_CROP = 0x49F, + NOUN_HAT = 0x4A0, + NOUN_LOGO = 0x4A1, + NOUN_MAINTENANCE_BUILDING = 0x4A2, + //NOUN_MASSAGE = 0x4A3, + //NOUN_MANGLE = 0x4A4, + //NOUN_RUB = 0x4A5, + //NOUN_JUGGLE = 0x4A6, + //NOUN_SMASH = 0x4A7, + //NOUN_GUZZLE = 0x4A8, + NOUN_WEST_END_OF_PLATFORM = 0x4A9, + NOUN_EAST_END_OF_PLATFORM = 0x4AA + //NOUN_FOLD = 0x4AB, + //NOUN_SPINDLE = 0x4AC, + //NOUN_MUTILATE = 0x4AD +}; + +class SceneFactory { +public: + static SceneLogic *createScene(MADSEngine *vm); +}; + +/** + * Specialized base class for Rex Nebular game scenes + */ +class NebularScene : public SceneLogic { +protected: + NebularGlobals &_globals; + GameNebular &_game; + MADSAction &_action; + + /** + * Forms an animation resource name + */ + Common::String formAnimName(char sepChar, int suffixNum); + + /** + * Plays appropriate sound for entering various rooms + */ + void lowRoomsEntrySound(); +public: + /** + * Constructor + */ + NebularScene(MADSEngine *vm); + + void sub7178C(); +}; + +class SceneInfoNebular : public SceneInfo { + friend class SceneInfo; +protected: + virtual void loadCodes(MSurface &depthSurface, int variant); + + virtual void loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream); + + /** + * Constructor + */ + SceneInfoNebular(MADSEngine *vm) : SceneInfo(vm) {} +}; + +class SceneTeleporter : public NebularScene { +protected: + int _buttonTyped; + int _curCode; + int _digitCount; + int _curMessageId; + int _handSpriteId; + int _handSequenceId; + int _finishedCodeCounter; + int _meteorologistNextPlace; + int _meteorologistCurPlace; + int _teleporterSceneId; + Common::String _msgText; + + int teleporterAddress(int code, bool working); + + void teleporterHandleKey(); + Common::Point teleporterComputeLocation(); + void teleporterEnter(); + bool teleporterActions(); + void teleporterStep(); + +protected: + /** + * Constructor + */ + SceneTeleporter(MADSEngine *vm); +}; + +} // End of namespace Nebular +} // End of namespace MADS + +#endif /* MADS_NEBULAR_SCENES_H */ diff --git a/engines/mads/nebular/nebular_scenes1.cpp b/engines/mads/nebular/nebular_scenes1.cpp new file mode 100644 index 0000000000..8cf4107ad4 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes1.cpp @@ -0,0 +1,3168 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "mads/mads.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/nebular/nebular_scenes1.h" + +namespace MADS { + +namespace Nebular { + +void Scene1xx::setAAName() { + int idx = (_scene->_nextSceneId > 103 && _scene->_nextSceneId < 112) ? 1 : 0; + _game._aaName = Resources::formatAAName(idx); +} + +void Scene1xx::sceneEntrySound() { + if (_vm->_musicFlag) { + switch (_scene->_nextSceneId) { + case 101: + _vm->_sound->command(11); + break; + case 102: + _vm->_sound->command(12); + break; + case 103: + _vm->_sound->command(3); + _vm->_sound->command(25); + break; + case 109: + _vm->_sound->command(13); + break; + case 110: + _vm->_sound->command(10); + break; + case 111: + _vm->_sound->command(3); + break; + case 112: + _vm->_sound->command(15); + break; + default: + if (_scene->_priorSceneId < 104 || _scene->_priorSceneId > 108) + _vm->_sound->command(10); + break; + } + } +} + +void Scene1xx::setPlayerSpritesPrefix() { + _vm->_sound->command(5); + Common::String oldName = _game._player._spritesPrefix; + if (_scene->_nextSceneId <= 103 || _scene->_nextSceneId == 111) { + if (_globals[kSexOfRex] == SEX_FEMALE) + _game._player._spritesPrefix = "ROX"; + else { + _game._player._spritesPrefix = "RXM"; + _globals[kSexOfRex] = SEX_MALE; + } + } else if (_scene->_nextSceneId <= 110) { + _game._player._spritesPrefix = "RXSW"; + _globals[kSexOfRex] = SEX_UNKNOWN; + } else if (_scene->_nextSceneId == 112) + _game._player._spritesPrefix = ""; + + if (oldName == _game._player._spritesPrefix) + _game._player._spritesChanged = true; + + if (_scene->_nextSceneId == 105 || (_scene->_nextSceneId == 109 && _globals[kHoovicAlive])) { + _game._player._spritesChanged = true; + _game._player._loadsFirst = false; + } + + _game._player._trigger = 0; + _vm->_palette->setEntry(16, 10, 63, 63); + _vm->_palette->setEntry(17, 10, 45, 45); +} + +/*------------------------------------------------------------------------*/ + +Scene101::Scene101(MADSEngine *vm) : Scene1xx(vm) { + _sittingFl = false; + _panelOpened = false; + _messageNum = 0; + _posY = 0; + _shieldSpriteIdx = 0; + _chairHotspotId = 0; + _oldSpecial = 0; +} + +void Scene101::synchronize(Common::Serializer &s) { + Scene1xx::synchronize(s); + + s.syncAsByte(_sittingFl); + s.syncAsByte(_panelOpened); + s.syncAsSint16LE(_messageNum); + s.syncAsSint16LE(_posY); + s.syncAsSint16LE(_shieldSpriteIdx); + s.syncAsSint16LE(_chairHotspotId); + s.syncAsSint16LE(_oldSpecial); +} + +void Scene101::setup() { + _scene->_animationData->preLoad(formAnimName('A', -1), 3); + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene101::sayDang() { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _game._player._stepEnabled = false; + + switch (_game._trigger) { + case 0: + _scene->_sequences.remove(_globals._sequenceIndexes[11]); + _globals._sequenceIndexes[11] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[11], false, 3, 6, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 17, 21); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + _vm->_sound->command(17); + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 3, 2, 0, 0); + break; + + case 72: + _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 17, 17); + _scene->_kernelMessages.add(Common::Point(143, 61), 0x1110, 0, 0, 60, _game.getQuote(57)); + _scene->_sequences.addTimer(120, 73); + break; + + case 73: + _vm->_dialogs->show(10117); + _game._player._stepEnabled = true; + break; + + default: + break; + } +} + +void Scene101::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 3)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 4)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('x', 5)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('x', 6)); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('x', 7)); + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('m', -1)); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('b', 1)); + _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('b', 2)); + _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('a', 0)); + _globals._spriteIndexes[12] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _globals._spriteIndexes[13] = _scene->_sprites.addSprites(formAnimName('x', 8)); + _globals._spriteIndexes[14] = _scene->_sprites.addSprites(formAnimName('x', 0)); + + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 0, 0, 25); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 4, 0, 1, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 0, 2, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 7, 70); + _globals._sequenceIndexes[4] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[4], false, 10, 0, 0, 60); + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 5, 0, 1, 0); + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 10, 0, 2, 0); + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 6, 0, 0, 0); + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 6, 0, 10, 4); + _globals._sequenceIndexes[10] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[10], false, 6, 0, 32, 47); + + _scene->_hotspots.activate(NOUN_SHIELD_MODULATOR, false); + _panelOpened = false; + + // HACK: set the prior scene to 102 for now when the game starts, to avoid Rex's getting up animation + if (_scene->_priorSceneId == -1) + _scene->_priorSceneId = 102; + + if (_scene->_priorSceneId != -1) + _globals[kNeedToStandUp] = false; + + if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(100, 152); + + if ((_scene->_priorSceneId == 112) || ((_scene->_priorSceneId == -2) && _sittingFl )) { + _game._player._visible = false; + _sittingFl = true; + _game._player._playerPos = Common::Point(161, 123); + _game._player._facing = FACING_NORTHEAST; + _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 3, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 17, 17); + _scene->_hotspots.activate(NOUN_CHAIR, false); + _chairHotspotId = _scene->_dynamicHotspots.add(NOUN_CHAIR, VERB_SIT_IN, -1, Common::Rect(159, 84, 159 + 33, 84 + 36)); + if (_scene->_priorSceneId == 112) + sayDang(); + } else { + _globals._sequenceIndexes[12] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[12], false, 6, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 4); + } + + _game.loadQuoteSet(0x31, 0x32, 0x39, 0x36, 0x37, 0x38, 0); + + if (_globals[kNeedToStandUp]) { + _scene->loadAnimation(Resources::formatName(101, 'S', -1, EXT_AA, ""), 71); + _game._player._visible = false; + _game._player._stepEnabled = false; + _game._player._playerPos = Common::Point(68, 140); + _game._player._facing = FACING_WEST; + + _messageNum = 0; + _posY = 30; + } + + _oldSpecial = false; + + sceneEntrySound(); +} + +void Scene101::step() { + if (_oldSpecial != _game._player._special) { + _oldSpecial = _game._player._special; + if (_oldSpecial) + _vm->_sound->command(39); + else + _vm->_sound->command(11); + } + + switch (_game._trigger) { + case 70: + _vm->_sound->command(9); + break; + + case 71: + _globals[kNeedToStandUp] = false; + _game._player._visible = true; + _game._player._stepEnabled = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + break; + + case 72: + case 73: + sayDang(); + break; + + default: + break; + } + + if (_scene->_activeAnimation != nullptr) { + if ((_scene->_activeAnimation->getCurrentFrame() >= 6) && (_messageNum == 0)) { + _messageNum++; + _scene->_kernelMessages.add(Common::Point(63, _posY), 0x1110, 0, 0, 240, _game.getQuote(49)); + _posY += 14; + } + + if ((_scene->_activeAnimation->getCurrentFrame() >= 7) && (_messageNum == 1)) { + _messageNum++; + _scene->_kernelMessages.add(Common::Point(63, _posY), 0x1110, 0, 0, 240, _game.getQuote(54)); + _posY += 14; + } + + if ((_scene->_activeAnimation->getCurrentFrame() >= 10) && (_messageNum == 2)) { + _messageNum++; + _scene->_kernelMessages.add(Common::Point(63, _posY), 0x1110, 0, 0, 240, _game.getQuote(55)); + _posY += 14; + } + + if ((_scene->_activeAnimation->getCurrentFrame() >= 17) && (_messageNum == 3)) { + _messageNum++; + _scene->_kernelMessages.add(Common::Point(63, _posY), 0x1110, 0, 0, 240, _game.getQuote(56)); + _posY += 14; + } + + if ((_scene->_activeAnimation->getCurrentFrame() >= 20) && (_messageNum == 4)) { + _messageNum++; + _scene->_kernelMessages.add(Common::Point(63, _posY), 0x1110, 0, 0, 240, _game.getQuote(50)); + _posY += 14; + } + } +} + +void Scene101::preActions() { + if (_action.isAction(VERB_LOOK, NOUN_VIEW_SCREEN)) + _game._player._needToWalk = true; + + if (_sittingFl) { + if (_action.isAction(VERB_LOOK) || _action.isObject(NOUN_CHAIR) || _action.isAction(VERB_TALKTO) || _action.isAction(VERB_PEER_THROUGH) || _action.isAction(VERB_EXAMINE)) + _game._player._needToWalk = false; + + if (_game._player._needToWalk) { + switch (_game._trigger) { + case 0: + _game._player._readyToWalk = false; + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[11]); + _globals._sequenceIndexes[11] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[11], false, 3, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 1, 17); + _vm->_sound->command(16); + break; + + case 1: + _sittingFl = false; + _game._player._visible = true; + _game._player._stepEnabled = true; + _game._player._readyToWalk = true; + _scene->_hotspots.activate(71, true); + _scene->_dynamicHotspots.remove(_chairHotspotId); + _globals._sequenceIndexes[12] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[12], false, 6, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 4); + break; + + default: + break; + } + } + } + + if (_panelOpened && !(_action.isObject(NOUN_SHIELD_ACCESS_PANEL) || _action.isObject(NOUN_SHIELD_MODULATOR))) { + switch (_game._trigger) { + case 0: + if (_game._player._needToWalk) { + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _shieldSpriteIdx = _game._objects.isInRoom(OBJ_SHIELD_MODULATOR) ? 13 : 14; + _globals._sequenceIndexes[13] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[_shieldSpriteIdx], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _game._player._stepEnabled = false; + _vm->_sound->command(20); + } + break; + + case 1: + _game._player._stepEnabled = true; + _panelOpened = false; + _scene->_hotspots.activate(NOUN_SHIELD_MODULATOR, false); + break; + + default: + break; + } + } +} + +void Scene101::actions() { + if (_action._lookFlag) { + _vm->_dialogs->show(10125); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_WALKTO, NOUN_LIFE_SUPPORT_SECTION)) { + _scene->_nextSceneId = 102; + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_SIT_IN, NOUN_CHAIR) || (_action.isAction(VERB_LOOK, NOUN_VIEW_SCREEN) && !_sittingFl)) { + if (!_sittingFl) { + switch (_game._trigger) { + case 0: + _scene->_sequences.remove(_globals._sequenceIndexes[12]); + _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 3, 1); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 1, 17); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_SPRITE, 10, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + _game._player._stepEnabled = false; + _game._player._visible = false; + _action._inProgress = false; + return; + + case 1: + _vm->_sound->command(16); + break; + + case 2: + _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 3, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 17, 17); + _game._player._stepEnabled = true; + _sittingFl = true; + _scene->_hotspots.activate(71, false); + _chairHotspotId = _scene->_dynamicHotspots.add(NOUN_CHAIR, VERB_SIT_IN, -1, Common::Rect(159, 84, 159 + 33, 84 + 36)); + if (!_action.isAction(VERB_LOOK, NOUN_VIEW_SCREEN)) { + _action._inProgress = false; + return; + } + _game._trigger = 0; + break; + + default: + break; + } + } else { + _vm->_dialogs->show(10131); + _action._inProgress = false; + return; + } + } + + if ((_action.isAction(VERB_WALKTO, NOUN_SHIELD_ACCESS_PANEL) || _action.isAction(VERB_OPEN, NOUN_SHIELD_ACCESS_PANEL)) && !_panelOpened) { + switch (_game._trigger) { + case 0: + _shieldSpriteIdx = _game._objects.isInRoom(OBJ_SHIELD_MODULATOR) ? 13 : 14; + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[_shieldSpriteIdx], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _game._player._stepEnabled = false; + _vm->_sound->command(20); + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[_shieldSpriteIdx], false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], -2, -2); + _game._player._stepEnabled = true; + _panelOpened = true; + if (_game._objects.isInRoom(OBJ_SHIELD_MODULATOR)) + _scene->_hotspots.activate(NOUN_SHIELD_MODULATOR, true); + break; + + default: + break; + } + _action._inProgress = false; + return; + } + + if ((_action.isAction(VERB_TAKE, NOUN_SHIELD_MODULATOR) || _action.isAction(VERB_PULL, NOUN_SHIELD_MODULATOR)) && _game._objects.isInRoom(OBJ_SHIELD_MODULATOR)) { + _game._objects.addToInventory(OBJ_SHIELD_MODULATOR); + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[14], false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], -2, -2); + _scene->_hotspots.activate(NOUN_SHIELD_MODULATOR, false); + _vm->_dialogs->showItem(OBJ_SHIELD_MODULATOR, 10120); + _vm->_sound->command(22); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_SHIELD_ACCESS_PANEL) || (_action.isAction(VERB_LOOK, NOUN_SHIELD_MODULATOR) && !_game._objects.isInInventory(OBJ_SHIELD_MODULATOR)) ) { + if (_panelOpened) { + if (_game._objects.isInRoom(OBJ_SHIELD_MODULATOR)) + _vm->_dialogs->show(10128); + else + _vm->_dialogs->show(10129); + } else + _vm->_dialogs->show(10127); + + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_OPEN, NOUN_SHIELD_ACCESS_PANEL) && _panelOpened) { + _vm->_dialogs->show(10130); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_VIEW_SCREEN) && _sittingFl) { + if (_globals[kWatchedViewScreen]) + sayDang(); + else { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[11]); + _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 3, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 17, 21); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _vm->_sound->command(17); + break; + + case 1: + _globals._sequenceIndexes[11] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[11], false, 3, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 17, 21); + break; + + case 2: + _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 3, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 17, 17); + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 3, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: + _game._player._stepEnabled = true; + _globals[kWatchedViewScreen] = true; + _sittingFl = true; + _scene->_nextSceneId = 112; + break; + + default: + break; + } + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_CHAIR)) { + _vm->_dialogs->show(10101); + _action._inProgress = false; + return; + } + + if ((_action.isAction(VERB_LOOK) || _action.isAction(VERB_PEER_THROUGH)) && (_action.isObject(NOUN_FRONT_WINDOW) || _action.isObject(NOUN_OUTSIDE))) { + _vm->_dialogs->show(10102); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_HULL) || _action.isAction(VERB_LOOK, NOUN_OUTER_HULL) || _action.isAction(VERB_EXAMINE, NOUN_HULL) || _action.isAction(VERB_EXAMINE, NOUN_OUTER_HULL)) { + _vm->_dialogs->show(10103); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_FUZZY_DICE)) { + _vm->_dialogs->show(10104); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_MIRROR) || _action.isAction(VERB_LOOK_IN, NOUN_MIRROR)) { + _vm->_dialogs->show(10105); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_CURTAINS)) { + _vm->_dialogs->show(10106); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_PLASTIC_JESUS)) { + _vm->_dialogs->show(10107); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_ESCAPE_HATCH) || (_action.isAction(VERB_OPEN, NOUN_ESCAPE_HATCH) && !_game._objects.isInInventory(OBJ_REBREATHER))) { + _vm->_dialogs->show(10109); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_OPEN, NOUN_ESCAPE_HATCH)) { + _vm->_dialogs->show(10110); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_TARGET_COMPUTER)) { + _vm->_dialogs->show(10111); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_LIBRARY_COMPUTER)) { + _vm->_dialogs->show(10126); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_DAMAGE_CONTROL_PANEL)) { + _vm->_dialogs->show(10112); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_NAVIGATION_CONTROLS)) { + _vm->_dialogs->show(10113); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_ENGINEERING_CONTROLS)) { + _vm->_dialogs->show(10114); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_WEAPONS_DISPLAY)) { + _vm->_dialogs->show(10115); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_SHIELD_STATUS_PANEL)) { + _vm->_dialogs->show(10116); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_PLASTIC_JESUS)) { + _vm->_dialogs->show(10118); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_FUZZY_DICE)) { + _vm->_dialogs->show(10119); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_OPEN, NOUN_DAMAGE_CONTROL_PANEL)) { + _vm->_dialogs->show(10121); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_OPEN, NOUN_CURTAINS)) { + _vm->_dialogs->show(10122); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_CLOSE, NOUN_CURTAINS)) { + _vm->_dialogs->show(10123); + _action._inProgress = false; + return; + } + + if ((_action.isAction(VERB_LOOK) || _action.isAction(VERB_PLAY)) && _action.isObject(NOUN_VIDEO_GAME)) { + _vm->_dialogs->show(10124); + _action._inProgress = false; + return; + } +} + +/*------------------------------------------------------------------------*/ + +Scene102::Scene102(MADSEngine *vm) : Scene1xx(vm) { + _fridgeOpenedFl = false; + _fridgeOpenedDescr = false; + _fridgeFirstOpenFl = false; + _chairDescrFl = false; + _drawerDescrFl = false; + _activeMsgFl = false; + _fridgeCommentCount = 0; +} + +void Scene102::synchronize(Common::Serializer &s) { + Scene1xx::synchronize(s); + + s.syncAsByte(_fridgeOpenedFl); + s.syncAsByte(_fridgeOpenedDescr); + s.syncAsByte(_fridgeFirstOpenFl); + s.syncAsByte(_chairDescrFl); + s.syncAsByte(_drawerDescrFl); + s.syncAsByte(_activeMsgFl); + + s.syncAsSint16LE(_fridgeCommentCount); +} + +void Scene102::setup() { + _scene->_animationData->preLoad(formAnimName('A', -1), 3); + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene102::addRandomMessage() { + _scene->_kernelMessages.reset(); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + int quoteId = _vm->getRandomNumber(65, 69); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 73, 120, _game.getQuote(quoteId)); + _activeMsgFl = true; +} + +void Scene102::enter() { + sceneEntrySound(); + + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 3)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 4)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('x', 5)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('b', -1)); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('c', -1)); + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('e', -1)); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('n', -1)); + _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('g', -1)); + _globals._spriteIndexes[11] = _scene->_sprites.addSprites("*RXMRC_8"); + _globals._spriteIndexes[13] = _scene->_sprites.addSprites(formAnimName('x', 0)); + + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 8, 0, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 170, 0, 1, 6); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 11, 0, 2, 3); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 4, 0, 1, 0); + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 3, 0, 0, 5); + + if (_game._objects.isInRoom(OBJ_BINOCULARS)) + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 24, 0, 0, 24); + else + _scene->_hotspots.activate(NOUN_BINOCULARS, false); + + _scene->_hotspots.activate(NOUN_BURGER, false); + + if (_globals[kMedicineCabinetOpen]) { + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 6, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], -2, -2); + } + + if (_scene->_priorSceneId == 101) { + _game._player._playerPos = Common::Point(229, 109); + _game._player._stepEnabled = false; + _globals._sequenceIndexes[6] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[6], false, 6, 1, 2, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 70); + } else if (_scene->_priorSceneId == 103) + _game._player._playerPos = Common::Point(47, 152); + else if (_scene->_priorSceneId != -2) { + _game._player._facing = FACING_NORTHWEST; + _game._player._playerPos = Common::Point(32, 129); + } + + if (_scene->_priorSceneId != 106) { + if (_globals[kWaterInAPuddle]) { + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], -2, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 5); + } + } else { + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 5); + _vm->_sound->command(24); + _vm->_sound->command(28); + } + + _fridgeOpenedFl = false; + _fridgeOpenedDescr = false; + _fridgeCommentCount = 0; + _fridgeFirstOpenFl = true; + _chairDescrFl = false; + _activeMsgFl = false; + + _game.loadQuoteSet(0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x45, 0x43, 0); + + if (_scene->_priorSceneId == 101) + _vm->_sound->command(20); +} + +void Scene102::step() { + if (_game._trigger == 70) + _game._player._stepEnabled = true; + + if (_game._trigger == 72) { + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], -2, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 5); + _scene->_sequences.addTimer(48, 90); + } + + if (_game._trigger >= 90) { + if (_game._trigger >= 94) { + _scene->loadAnimation(formAnimName('B', -1), 71); + _game._player._stepEnabled = false; + _game._player._visible = false; + + _globals[kWaterInAPuddle] = true; + _vm->_sound->command(24); + } else { + _vm->_sound->command(23); + _scene->_sequences.addTimer(48, _game._trigger + 1); + } + } + + if (_game._trigger == 71) { + _game._player._stepEnabled = true; + _game._player._visible = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + } + + if (_fridgeOpenedFl && !_fridgeOpenedDescr) { + _fridgeCommentCount++; + if (_fridgeCommentCount > 16384) { + _fridgeOpenedDescr = true; + _vm->_dialogs->show(10213); + } + } + + if (!_activeMsgFl && (_game._player._playerPos == Common::Point(177, 114)) && (_game._player._facing == FACING_NORTH) + && (_vm->getRandomNumber(1, 5000) == 1)) { + _scene->_kernelMessages.reset(); + _activeMsgFl = false; + addRandomMessage(); + } + + if (_game._trigger == 73) + _activeMsgFl = false; +} + +void Scene102::preActions() { + if (_action.isObject(NOUN_REFRIGERATOR) || _action.isObject(NOUN_POSTER)) + _game._player._needToWalk = _game._player._readyToWalk; + + if (_fridgeOpenedFl && !_action.isObject(NOUN_REFRIGERATOR)) { + switch (_game._trigger) { + case 0: + if (_game._player._needToWalk) { + _scene->_sequences.remove(_globals._sequenceIndexes[7]); + _globals._sequenceIndexes[7] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[7], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 15); + _game._player._stepEnabled = false; + _vm->_sound->command(20); + } + break; + + case 1: + if (_game._objects.isInRoom(OBJ_BURGER)) { + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _scene->_hotspots.activate(NOUN_BURGER, false); + } + _fridgeOpenedFl = false; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } + + if (_game._player._needToWalk) + _scene->_kernelMessages.reset(); +} + +void Scene102::actions() { + if (_action._lookFlag) { + _vm->_dialogs->show(10234); + _action._inProgress = false; + return; + } + + bool justOpenedFl = false; + if (_action.isObject(NOUN_REFRIGERATOR) && !_fridgeOpenedFl) { + switch (_game._trigger) { + case 0: + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 15); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + if (_game._objects.isInRoom(OBJ_BURGER)) { + _globals._sequenceIndexes[10] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[10], false, 7, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 14); + } + _game._player._stepEnabled = false; + _vm->_sound->command(20); + _action._inProgress = false; + return; + + case 1: + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], -2, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 15); + int delay; + if (_action.isAction(VERB_WALKTO) && !_fridgeFirstOpenFl) + delay = 0; + else + delay = 48; + _scene->_sequences.addTimer(delay, 2); + _action._inProgress = false; + return; + + case 2: + _fridgeOpenedFl = true; + _fridgeOpenedDescr = false; + _fridgeCommentCount = 0; + _game._player._stepEnabled = true; + justOpenedFl = true; + if (_game._objects.isInRoom(OBJ_BURGER)) + _scene->_hotspots.activate(NOUN_BURGER, true); + break; + + default: + break; + } + } + + if (_action.isAction(VERB_LOOK, NOUN_REFRIGERATOR) || _action.isAction(VERB_OPEN, NOUN_REFRIGERATOR)) { + if (_game._objects.isInRoom(OBJ_BURGER)) + _vm->_dialogs->show(10230); + else + _vm->_dialogs->show(10229); + + _fridgeFirstOpenFl = false; + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_WALKTO, NOUN_REFRIGERATOR) && justOpenedFl) { + _fridgeFirstOpenFl = false; + int quoteId = _vm->getRandomNumber(59, 63); + Common::String curQuote = _game.getQuote(quoteId); + int width = _vm->_font->getWidth(curQuote, -1); + _scene->_kernelMessages.reset(); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_kernelMessages.add(Common::Point(210, 60), 0x1110, 0, 73, 120, curQuote); + _scene->_kernelMessages.add(Common::Point(214 + width, 60), 0x1110, 0, 73, 120, _game.getQuote(64)); + _activeMsgFl = true; + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_CLOSE, NOUN_REFRIGERATOR)) { + _vm->_dialogs->show(10213); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_REFRIGERATOR)) { + _vm->_dialogs->show(8); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOOR)) { + switch (_game._trigger) { + case 0: + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _game._player._stepEnabled = false; + _vm->_sound->command(20); + break; + + case 1: + _scene->_nextSceneId = 101; + break; + + default: + break; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_WALKTO, NOUN_ENGINEERING_SECTION)) { + _scene->_nextSceneId = 103; + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_WALKTO, NOUN_POSTER) || _action.isAction(VERB_LOOK, NOUN_POSTER) || _action.isAction(VERB_WALKTO, NOUN_BINOCULARS)) { + addRandomMessage(); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_WEIGHT_MACHINE)) { + _vm->_dialogs->show(10212); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_ENGINEERING_SECTION)) { + _vm->_dialogs->show(10205); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_DOOR)) { + _vm->_dialogs->show(10204); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_STARE_AT, NOUN_CEILING) || _action.isAction(VERB_LOOK, NOUN_CEILING)) { + _vm->_dialogs->show(10203); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_STARE_AT, NOUN_OVERHEAD_LAMP) || _action.isAction(VERB_LOOK, NOUN_OVERHEAD_LAMP)) { + _vm->_dialogs->show(10202); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_ROBO_KITCHEN)) { + _vm->_dialogs->show(10215); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_PUT, NOUN_BURGER, NOUN_ROBO_KITCHEN) && _game._objects.isInInventory(OBJ_BURGER)) { + _vm->_dialogs->show(10216); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_PUT, NOUN_REFRIGERATOR) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) { + _vm->_dialogs->show(10217); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_PUT, NOUN_DEAD_FISH, NOUN_ROBO_KITCHEN) || _action.isAction(VERB_PUT, NOUN_STUFFED_FISH, NOUN_ROBO_KITCHEN)) { + _vm->_dialogs->show(10230); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_OPEN, NOUN_ROBO_KITCHEN)) { + _vm->_dialogs->show(10218); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_CLOSET)) { + _vm->_dialogs->show(10219); + _action._inProgress = false; + return; + } + + if ((_action.isObject(NOUN_LADDER) || _action.isObject(NOUN_HATCHWAY)) && (_action.isAction(VERB_LOOK) || _action.isAction(VERB_CLIMB_UP) || _action.isAction(VERB_CLIMB_THROUGH))) { + if (_game._objects.isInInventory(OBJ_REBREATHER)) { + if (!_action.isAction(VERB_CLIMB_UP) && !_action.isAction(VERB_CLIMB_THROUGH)) { + _vm->_dialogs->show(10231); + _action._inProgress = false; + return; + } + } else if (_action.isAction(VERB_LOOK) || (_game._difficulty != DIFFICULTY_EASY)) { + _vm->_dialogs->show(10222); + _action._inProgress = false; + return; + } + } + + if ((_action.isObject(NOUN_LADDER) || _action.isObject(NOUN_HATCHWAY)) && (_action.isAction(VERB_CLIMB_UP) || _action.isAction(VERB_CLIMB_THROUGH)) ) { + switch (_game._trigger) { + case 0: + _scene->loadAnimation(formAnimName('A', -1), 1); + _game._player._stepEnabled = false; + _game._player._visible = false; + break; + + case 1: + _vm->_sound->command(24); + _scene->_sequences.addTimer(48, 2); + break; + + case 2: + case 3: + case 4: + _vm->_sound->command(23); + _scene->_sequences.addTimer(48, _game._trigger + 1); + break; + + case 5: + _vm->_sound->command(24); + _scene->_sequences.addTimer(48, _game._trigger + 1); + break; + + case 6: + if (_game._objects.isInInventory(OBJ_REBREATHER) && !_game._visitedScenes.exists(106)) + _vm->_dialogs->show(10237); + _scene->_nextSceneId = 106; + break; + + default: + break; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_POWER_STATUS_PANEL)) { + _vm->_dialogs->show(10226); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_WINDOW) || _action.isAction(VERB_LOOK_THROUGH, NOUN_WINDOW)) { + _vm->_dialogs->show(10227); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_DOORWAY) || _action.isAction(VERB_WALKTO, NOUN_DOORWAY)) { + _vm->_dialogs->show(10228); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_DRAWER) || ((_action.isAction(VERB_CLOSE, NOUN_DRAWER) || _action.isAction(VERB_PUSH, NOUN_DRAWER)) && !_drawerDescrFl)) { + _vm->_dialogs->show(10220); + _drawerDescrFl = true; + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_CLOSE, NOUN_DRAWER) || _action.isAction(VERB_PUSH, NOUN_DRAWER)) { + _vm->_dialogs->show(10221); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_OPEN, NOUN_DRAWER)) { + _vm->_dialogs->show(10236); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_CHAIR) || (_action.isAction(VERB_SIT_IN, NOUN_CHAIR) && !_chairDescrFl)) { + _chairDescrFl = true; + _vm->_dialogs->show(10210); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_SIT_IN, NOUN_CHAIR)) { + _vm->_dialogs->show(10211); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_MEDICINE_CABINET)) { + if (_globals[kMedicineCabinetOpen]) + _vm->_dialogs->show(10207); + else + _vm->_dialogs->show(10206); + + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_CLOSE, NOUN_MEDICINE_CABINET) && _globals[kMedicineCabinetOpen]) { + switch (_game._trigger) { + case 0: + _scene->_sequences.remove(_globals._sequenceIndexes[8]); + _globals._sequenceIndexes[8] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[8], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _game._player._stepEnabled = false; + _vm->_sound->command(21); + break; + + case 1: + _scene->_sequences.addTimer(48, 2); + break; + + case 2: + _game._player._stepEnabled = true; + _globals[kMedicineCabinetOpen] = false; + _vm->_dialogs->show(10209); + break; + + default: + break; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_OPEN, NOUN_MEDICINE_CABINET) && !_globals[kMedicineCabinetOpen]) { + switch (_game._trigger) { + case 0: + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _game._player._stepEnabled = false; + _vm->_sound->command(21); + break; + + case 1: + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], -2, -2); + _scene->_sequences.addTimer(48, 2); + break; + + case 2: + _game._player._stepEnabled = true; + _globals[kMedicineCabinetOpen] = true; + if (_globals[kMedicineCabinetVirgin]) { + _vm->_dialogs->show(10208); + } else { + _vm->_dialogs->show(10207); + } + _globals[kMedicineCabinetVirgin] = false; + break; + + default: + break; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_BINOCULARS) && _game._objects.isInRoom(OBJ_BINOCULARS)) { + switch (_game._trigger) { + case 0: + _globals._sequenceIndexes[11] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[11], false, 3, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[11]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _game._player._visible = false; + _game._player._stepEnabled = false; + break; + + case 1: + _game._objects.addToInventory(OBJ_BINOCULARS); + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _scene->_hotspots.activate(NOUN_BINOCULARS, false); + _game._player._visible = true; + _game._player._stepEnabled = true; + _vm->_sound->command(22); + _vm->_dialogs->showItem(OBJ_BINOCULARS, 10201); + break; + + default: + break; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_BURGER) && _game._objects.isInRoom(OBJ_BURGER)) { + if (_game._trigger == 0) { + _vm->_dialogs->showItem(OBJ_BURGER, 10235); + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _game._objects.addToInventory(OBJ_BURGER); + _scene->_hotspots.activate(NOUN_BURGER, false); + _vm->_sound->command(22); + _game._player._visible = true; + _game._player._stepEnabled = true; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_POSTER)) { + _vm->_dialogs->show(10224); + _action._inProgress = false; + return; + } + + if ((_action.isAction(VERB_PUSH) || _action.isAction(VERB_PULL)) && _action.isObject(NOUN_WEIGHT_MACHINE)) { + _vm->_dialogs->show(10225); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_FLOOR)) { + _vm->_dialogs->show(10232); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS) && !_game._objects.isInInventory(OBJ_BINOCULARS)) { + _vm->_dialogs->show(10233); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_BURGER) && (_action._mainObjectSource == 4)) { + _vm->_dialogs->show(801); + _action._inProgress = false; + } +} + +void Scene102::postActions() { + if (_action.isAction(VERB_PUT, NOUN_ROBO_KITCHEN) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) { + _vm->_dialogs->show(10217); + _action._inProgress = false; + } +} + +/*------------------------------------------------------------------------*/ + +Scene103::Scene103(MADSEngine *vm) : Scene1xx(vm) { + _updateClock = 0; +} + +void Scene103::synchronize(Common::Serializer &s) { + Scene1xx::synchronize(s); + + byte dummy = 0; + s.syncAsByte(dummy); // In order to avoid to break savegame compatibility + s.syncAsUint32LE(_updateClock); +} + +void Scene103::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene103::enter() { + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 3)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 4)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('x', 5)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('b', -1)); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('h', -1)); + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('m', -1)); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('t', -1)); + _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('r', -1)); + _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('c', -1)); + _globals._spriteIndexes[12] = _scene->_sprites.addSprites("*RXMBD_2"); + _globals._spriteIndexes[13] = _scene->_sprites.addSprites("*RXMRD_3"); + _globals._spriteIndexes[15] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 7, 0, 1, 0); + + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 0, 2, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 0); + + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 0, 0, 25); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 2, 72); + + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 0, 1, 37); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 2, 73); + + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8); + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 6); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6); + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 6); + + if (_game._objects.isInRoom(OBJ_TIMER_MODULE)) + _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 6); + else + _vm->_game->_scene._hotspots.activate(371, false); + + if (_game._objects.isInRoom(OBJ_REBREATHER)) + _globals._sequenceIndexes[10] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[10], false, 6); + else + _vm->_game->_scene._hotspots.activate(289, false); + + if (_globals[kTurkeyExploded]) { + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 6); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], -2, -2); + _scene->_hotspots.activate(362, false); + } + + if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(237, 74); + + if (_scene->_priorSceneId == 102) { + _game._player._stepEnabled = false; + _globals._sequenceIndexes[6] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[6], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 70); + } + + sceneEntrySound(); + _vm->_game->loadQuoteSet(70, 51, 71, 7, 73, 0); + + if (!_game._visitedScenes._sceneRevisited) { + int msgIndex = _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(70)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + } + + if (_scene->_priorSceneId == 102) + _vm->_sound->command(20); + + _vm->_palette->setEntry(252, 63, 63, 10); + _vm->_palette->setEntry(253, 45, 45, 10); + _updateClock = _scene->_frameStartTime; +} + +void Scene103::step() { + switch (_vm->_game->_trigger) { + case 70: + _vm->_game->_player._stepEnabled = true; + break; + + case 72: { + Common::Point pt = _vm->_game->_player._playerPos; + int dist = _vm->hypotenuse(pt.x - 58, pt.y - 93); + _vm->_sound->command(27, (dist * -128 / 378) + 127); + } + break; + + case 73: { + Common::Point pt = _vm->_game->_player._playerPos; + int dist = _vm->hypotenuse(pt.x - 266, pt.y - 81); + _vm->_sound->command(27, (dist * -127 / 378) + 127); + } + break; + + default: + break; + } + + if (_scene->_frameStartTime >= _updateClock) { + Common::Point pt = _vm->_game->_player._playerPos; + int dist = _vm->hypotenuse(pt.x - 79, pt.y - 137); + _vm->_sound->command(29, (dist * -127 / 378) + 127); + + pt = _vm->_game->_player._playerPos; + dist = _vm->hypotenuse(pt.x - 69, pt.y - 80); + _vm->_sound->command(30, (dist * -127 / 378) + 127); + + pt = _vm->_game->_player._playerPos; + dist = _vm->hypotenuse(pt.x - 266, pt.y - 138); + _vm->_sound->command(32, (dist * -127 / 378) + 127); + + _updateClock = _scene->_frameStartTime + _vm->_game->_player._ticksAmount; + } +} + +void Scene103::actions() { + if (_action._savedFields._lookFlag) + _vm->_dialogs->show(10322); + else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOOR)) { + switch (_vm->_game->_trigger) { + case 0: + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 6, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _game._player._stepEnabled = false; + _vm->_sound->command(20); + break; + + case 1: + _vm->_sound->command(1); + _scene->_nextSceneId = 102; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_TAKE, NOUN_TIMER_MODULE) && _game._objects.isInRoom(OBJ_TIMER_MODULE)) { + switch (_vm->_game->_trigger) { + case 0: + _scene->changeVariant(1); + _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 3, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[13]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_SPRITE, 7, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + _vm->_game->_player._visible = false; + _vm->_game->_player._stepEnabled = false; + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[11]); + break; + + case 2: + _vm->_sound->command(22); + _game._objects.addToInventory(OBJ_TIMER_MODULE); + _scene->changeVariant(0); + _scene->drawElements(kTransitionNone, false); + _scene->_hotspots.activate(371, false); + _vm->_game->_player._visible = true; + _vm->_game->_player._stepEnabled = true; + _vm->_dialogs->showItem(OBJ_REBREATHER, 805); + break; + + default: + break; + } + } else if (_action.isAction(VERB_TAKE, 289, 0) && _game._objects.isInRoom(OBJ_REBREATHER)) { + switch (_vm->_game->_trigger) { + case 0: + _scene->changeVariant(1); + _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 3, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[12]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_SPRITE, 6, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + _vm->_game->_player._visible = false; + _vm->_game->_player._stepEnabled = false; + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + break; + + case 2: + _vm->_sound->command(22); + _game._objects.addToInventory(OBJ_REBREATHER); + _scene->_hotspots.activate(289, false); + _vm->_game->_player._visible = true; + _vm->_game->_player._stepEnabled = true; + _vm->_dialogs->showItem(OBJ_REBREATHER, 804); + break; + + default: + break; + } + } else if (_action.isAction(VERB_LOOK, 362)) + _vm->_dialogs->show(10301); + else if (_action.isAction(VERB_TAKE, 362)) { + // Take Turkey + if (!_vm->_game->_trigger) + _vm->_sound->command(31); + + if (_vm->_game->_trigger < 2) { + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 6, _vm->_game->_trigger < 1 ? 1 : 0); + if (_vm->_game->_trigger) { + // Lock the turkey into a permanent "exploded" frame + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], -2, -2); + + // Rex says "Gads.." + Common::String msg = _game.getQuote(51); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 18, 0, 60, msg); + _scene->_sequences.addTimer(120, _vm->_game->_trigger + 1); + } else { + // Initial turky explosion + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + } + } + + // Re-enable player if sequence is ended, and set global flag + _game._player._stepEnabled = _game._trigger == 2; + _globals[kTurkeyExploded] = -1; + + if (_game._trigger == 2) { + // Show exposition dialog at end of sequence + _vm->_dialogs->show(10302); + _scene->_hotspots.activate(362, false); + } + } else if (_action.isAction(VERB_LOOK, 250)) + _vm->_dialogs->show(!_globals[kTurkeyExploded] ? 10323 : 10303); + else if (_action.isAction(VERB_TALKTO, 27)) { + switch (_vm->_game->_trigger) { + case 0: { + _game._player._stepEnabled = false; + Common::String msg = _game.getQuote(71); + _scene->_kernelMessages.add(Common::Point(), 0x1110, 18, 1, 120, msg); + break; + } + + case 1: { + Common::String msg = _game.getQuote(72); + _scene->_kernelMessages.add(Common::Point(310, 132), 0xFDFC, 16, 2, 120, msg); + break; + } + + case 2: + _scene->_kernelMessages.reset(); + _scene->_sequences.addTimer(1, 3); + break; + + case 3: + _game._player._stepEnabled = true; + _vm->_dialogs->show(10306); + break; + + default: + break; + } + } else if (_action.isAction(VERB_LOOK, 27)) + _vm->_dialogs->show(10304); + else if (_action.isAction(VERB_LOOK, 36)) + _vm->_dialogs->show(10307); + else if (_action.isAction(VERB_LOOK, 55)) + _vm->_dialogs->show(10308); + else if (_action.isAction(VERB_TAKE, 315)) + _vm->_dialogs->show(10309); + else if (_action.isAction(VERB_TAKE, 85)) + _vm->_dialogs->show(10310); + else if (_action.isAction(VERB_LOOK, 144)) + _vm->_dialogs->show(10312); + else if (_action.isAction(VERB_OPEN, 144)) + _vm->_dialogs->show(10313); + else if (_action.isAction(VERB_CLOSE, 27)) + _vm->_dialogs->show(10314); + else if (_action.isAction(VERB_LOOK, 310)) + _vm->_dialogs->show(10315); + else if (_action.isAction(VERB_LOOK, 178)) + _vm->_dialogs->show(10316); + else if (_action.isAction(VERB_LOOK, 283)) + _vm->_dialogs->show(10317); + else if (_action.isAction(VERB_LOOK, 120)) + _vm->_dialogs->show(10318); + else if (_action.isAction(VERB_LOOK, 289) && _game._objects.isInInventory(OBJ_REBREATHER)) + _vm->_dialogs->show(10319); + else if (_action.isAction(VERB_LOOK, 371) && _game._objects.isInInventory(OBJ_TIMER_MODULE)) + _vm->_dialogs->show(10320); + else if (_action.isAction(VERB_LOOK, 137)) + _vm->_dialogs->show(10321); + else if (_action.isAction(VERB_LOOK, 409)) + _vm->_dialogs->show(_game._objects.isInInventory(OBJ_TIMER_MODULE) ? 10324 : 10325); + else + return; + + _action._inProgress = false; +} + +void Scene103::postActions() { + if (_action.isObject(NOUN_AUXILIARY_POWER) && !_action.isAction(VERB_WALKTO)) { + _vm->_dialogs->show(10305); + _action._inProgress = false; + } else if (_action.isAction(VERB_PUT, NOUN_COAL, NOUN_FURNACE)) { + Common::String msg = _game.getQuote(73); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, msg); + _action._inProgress = false; + } +} + +/*------------------------------------------------------------------------*/ + +Scene104::Scene104(MADSEngine *vm) : Scene1xx(vm) { + _kargShootingFl = false; + _loseFl = false; +} + +void Scene104::synchronize(Common::Serializer &s) { + Scene1xx::synchronize(s); + + s.syncAsByte(_kargShootingFl); + s.syncAsByte(_loseFl); +} + +void Scene104::setup() { + // Preloading has been skipped + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene104::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('h', -1)); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 14, 0, 0, 1); + + if (_scene->_priorSceneId == 105) + _game._player._playerPos = Common::Point(302, 107); + else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(160, 134); + + _loseFl = false; + _game.loadQuoteSet(0x35, 0x34, 0); + _kargShootingFl = false; + + if (_vm->getRandomNumber(1, 3) == 1) { + _scene->loadAnimation(Resources::formatName(104, 'B', -1, EXT_AA, ""), 0); + _kargShootingFl = true; + } + + sceneEntrySound(); +} + +void Scene104::step() { + if ((_game._player._playerPos == Common::Point(189, 70)) && (_game._trigger || !_loseFl)) { + if (_game._player._facing == FACING_SOUTHWEST || _game._player._facing == FACING_SOUTHEAST) + _game._player._facing = FACING_SOUTH; + + if (_game._player._facing == FACING_NORTHWEST || _game._player._facing == FACING_NORTHEAST) + _game._player._facing = FACING_NORTH; + + bool mirrorFl = false; + if (_game._player._facing == FACING_WEST) { + _game._player._facing = FACING_EAST; + mirrorFl = true; + } + + _loseFl = true; + + switch (_game._player._facing) { + case FACING_EAST: + switch (_game._trigger) { + case 0: + _scene->_kernelMessages.reset(); + _scene->freeAnimation(); + _scene->resetScene(); + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 0)); + _vm->_palette->refreshSceneColors(); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], mirrorFl, 7, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(198, 143)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], mirrorFl, 7, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(198, 143)); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -2, -2); + _scene->_sequences.addTimer(90, 2); + break; + + case 2: + _vm->_dialogs->show(10406); + _scene->_reloadSceneFlag = true; + break; + + default: + break; + } + break; + + case FACING_SOUTH: + switch (_game._trigger) { + case 0: + _scene->_kernelMessages.reset(); + _scene->freeAnimation(); + _scene->resetScene(); + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _vm->_palette->refreshSceneColors(); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(198, 143)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 4); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 14); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 5, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(198, 143)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 4); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 15, 32); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 2: + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 3, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(198, 143)); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], -2, -2); + _scene->_sequences.addTimer(90, 3); + break; + + case 3: + _vm->_dialogs->show(10406); + _scene->_reloadSceneFlag = true; + break; + + default: + break; + } + break; + + case FACING_NORTH: + switch (_game._trigger) { + case 0: + _scene->_kernelMessages.reset(); + _scene->freeAnimation(); + _scene->resetScene(); + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('a', 2)); + _vm->_palette->refreshSceneColors(); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 8, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(198, 143)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + if (_game._storyMode >= STORYMODE_NICE) + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 15, 2); + break; + + case 1: + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 8, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(198, 143)); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], -2, -2); + _scene->_sequences.addTimer(90, 2); + break; + + case 2: + _vm->_dialogs->show(10406); + _scene->_reloadSceneFlag = true; + break; + + default: + break; + } + break; + default: + break; + } + + if (!_game._trigger) + _vm->_sound->command(34); + } + + if (_game._player._moving && (_scene->_rails.getNext() > 0)) { + _game._player.cancelCommand(); + _game._player.startWalking(Common::Point(189, 70), FACING_NONE); + _scene->_rails.resetNext(); + } + + if ((_game._player._special > 0) && _game._player._stepEnabled) + _game._player._stepEnabled = false; + + if (_kargShootingFl && (_scene->_activeAnimation->getCurrentFrame() >= 19)) { + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(52)); + _kargShootingFl = false; + } +} + +void Scene104::preActions() { + if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_EASTERN_CLIFF_FACE)) + _game._player._walkOffScreenSceneId = 105; + + if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_OPEN_AREA_TO_SOUTH)) + _game._player._walkOffScreenSceneId = 106; +} + +void Scene104::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(10405); + else if (_action.isAction(VERB_LOOK, NOUN_CURIOUS_WEED_PATCH)) + _vm->_dialogs->show(10404); + else if (_action.isAction(VERB_LOOK, NOUN_SURFACE)) + _vm->_dialogs->show(10403); + else if (_action.isAction(VERB_LOOK, NOUN_CLIFF_FACE)) + _vm->_dialogs->show(10401); + else if (_action.isAction(VERB_LOOK, NOUN_OCEAN_FLOOR)) + _vm->_dialogs->show(10402); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene105::Scene105(MADSEngine *vm) : Scene1xx(vm) { + _explosionFl = false; +} + +void Scene105::synchronize(Common::Serializer &s) { + Scene1xx::synchronize(s); + + s.syncAsByte(_explosionFl); +} + +void Scene105::setup() { + // Preloading has been skipped + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene105::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('m', 1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('f', 4)); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 8, 0, 0, 0); + + if (_globals[kFishIn105]) { + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(48, 144)); + + int idx = _scene->_dynamicHotspots.add(101, 348, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(56, 141), FACING_NORTHWEST); + } + + if (_scene->_priorSceneId == 104) + _game._player._playerPos = Common::Point(13, 97); + else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(116, 147); + + _game.loadQuoteSet(0x4A, 0x4B, 0x4C, 0x35, 0x34, 0); + _explosionFl = false; + + sceneEntrySound(); +} + +void Scene105::step() { + if ((_game._player._playerPos == Common::Point(170, 87)) && (_game._trigger || !_explosionFl)) { + _explosionFl = true; + switch (_game._trigger) { + case 0: + _scene->_kernelMessages.reset(); + _scene->resetScene(); + _game._player._stepEnabled = false; + _game._player._visible = false; + + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('m', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('m', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('m', 3)); + _vm->_sound->command(33); + _scene->clearSequenceList(); + _vm->_palette->refreshSceneColors(); + + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + + if (_game._storyMode >= STORYMODE_NICE) + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_SPRITE, 8, 3); + break; + + case 1: + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], -2, -2); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 9, 1, 0, 0); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], _globals._sequenceIndexes[0]); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 8); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 5, 7); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 2: { + int oldIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 9, 0, 0, 0); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 8); + _scene->_sequences.addTimer(90, 3); + } + break; + + case 3: + _vm->_dialogs->show(10507); + _scene->_reloadSceneFlag = true; + _scene->_sequences.addTimer(90, 4); + break; + + default: + break; + } + } + + if (_game._player._moving && (_scene->_rails.getNext() > 0)) { + _game._player.cancelCommand(); + _game._player.startWalking(Common::Point(170, 87), FACING_NONE); + _scene->_rails.resetNext(); + } + + if ((_game._player._special > 0) && _game._player._stepEnabled) + _game._player._stepEnabled = false; +} + +void Scene105::preActions() { + if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_WESTERN_CLIFF_FACE)) + _game._player._walkOffScreenSceneId = 104; + + if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_OPEN_AREA_TO_SOUTH)) + _game._player._walkOffScreenSceneId = 107; + + if (_action.isObject(NOUN_MINE) && (_action.isAction(VERB_TALKTO) || _action.isAction(VERB_LOOK))) + _game._player._needToWalk = false; +} + +void Scene105::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(10512); + else if (_action.isAction(VERB_TAKE, NOUN_DEAD_FISH) && _globals[kFishIn105]) { + if (_game._objects.isInInventory(OBJ_DEAD_FISH)) { + int randVal = _vm->getRandomNumber(74, 76); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(randVal)); + } else { + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _game._objects.addToInventory(OBJ_DEAD_FISH); + _globals[kFishIn105] = false; + _vm->_dialogs->showItem(OBJ_DEAD_FISH, 802, 0); + } + } else if (_action.isAction(VERB_LOOK, NOUN_WESTERN_CLIFF_FACE)) + _vm->_dialogs->show(10501); + else if (_action.isAction(VERB_LOOK, NOUN_CLIFF_FACE)) + _vm->_dialogs->show(10502); + else if (_action.isAction(VERB_LOOK, NOUN_OCEAN_FLOOR)) + _vm->_dialogs->show(10503); + else if (_action.isAction(VERB_LOOK, NOUN_MEDICAL_WASTE)) + _vm->_dialogs->show(10504); + else if (_action.isAction(VERB_TAKE, NOUN_MEDICAL_WASTE)) + _vm->_dialogs->show(10505); + else if (_action.isAction(VERB_LOOK, NOUN_MINE)) + _vm->_dialogs->show(10506); + else if (_action.isAction(VERB_LOOK, NOUN_DEAD_FISH)) + _vm->_dialogs->show(10508); + else if (_action.isAction(VERB_LOOK, NOUN_SURFACE)) + _vm->_dialogs->show(10509); + else if (_action.isAction(VERB_LOOK, NOUN_OPEN_AREA_TO_SOUTH)) + _vm->_dialogs->show(10510); + else if (_action.isAction(VERB_LOOK, NOUN_ROCKS)) + _vm->_dialogs->show(10511); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene106::Scene106(MADSEngine *vm) : Scene1xx(vm) { + _backToShipFl = false; + _shadowFl = false; + _firstEmergingFl = false; + _positionY = 0; +} + +void Scene106::synchronize(Common::Serializer &s) { + Scene1xx::synchronize(s); + + s.syncAsByte(_backToShipFl); + s.syncAsByte(_shadowFl); + s.syncAsByte(_firstEmergingFl); + s.syncAsSint32LE(_positionY); +} + +void Scene106::setup() { + setPlayerSpritesPrefix(); + setAAName(); + + if ((_scene->_priorSceneId == 102) && !_game._objects.isInInventory(OBJ_REBREATHER) && !_scene->_roomChanged) + _game._player._spritesPrefix = ""; + + _vm->_dialogs->_defaultPosition.y = 100; +} + +void Scene106::enter() { + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('H', -1)); + + if (_game._objects.isInInventory(OBJ_REBREATHER) || (_scene->_priorSceneId != 102) || _scene->_roomChanged) { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('A', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('A', 1)); + } + + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('G', -1)); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 21, 0, 0, 0); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('I', -1)); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 0, 32, 47); + + if (_scene->_priorSceneId == 102) { + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 6, 1, 4, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_EXPIRE, 0, 70); + _game._player._visible = false; + _game._player._stepEnabled = false; + _game._player._facing = FACING_EAST; + _game._player._playerPos = Common::Point(106, 69); + } else if (_scene->_priorSceneId != -2) { + if (_scene->_priorSceneId == 107) { + _game._player._playerPos = Common::Point(319, 84); + _game._player._facing = _game._player._prepareWalkFacing = FACING_WEST; + } else { + _game._player._playerPos = Common::Point(319, 44); + _game._player._facing = _game._player._prepareWalkFacing = FACING_SOUTHWEST; + _scene->_sprites[_game._player._spritesStart + 3]->_charInfo->_velocity = 24; + } + + _game._player._prepareWalkPos = Common::Point(246, 69); + _game._player._needToWalk = true; + _game._player._readyToWalk = true; + } + + if (_scene->_priorSceneId != 102) { + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[0], -2, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 14); + } + + _backToShipFl = false; + _shadowFl = false; + _firstEmergingFl = false; + + _game.loadQuoteSet(0x31, 0x32, 0x34, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0); + sceneEntrySound(); +} + +void Scene106::step() { + if (_game._trigger == 70) { + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[0], -2, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 14); + + if (!_game._objects.isInInventory(OBJ_REBREATHER) && !_scene->_roomChanged) { + _scene->loadAnimation(Resources::formatName(106, 'A', -1, EXT_AA, ""), 75); + } else { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 4, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_SPRITE, 28, 71); + } + } + + if (_game._trigger == 71) { + _game._player._prepareWalkPos = Common::Point(246, 69); + _game._player._prepareWalkFacing = FACING_EAST; + _game._player._needToWalk = true; + _game._player._readyToWalk = true; + _game._player._visible = true; + + if (_game._visitedScenes._sceneRevisited) { + _game._player._stepEnabled = true; + } else { + _game._player._prepareWalkFacing = FACING_SOUTHWEST; + _firstEmergingFl = true; + _scene->loadAnimation(Resources::formatName(106, 'B', -1, EXT_AA, ""), 80); + } + } + + if (_firstEmergingFl && (_scene->_activeAnimation->getCurrentFrame() >= 19)) { + _firstEmergingFl = false; + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(52)); + } + + if ((_game._trigger >= 80) && (_game._trigger <= 87)) { + int tmpVal = _game._trigger - 80; + int msgId = -1; + switch (tmpVal) { + case 0: + _positionY = 26; + msgId = 49; + break; + + case 1: + case 2: + case 3: + case 4: + case 5: + msgId = 76 + tmpVal; + break; + + case 6: + msgId = 50; + break; + + default: + msgId = -1; + _game._player._stepEnabled = true; + break; + } + + if (msgId >= 0) { + int nextAbortVal = _game._trigger + 1; + _scene->_kernelMessages.add(Common::Point(15, _positionY), 0x1110, 0, 0, 360, _game.getQuote(msgId)); + _scene->_sequences.addTimer(150, nextAbortVal); + _positionY += 14; + } + } + + if (_backToShipFl) { + if (!_shadowFl) { + if (_game._player._playerPos.x < 204) { + _shadowFl = true; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 4, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 44, 73); + } + } else if (_game._trigger == 73) + _game._player._visible = false; + else if (_game._trigger == 72) + _scene->_sequences.addTimer(24, 74); + else if (_game._trigger == 74) + _scene->_nextSceneId = 102; + } + + if (_game._trigger == 75) { + _game._visitedScenes.pop_back(); + _scene->_nextSceneId = 102; + } +} + +void Scene106::preActions() { + if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_SEA_CLIFF) || _action.isAction(VERB_SWIM_TOWARDS, NOUN_SEAWEED_BANK)) { + _game._player._stepEnabled = false; + _scene->_sprites[_game._player._spritesStart + 1]->_charInfo->_velocity = 24; + _game._player._walkOffScreenSceneId = 104; + } + + if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_OPEN_AREA_TO_EAST)) + _game._player._walkOffScreenSceneId = 107; +} + +void Scene106::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(10614); + else if (_action.isAction(VERB_SWIM_TO, NOUN_MAIN_AIRLOCK)) { + _game._player._stepEnabled = false; + _game._player._prepareWalkPos = Common::Point(95, 72); + _game._player._prepareWalkFacing = FACING_WEST; + _game._player._needToWalk = true; + _game._player._readyToWalk = true; + _game._player._frameNumber = 9; + _backToShipFl = true; + } else if (_action.isAction(VERB_LOOK, NOUN_ANEMONE) || _action.isAction(VERB_LOOK_AT, NOUN_ANEMONE)) + _vm->_dialogs->show(10601); + else if (_action.isAction(VERB_TAKE, NOUN_ANEMONE)) + _vm->_dialogs->show(10602); + else if (_action.isAction(VERB_LOOK, NOUN_SEAWEED) || _action.isAction(VERB_LOOK, NOUN_SEAWEED_BANK)) + _vm->_dialogs->show(10603); + else if (_action.isAction(VERB_TAKE, NOUN_SEAWEED) || _action.isAction(VERB_TAKE, NOUN_SEAWEED_BANK)) + _vm->_dialogs->show(10604); + else if (_action.isAction(VERB_LOOK, NOUN_OPEN_AREA_TO_EAST)) + _vm->_dialogs->show(10605); + else if (_action.isAction(VERB_LOOK, NOUN_PILE_OF_ROCKS) || _action.isAction(VERB_LOOK_AT, NOUN_PILE_OF_ROCKS)) + _vm->_dialogs->show(10606); + else if (_action.isObject(NOUN_PILE_OF_ROCKS) && (_action.isAction(VERB_PUSH) || _action.isAction(VERB_PULL) || _action.isAction(VERB_TAKE))) + _vm->_dialogs->show(10607); + else if (_action.isAction(VERB_LOOK, NOUN_SHIP) || _action.isAction(VERB_LOOK_AT, NOUN_SHIP)) + _vm->_dialogs->show(10608); + else if (_action.isAction(VERB_LOOK, NOUN_MAIN_AIRLOCK)) + _vm->_dialogs->show(10609); + else if (_action.isAction(VERB_OPEN, NOUN_MAIN_AIRLOCK)) + _vm->_dialogs->show(10610); + else if (_action.isAction(VERB_CLOSE, NOUN_MAIN_AIRLOCK)) + _vm->_dialogs->show(10611); + else if (_action.isAction(VERB_LOOK, NOUN_SEA_CLIFF)) + _vm->_dialogs->show(10612); + else if (_action.isAction(VERB_LOOK, NOUN_OCEAN_FLOOR)) + _vm->_dialogs->show(10613); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene107::Scene107(MADSEngine *vm) : Scene1xx(vm) { + _shootingFl = false; +} + +void Scene107::synchronize(Common::Serializer &s) { + Scene1xx::synchronize(s); + + s.syncAsByte(_shootingFl); +} + +void Scene107::setup() { + setPlayerSpritesPrefix(); + setAAName(); + + _scene->addActiveVocab(NOUN_MANTA_RAY); +} + +void Scene107::enter() { + for (int i = 0; i < 3; i++) + _globals._spriteIndexes[i + 1] = _scene->_sprites.addSprites(formAnimName('G', i)); + + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(Resources::formatName(105, 'f', 4, EXT_SS, "")); + + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 14, 0, 0, 7); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 17, 0, 0, 13); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 19, 0, 0, 9); + + for (int i = 1; i < 4; i++) + _scene->_sequences.setDepth(_globals._sequenceIndexes[i], 0); + + if (_globals[kFishIn107]) { + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(68, 151)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + int idx = _scene->_dynamicHotspots.add(101, 348, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(78, 135), FACING_SOUTHWEST); + } + + if (_scene->_priorSceneId == 105) + _game._player._playerPos = Common::Point(132, 47); + else if (_scene->_priorSceneId == 106) + _game._player._playerPos = Common::Point(20, 91); + else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(223, 151); + + if (((_scene->_priorSceneId == 105) || (_scene->_priorSceneId == 106)) && (_vm->getRandomNumber(1, 3) == 1)) { + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(Resources::formatName(105, 'R', 1, EXT_SS, "")); + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], true, 4, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[0], Common::Point(270, 150)); + _scene->_sequences.setMotion(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_SPRITE, -200, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 2); + _scene->_dynamicHotspots.add(218, 348, _globals._sequenceIndexes[0], Common::Rect(0, 0, 0, 0)); + } + + _game.loadQuoteSet(0x4A, 0x4B, 0x4C, 0x35, 0x34, 0); + _shootingFl = false; + + if (_vm->getRandomNumber(1, 3) == 1) { + _scene->loadAnimation(Resources::formatName(107, 'B', -1, EXT_AA, ""), 0); + _shootingFl = true; + } + + sceneEntrySound(); +} + +void Scene107::step() { + if (_shootingFl && (_scene->_activeAnimation->getCurrentFrame() >= 19)) { + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(52)); + _shootingFl = false; + } +} + +void Scene107::preActions() { + if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_OPEN_AREA_TO_WEST)) + _game._player._walkOffScreenSceneId = 106; + + if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_OPEN_AREA_TO_SOUTH)) + _game._player._walkOffScreenSceneId = 108; +} + +void Scene107::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(10708); + else if (_action.isAction(VERB_TAKE, NOUN_DEAD_FISH) && _globals[kFishIn107]) { + if (_game._objects.isInInventory(OBJ_DEAD_FISH)) { + int randVal = _vm->getRandomNumber(74, 76); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(randVal)); + } else { + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _game._objects.addToInventory(OBJ_DEAD_FISH); + _globals[kFishIn107] = false; + _vm->_dialogs->showItem(OBJ_DEAD_FISH, 802); + } + } else if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_NORTHERN_SEA_CLIFF)) + _scene->_nextSceneId = 105; + else if (_action.isAction(VERB_LOOK, NOUN_NORTHERN_SEA_CLIFF)) + _vm->_dialogs->show(10701); + else if (_action.isAction(VERB_LOOK, NOUN_DEAD_FISH) && (_action._mainObjectSource == 4)) + _vm->_dialogs->show(10702); + else if (_action.isAction(VERB_LOOK, NOUN_BUSH_LIKE_FORMATION)) + _vm->_dialogs->show(10703); + else if (_action.isAction(VERB_LOOK, NOUN_ROCK)) + _vm->_dialogs->show(10704); + else if (_action.isAction(VERB_LOOK, NOUN_SEAWEED)) + _vm->_dialogs->show(10705); + else if (_action.isAction(VERB_LOOK, NOUN_OPEN_AREA_TO_SOUTH)) + _vm->_dialogs->show(10706); + else if (_action.isAction(VERB_LOOK, NOUN_CLIFF_FACE)) + _vm->_dialogs->show(10707); + else if (_action.isAction(VERB_LOOK, NOUN_MANTA_RAY)) + _vm->_dialogs->show(10709); + else if (_action.isAction(VERB_TAKE, NOUN_MANTA_RAY)) + _vm->_dialogs->show(10710); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene108::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene108::enter() { + if (_globals[kHoovicSated] == 2) + _globals[kHoovicSated] = 0; + + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('X', 0)); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('X', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('X', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('X', 3)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(Resources::formatName(105, 'f', 4, EXT_SS, "")); + + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 13, 0, 0, 7); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 16, 0, 0, 9); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 17, 0, 0, 3); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 14, 0, 0, 13); + + for (int i = 0; i <= 3; i++) + _scene->_sequences.setDepth(_globals._sequenceIndexes[i], 0); + + if (_globals[kFishIn108]) { + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(41, 109)); + int idx = _scene->_dynamicHotspots.add(101, 348, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(41, 109), FACING_NORTHWEST); + } + + if (_scene->_priorSceneId == 107) + _game._player._playerPos = Common::Point(138, 58); + else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(305, 98); + + _game.loadQuoteSet(0x4A, 0x4B, 0x4C, 0x35, 0x34, 0); + sceneEntrySound(); +} + +void Scene108::preActions() { + if (_action.isAction(VERB_SWIM_UNDER, NOUN_OVERHANG_TO_EAST)) + _game._player._walkOffScreenSceneId = 109; +} + +void Scene108::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(10812); + else if (_action.isAction(VERB_TAKE, NOUN_DEAD_FISH) && _globals[kFishIn108]) { + if (_game._objects.isInInventory(OBJ_DEAD_FISH)) { + int randVal = _vm->getRandomNumber(74, 76); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(randVal)); + } else { + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _game._objects.addToInventory(OBJ_DEAD_FISH); + _globals[kFishIn108] = false; + _vm->_dialogs->showItem(OBJ_DEAD_FISH, 10808); + } + } else if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_OPEN_AREA_TO_NORTH)) + _scene->_nextSceneId = 107; + else if (_action.isAction(VERB_LOOK, NOUN_CLIFF_FACE)) + _vm->_dialogs->show(10801); + else if (_action.isAction(VERB_LOOK, NOUN_OCEAN_FLOOR)) + _vm->_dialogs->show(10802); + else if (_action.isAction(VERB_LOOK, NOUN_ODD_ROCK_FORMATION)) + _vm->_dialogs->show(10803); + else if (_action.isAction(VERB_TAKE, NOUN_ODD_ROCK_FORMATION)) + _vm->_dialogs->show(10804); + else if (_action.isAction(VERB_LOOK, NOUN_ROCKS)) + _vm->_dialogs->show(10805); + else if (_action.isAction(VERB_TAKE, NOUN_ROCKS)) + _vm->_dialogs->show(10806); + else if (_action.isAction(VERB_LOOK, NOUN_DEAD_FISH)) + _vm->_dialogs->show(10807); + else if (_action.isAction(VERB_LOOK, NOUN_OVERHANG_TO_EAST)) + _vm->_dialogs->show(10809); + else if (_action.isAction(VERB_LOOK, NOUN_OPEN_AREA_TO_NORTH)) + _vm->_dialogs->show(10810); + else if (_action.isAction(VERB_LOOK, NOUN_SURFACE)) + _vm->_dialogs->show(10811); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene109::Scene109(MADSEngine *vm) : Scene1xx(vm) { + _rexThrowingObject = false; + _hoovicDifficultFl = false; + _beforeEatingRex = false; + _eatingRex = false; + _hungryFl = false; + _eatingFirstFish = false; + + _throwingObjectId = -1; + _hoovicTrigger = 0; +} + +void Scene109::synchronize(Common::Serializer &s) { + Scene1xx::synchronize(s); + + s.syncAsByte(_rexThrowingObject); + s.syncAsByte(_hoovicDifficultFl); + s.syncAsByte(_beforeEatingRex); + s.syncAsByte(_eatingRex); + s.syncAsByte(_hungryFl); + s.syncAsByte(_eatingFirstFish); + s.syncAsSint32LE(_throwingObjectId); + s.syncAsSint32LE(_hoovicTrigger); +} + +void Scene109::setup() { + _scene->addActiveVocab(NOUN_DEAD_PURPLE_MONSTER); + _scene->addActiveVocab(NOUN_MONSTER_SLUDGE); + + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene109::enter() { + _globals[kFishIn105] = true; + + _globals._spriteIndexes[0] = _scene->_sprites.addSprites("*RXSWRC_6"); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('O', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('O', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('O', 0)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('H', 4)); + + _rexThrowingObject = false; + _throwingObjectId = 0; + _beforeEatingRex = false; + _eatingRex = false; + _hungryFl = false; + + if (_scene->_priorSceneId == 110) { + _game._player._playerPos = Common::Point(248, 38); + _globals[kHoovicSated] = 2; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(20, 68); + _game._player._facing = FACING_EAST; + } + + if (!_globals[kHoovicAlive]) { + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 4); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], -2, -2); + + int idx = _scene->_dynamicHotspots.add(102, 348, -1, Common::Rect(256, 57, 267, 87)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(241, 91), FACING_NORTHEAST); + idx = _scene->_dynamicHotspots.add(102, 348, -1, Common::Rect(242, 79, 265, 90)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(241, 91), FACING_NORTHEAST); + idx = _scene->_dynamicHotspots.add(229, 348, -1, Common::Rect(231, 88, 253, 94)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(241, 91), FACING_NORTHEAST); + } + + if (!_globals[kHoovicAlive] || _globals[kHoovicSated]) + _scene->changeVariant(1); + + if (_game._objects.isInRoom(OBJ_BURGER)) { + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], -2, -2); + int idx = _scene->_dynamicHotspots.add(53, 348, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-3, 0), FACING_NORTHEAST); + } else if (_scene->_roomChanged) + _game._objects.addToInventory(OBJ_BURGER); + + if (_scene->_roomChanged) { + _game._objects.addToInventory(OBJ_DEAD_FISH); + _game._objects.addToInventory(OBJ_STUFFED_FISH); + } + + _vm->_palette->setEntry(252, 50, 50, 63); + _vm->_palette->setEntry(253, 30, 30, 50); + + _game.loadQuoteSet(0x53, 0x52, 0x54, 0x55, 0x56, 0x57, 0x58, 0); + _eatingFirstFish = (!_game._visitedScenes._sceneRevisited) && (_scene->_priorSceneId < 110); + + if (_eatingFirstFish) { + _globals._spriteIndexes[10] = _scene->_sprites.addSprites(Resources::formatName(105, 'F', 1, EXT_SS, "")); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('H', 1)); + + _globals._sequenceIndexes[10] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[10], true, 4, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 5); + _scene->_sequences.setPosition(_globals._sequenceIndexes[10], Common::Point(126, 39)); + _scene->_sequences.setMotion(_globals._sequenceIndexes[10], 0, 200, 0); + _scene->_sequences.setScale(_globals._sequenceIndexes[10], 80); + _game._player._stepEnabled = false; + } + + sceneEntrySound(); +} + +void Scene109::step() { + if (_beforeEatingRex) { + if (!_eatingRex) { + if (_game._player._playerPos.x > 205) { + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 6, 70); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + + _eatingRex = true; + _vm->_sound->command(34); + } + } else { + switch (_game._trigger) { + case 70: + _game._player._visible = false; + break; + + case 71: + _scene->_reloadSceneFlag = true; + break; + } + } + } + + if (_hungryFl && (_game._player._playerPos == Common::Point(160, 32)) && (_game._player._facing == FACING_EAST)) { + _game._player.walk(Common::Point(226, 24), FACING_EAST); + _game._player._stepEnabled = false; + _hungryFl = false; + _beforeEatingRex = true; + _scene->_sprites.remove(_globals._spriteIndexes[6]); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('H', 0)); + _vm->_palette->refreshSceneColors(); + } + + if (_game._player._moving && (_scene->_rails.getNext() > 0) && _globals[kHoovicAlive] && !_globals[kHoovicSated] && !_hungryFl && !_beforeEatingRex) { + _game._player.cancelCommand(); + _game._player.startWalking(Common::Point(160, 32), FACING_EAST); + _scene->_rails.resetNext(); + _hungryFl = true; + } + + if (_eatingFirstFish && (_scene->_sequences[_globals._sequenceIndexes[10]]._position.x >= 178)) { + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 4, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_SPRITE, 29, 72); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 29, 73); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[10], _globals._sequenceIndexes[9]); + _eatingFirstFish = false; + _game._player._stepEnabled = true; + _vm->_sound->command(34); + } + + if (_game._trigger == 72) + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + + if (_game._trigger == 73) { + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _scene->_sprites.remove(_globals._spriteIndexes[9]); + _scene->_sprites.remove(_globals._spriteIndexes[10]); + + _scene->_spriteSlots.clear(); + _scene->_spriteSlots.fullRefresh(); + + int randVal = _vm->getRandomNumber(85, 88); + int idx = _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(randVal)); + _scene->_kernelMessages.setQuoted(idx, 4, true); + _scene->_kernelMessages._entries[idx]._frameTimer = _scene->_frameStartTime + 4; + } +} + +void Scene109::preActions() { + if (_action.isAction(VERB_SWIM_UNDER, NOUN_OVERHANG_TO_WEST)) + _game._player._walkOffScreenSceneId = 108; + + if ((_action.isAction(VERB_THROW) || _action.isAction(VERB_GIVE) || _action.isAction(VERB_PUT)) + && (_action.isObject(NOUN_SMALL_HOLE) || _action.isObject(NOUN_TUNNEL)) + && (_action.isObject(NOUN_DEAD_FISH) || _action.isObject(NOUN_STUFFED_FISH) || _action.isObject(NOUN_BURGER))) { + int idx = _game._objects.getIdFromDesc(_action._activeAction._objectNameId); + if ((idx >= 0) && _game._objects.isInInventory(idx)) { + _game._player._prepareWalkPos = Common::Point(106, 38); + _game._player._prepareWalkFacing = FACING_EAST; + _game._player._needToWalk = true; + _game._player._readyToWalk = true; + } + } + + if ((_action.isAction(VERB_SWIM_INTO, NOUN_TUNNEL) || _action.isAction(VERB_SWIM_TO, NOUN_SMALL_HOLE)) + && (!_globals[kHoovicAlive] || _globals[kHoovicSated]) && (_action.isObject(NOUN_TUNNEL))) + _game._player._walkOffScreenSceneId = 110; + + _hungryFl = false; +} + +void Scene109::actions() { + if (_action._lookFlag) { + _vm->_dialogs->show(10912); + _action._inProgress = false; + return; + } + + if ((_action.isAction(VERB_THROW) || _action.isAction(VERB_GIVE)) && (_action.isTarget(NOUN_SMALL_HOLE) || _action.isTarget(NOUN_TUNNEL))) { + if (_action.isObject(NOUN_DEAD_FISH) || _action.isObject(NOUN_STUFFED_FISH) || _action.isObject(NOUN_BURGER)) { + _throwingObjectId = _game._objects.getIdFromDesc(_action._activeAction._objectNameId); + if (_throwingObjectId >= 0) { + if ((_game._objects.isInInventory(_throwingObjectId) && _globals[kHoovicAlive]) || _rexThrowingObject) { + switch (_game._trigger) { + case 0: + _rexThrowingObject = true; + _hoovicDifficultFl = false; + _game._objects.setRoom(_throwingObjectId, NOWHERE); + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 4, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[0]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _game._player._visible = false; + _game._player._stepEnabled = false; + + switch (_throwingObjectId) { + case OBJ_DEAD_FISH: + case OBJ_STUFFED_FISH: + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('H', 1)); + break; + + case OBJ_BURGER: + _hoovicDifficultFl = (_game._difficulty == DIFFICULTY_EASY); + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('H', (_hoovicDifficultFl ? 3 : 1))); + break; + } + + _vm->_palette->refreshSceneColors(); + break; + + case 1: + _game._player._visible = true; + _hoovicTrigger = 4; + switch (_throwingObjectId) { + case OBJ_BURGER: + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, (_hoovicDifficultFl ? 4 : 6), 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 2, 2); + if (_hoovicDifficultFl) { + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 30); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 5); + } else { + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 8); + _hoovicTrigger = 3; + } + break; + case OBJ_DEAD_FISH: + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 4, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_SPRITE, 2, 2); + break; + case OBJ_STUFFED_FISH: + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 4, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 2, 2); + _hoovicTrigger = 3; + break; + } + break; + + case 2: + if (_hoovicDifficultFl) + _globals._sequenceIndexes[8] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[8], false, 4, 2, 0, 0); + else + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 4, 1, 0, 0); + + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, _hoovicTrigger); + _vm->_sound->command(34); + break; + + case 3: + _scene->loadAnimation(Resources::formatName(109, 'H', 2, EXT_AA, ""), 4); + _vm->_sound->command(35); + _globals[kHoovicAlive] = false; + break; + + case 4: + if (!_globals[kHoovicAlive]) { + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 4); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], -2, -2); + int idx = _scene->_dynamicHotspots.add(102, 348, -1, Common::Rect(256, 57, 256 + 12, 57 + 31)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(241, 91), FACING_NORTHEAST); + idx = _scene->_dynamicHotspots.add(102, 348, -1, Common::Rect(242, 79, 242 + 24, 79 + 12)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(241, 91), FACING_NORTHEAST); + idx = _scene->_dynamicHotspots.add(229, 348, -1, Common::Rect(231, 88, 231 + 23, 88 + 7)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(241, 91), FACING_NORTHEAST); + _scene->changeVariant(1); + } else { + if (_throwingObjectId == OBJ_DEAD_FISH) { + ++_globals[kHoovicFishEaten]; + int threshold; + switch (_game._difficulty) { + case DIFFICULTY_HARD: + threshold = 1; + break; + case DIFFICULTY_MEDIUM: + threshold = 3; + break; + default: + threshold = 50; + break; + } + + if (_globals[kHoovicFishEaten] >= threshold) { + int randVal = _vm->getRandomNumber(83, 84); + _scene->_kernelMessages.add(Common::Point(230, 24), 0xFDFC, 0, 0, 120, _game.getQuote(randVal)); + _globals[kHoovicFishEaten] = 0; + _globals[kHoovicSated] = 1; + _scene->changeVariant(1); + } + } + } + _scene->freeAnimation(); + _scene->_sequences.remove(_globals._sequenceIndexes[8]); + _scene->_sprites.remove(_globals._spriteIndexes[8]); + _scene->_spriteSlots.clear(); + _scene->_spriteSlots.fullRefresh(); + _scene->_sequences.scan(); + if (_game._player._visible) { + _game._player._forceRefresh = true; + _game._player.update(); + } + + _game._player._stepEnabled = true; + _rexThrowingObject = false; + break; + + case 5: { + _game._objects.setRoom(OBJ_BURGER, _scene->_currentSceneId); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 30, 30); + int idx = _scene->_dynamicHotspots.add(53, 348, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-3, 0), FACING_NORTHEAST); + _scene->_sequences.addTimer(65, 6); + } + break; + + case 6: { + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 31, 46); + int idx = _scene->_dynamicHotspots.add(53, 348, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-3, 0), FACING_NORTHEAST); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 7); + } + break; + + case 7: { + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + int idx = _scene->_dynamicHotspots.add(53, 348, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-3, 0), FACING_NORTHEAST); + _vm->_dialogs->show(10915); + } + break; + + case 8: + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 5, 16); + break; + } + _action._inProgress = false; + return; + } else if (_game._objects.isInInventory(_throwingObjectId)) { + // Nothing. + } + } + } + } + + if (_action.isAction(VERB_TAKE, NOUN_BURGER) && _game._objects.isInRoom(OBJ_BURGER)) { + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _game._objects.addToInventory(OBJ_BURGER); + } else if (_action.isAction(VERB_LOOK, NOUN_OCEAN_FLOOR)) + _vm->_dialogs->show(10901); + else if (_action.isAction(VERB_LOOK, NOUN_CORAL)) + _vm->_dialogs->show(10902); + else if ((_action.isAction(VERB_TAKE) || _action.isAction(VERB_PULL)) && _action.isObject(NOUN_CORAL)) + _vm->_dialogs->show(10903); + else if (_action.isAction(VERB_LOOK, NOUN_ROCKS)) + _vm->_dialogs->show(10904); + else if (_action.isAction(VERB_TAKE, NOUN_ROCKS)) + _vm->_dialogs->show(10905); + else if (_action.isAction(VERB_LOOK, NOUN_CAVE_WALL)) + _vm->_dialogs->show(10906); + else if (_action.isAction(VERB_LOOK, NOUN_TUNNEL)) { + if (_globals[kHoovicAlive]) + _vm->_dialogs->show(10907); + else + _vm->_dialogs->show(10913); + } else if (_action.isAction(VERB_LOOK, NOUN_SMALL_HOLE)) + _vm->_dialogs->show(10908); + else if (_action.isAction(VERB_LOOK, NOUN_OVERHANG_TO_WEST)) + _vm->_dialogs->show(10911); + else if (_action.isAction(VERB_PUT, NOUN_SMALL_HOLE)) + _vm->_dialogs->show(10910); + else if (_action.isAction(VERB_LOOK, NOUN_DEAD_PURPLE_MONSTER)) + _vm->_dialogs->show(10914); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene110::Scene110(MADSEngine *vm) : Scene1xx(vm) { + _crabsFl = false; +} + +void Scene110::synchronize(Common::Serializer &s) { + Scene1xx::synchronize(s); + + s.syncAsByte(_crabsFl); +} + +void Scene110::setup() { + setPlayerSpritesPrefix(); + setAAName(); + + _scene->addActiveVocab(NOUN_CRAB); +} + +void Scene110::enter() { + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('X', 0)); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('X', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('X', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('X', 3)); + + _crabsFl = false; + + if (_scene->_priorSceneId == 109) { + _game._player._playerPos = Common::Point(59, 71); + + _globals._sequenceIndexes[0] = _scene->_sequences.startCycle(_globals._spriteIndexes[0], false, 1); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + + _crabsFl = true; + + int idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[0], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE); + idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE); + idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE); + idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE); + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(194, 23); + _game._player._facing = FACING_SOUTH; + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->loadAnimation(Resources::formatName(110, 'T', 1,EXT_AA, ""), 70); + } + + sceneEntrySound(); + _game.loadQuoteSet(0x59, 0); + + if (!_game._visitedScenes._sceneRevisited && (_scene->_priorSceneId == 109)) + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(109)); +} + +void Scene110::step() { + if (_game._trigger == 70) { + _game._player._visible = true; + _game._player._stepEnabled = true; + } +} + +void Scene110::preActions() { + if (_action.isAction(VERB_SWIM_THROUGH, NOUN_CAVE_ENTRANCE)) + _game._player._walkOffScreenSceneId = 109; + + if (_crabsFl) { + _crabsFl = false; + + _scene->_sequences.remove(_globals._sequenceIndexes[0]); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 16, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 16, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 16, 1, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 16, 1, 0, 0); + + int idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[0], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE); + idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE); + idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE); + idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE); + } +} + +void Scene110::actions() { + if (_action.isAction(VERB_SWIM_THROUGH, NOUN_TUNNEL)) { + switch (_game._trigger) { + case 0: + _scene->loadAnimation(Resources::formatName(110, 'T', 0, EXT_AA, ""), 1); + _scene->_activeAnimation->setNextFrameTimer(_game._player._ticksAmount + _game._player._priorTimer); + _game._player._stepEnabled = false; + _game._player._visible = false; + break; + case 1: + _game._player._visible = true; + _game._player._stepEnabled = true; + _scene->_nextSceneId = 111; + break; + } + } else if ((_action._lookFlag) || _action.isAction(VERB_LOOK, NOUN_CAVE)) + _vm->_dialogs->show(11001); + else if (_action.isAction(VERB_LOOK, NOUN_CAVE_CEILING) || _action.isAction(VERB_LOOK_AT, NOUN_CAVE_CEILING)) + _vm->_dialogs->show(11002); + else if (_action.isAction(VERB_LOOK, NOUN_ROCKS)) + _vm->_dialogs->show(11003); + else if (_action.isAction(VERB_TAKE, NOUN_ROCKS)) + _vm->_dialogs->show(11004); + else if (_action.isAction(VERB_LOOK, NOUN_TUNNEL)) + _vm->_dialogs->show(11005); + else if (_action.isAction(VERB_LOOK, NOUN_CAVE_ENTRANCE)) + _vm->_dialogs->show(11006); + else if (_action.isAction(VERB_LOOK, NOUN_FUNGOIDS)) + _vm->_dialogs->show(11007); + else if (_action.isAction(VERB_TAKE, NOUN_FUNGOIDS)) + _vm->_dialogs->show(11008); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene111::Scene111(MADSEngine *vm) : Scene1xx(vm) { + _stampedFl = false; + _launch1Fl = false; + _launched2Fl = false; + _rexDivingFl = false; +} + +void Scene111::synchronize(Common::Serializer &s) { + Scene1xx::synchronize(s); + + s.syncAsByte(_stampedFl); + s.syncAsByte(_launch1Fl); + s.syncAsByte(_launched2Fl); + s.syncAsByte(_rexDivingFl); +} + +void Scene111::setup() { + _scene->addActiveVocab(NOUN_BATS); + + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene111::enter() { + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('X', 0)); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('X', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('X', 2)); + + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('B', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('B', 1)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('B', 2)); + + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 8, 0, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_SPRITE, 9, 73); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_SPRITE, 13, 73); + + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 0, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_SPRITE, 71, 71); + + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 0, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1); + + int idx = _scene->_dynamicHotspots.add(NOUN_BATS, VERB_LOOK_AT, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-2, 0), FACING_NONE); + idx = _scene->_dynamicHotspots.add(NOUN_BATS, VERB_LOOK_AT, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-2, 0), FACING_NONE); + idx = _scene->_dynamicHotspots.add(NOUN_BATS, VERB_LOOK_AT, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-2, 0), FACING_NONE); + + _launch1Fl = false; + _launched2Fl = false; + _stampedFl = false; + + if ((_scene->_priorSceneId < 201) && (_scene->_priorSceneId != -2)) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->loadAnimation(Resources::formatName(111, 'A', 0, EXT_AA, ""), 70); + _game._player._playerPos = Common::Point(234, 116); + _game._player._facing = FACING_EAST; + + _launch1Fl = true; + _launched2Fl = true; + + _vm->_sound->command(36); + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(300, 130); + _game._player._facing = FACING_WEST; + } + + _rexDivingFl = false; + + sceneEntrySound(); +} + +void Scene111::step() { + if (_game._trigger == 70) { + _game._player._stepEnabled = true; + _game._player._visible = true; + _launch1Fl = false; + _launched2Fl = false; + } + + if ((_game._trigger == 71) && !_stampedFl) { + _stampedFl = true; + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 18, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + } + + if (_game._trigger == 72) { + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 20); + } + + if (!_launch1Fl && (_vm->getRandomNumber(1, 5000) == 1)) { + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 5, 1, 0, 0); + _launch1Fl = true; + int idx = _scene->_dynamicHotspots.add(NOUN_BATS, VERB_LOOK_AT, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-2, 0), FACING_NONE); + } + + if (!_launched2Fl && (_vm->getRandomNumber(1, 30000) == 1)) { + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 5, 1, 0, 0); + int idx = _scene->_dynamicHotspots.add(NOUN_BATS, VERB_LOOK_AT, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-2, 0), FACING_NONE); + _launched2Fl = true; + } + + if (_game._trigger == 73) + _vm->_sound->command(37); + + if (_rexDivingFl && (_scene->_activeAnimation->getCurrentFrame() >= 9)) { + _vm->_sound->command(36); + _rexDivingFl = false; + } +} + +void Scene111::preActions() { + if (_action.isAction(VERB_WALK_THROUGH, NOUN_CAVE_ENTRANCE)) + _game._player._walkOffScreenSceneId = 212; +} + +void Scene111::actions() { + if (_action.isAction(VERB_DIVE_INTO, NOUN_POOL) && _game._objects.isInInventory(OBJ_REBREATHER)) { + switch (_game._trigger) { + case 0: + _scene->loadAnimation(Resources::formatName(111, 'A', 1, EXT_AA, ""), 1); + _rexDivingFl = true; + _game._player._stepEnabled = false; + _game._player._visible = false; + break; + + case 1: + _scene->_nextSceneId = 110; + break; + } + } else if (_action.isAction(VERB_LOOK, NOUN_CAVE_FLOOR)) + _vm->_dialogs->show(11101); + else if (_action.isAction(VERB_LOOK, NOUN_POOL)) + _vm->_dialogs->show(11102); + else if (_action.isAction(VERB_LOOK, NOUN_CAVE_ENTRANCE)) + _vm->_dialogs->show(11103); + else if (_action.isAction(VERB_LOOK, NOUN_STALAGMITES)) + _vm->_dialogs->show(11104); + else if (_action.isAction(VERB_LOOK, NOUN_LARGE_STALAGMITE)) + _vm->_dialogs->show(11105); + else if ((_action.isAction(VERB_PULL) || _action.isAction(VERB_TAKE)) && (_action.isObject(NOUN_STALAGMITES) || _action.isObject(NOUN_LARGE_STALAGMITE))) + _vm->_dialogs->show(11106); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene112::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene112::enter() { + sceneEntrySound(); + + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('X', 0)); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('X', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('X', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('X', 5)); + + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 10, 0, 17, 20); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 4, 0, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 0, 3, 0); + + _game._player._stepEnabled = false; + _game._player._visible = false; + + _scene->_userInterface.emptyConversationList(); + _scene->_userInterface.setup(kInputConversation); + + _scene->loadAnimation(Resources::formatName(112, 'X', -1, EXT_AA, ""), 70); +} + +void Scene112::step() { + if ((_scene->_activeAnimation != nullptr) && (_game._storyMode == STORYMODE_NICE)) { + if (_scene->_activeAnimation->getCurrentFrame() >= 54) { + _scene->freeAnimation(); + _game._trigger = 70; + } + } + + if (_game._trigger == 70) { + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 7, 3, 0, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + } + + if (_game._trigger == 71) { + _scene->_nextSceneId = 101; + _game._player._stepEnabled = true; + _game._player._visible = true; + } +} + +/*------------------------------------------------------------------------*/ + +} // End of namespace Nebular +} // End of namespace MADS diff --git a/engines/mads/nebular/nebular_scenes1.h b/engines/mads/nebular/nebular_scenes1.h new file mode 100644 index 0000000000..1afa7fccc1 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes1.h @@ -0,0 +1,264 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 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. + * + */ + +#ifndef MADS_NEBULAR_SCENES1_H +#define MADS_NEBULAR_SCENES1_H + +#include "common/scummsys.h" +#include "common/serializer.h" +#include "mads/game.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" + +namespace MADS { + +namespace Nebular { + +class Scene1xx : public NebularScene { +protected: + /** + * Plays an appropriate sound when entering a scene + */ + void sceneEntrySound(); + + /** + *Sets the AA file to use for the scene + */ + void setAAName(); + + /** + * Updates the prefix used for getting player sprites for the scene + */ + void setPlayerSpritesPrefix(); +public: + Scene1xx(MADSEngine *vm) : NebularScene(vm) {} +}; + +class Scene101 : public Scene1xx { +private: + bool _sittingFl; + bool _panelOpened; + + int _messageNum; + int _posY; + int _shieldSpriteIdx; + int _chairHotspotId; + int _oldSpecial; + + void sayDang(); + +public: + Scene101(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene102 : public Scene1xx { +private: + bool _fridgeOpenedFl; + bool _fridgeOpenedDescr; + bool _fridgeFirstOpenFl; + bool _chairDescrFl; + bool _drawerDescrFl; + bool _activeMsgFl; + + int _fridgeCommentCount; + + void addRandomMessage(); + +public: + Scene102(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); + virtual void postActions(); +}; + +class Scene103 : public Scene1xx { +private: + uint32 _updateClock; + +public: + Scene103(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); + virtual void postActions(); +}; + +class Scene104 : public Scene1xx { +private: + bool _kargShootingFl; + bool _loseFl; + +public: + Scene104(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene105 : public Scene1xx { +private: + bool _explosionFl; + +public: + Scene105(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene106 : public Scene1xx { +private: + bool _backToShipFl; + bool _shadowFl; + bool _firstEmergingFl; + + int _positionY; + +public: + Scene106(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene107 : public Scene1xx { +private: + bool _shootingFl; + +public: + Scene107(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene108 : public Scene1xx { +public: + Scene108(MADSEngine *vm) : Scene1xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene109 : public Scene1xx { +private: + bool _rexThrowingObject; + bool _hoovicDifficultFl; + bool _beforeEatingRex; + bool _eatingRex; + bool _hungryFl; + bool _eatingFirstFish; + + int _throwingObjectId; + int _hoovicTrigger; + +public: + Scene109(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene110 : public Scene1xx { +private: + bool _crabsFl; + +public: + Scene110(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene111 : public Scene1xx { +private: + bool _stampedFl; + bool _launch1Fl; + bool _launched2Fl; + bool _rexDivingFl; + +public: + Scene111(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene112 : public Scene1xx { +public: + Scene112(MADSEngine *vm) : Scene1xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions() {}; +}; + +} // End of namespace Nebular +} // End of namespace MADS + +#endif /* MADS_NEBULAR_SCENES1_H */ diff --git a/engines/mads/nebular/nebular_scenes2.cpp b/engines/mads/nebular/nebular_scenes2.cpp new file mode 100644 index 0000000000..36e7107609 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes2.cpp @@ -0,0 +1,5380 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "mads/mads.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/nebular/nebular_scenes2.h" + +namespace MADS { + +namespace Nebular { + +void Scene2xx::setAAName() { + int idx = (_scene->_nextSceneId == 216) ? 4 : 2; + _game._aaName = Resources::formatAAName(idx); +} + +void Scene2xx::setPlayerSpritesPrefix() { + _vm->_sound->command(5); + Common::String oldName = _game._player._spritesPrefix; + + switch(_scene->_nextSceneId) { + case 213: + case 216: + _game._player._spritesPrefix = ""; + break; + default: + if (_globals[kSexOfRex] != SEX_MALE) { + _game._player._spritesPrefix = "ROX"; + } else { + _game._player._spritesPrefix = "RXM"; + } + break; + } + + _game._player._scalingVelocity = (_scene->_nextSceneId <= 212); + + if (oldName != _game._player._spritesPrefix) + _game._player._spritesChanged = true; + + if ((_scene->_nextSceneId == 203 || _scene->_nextSceneId == 204) && _globals[kRhotundaStatus]) + _game._player._loadsFirst = false; + + _vm->_palette->setEntry(16, 10, 63, 63); + _vm->_palette->setEntry(17, 10, 45, 45); +} + +void Scene2xx::sceneEntrySound() { + if (_vm->_musicFlag) { + switch (_scene->_nextSceneId) { + case 201: + if ((_globals[kTeleporterCommand] == 2) || (_globals[kTeleporterCommand] == 4) || (_globals[kMeteorologistStatus] != 1)) + _vm->_sound->command(9); + else + _vm->_sound->command(17); + break; + case 202: + case 203: + case 204: + case 205: + case 208: + case 209: + case 212: + _vm->_sound->command(9); + break; + case 206: + case 211: + case 215: + _vm->_sound->command(10); + break; + case 207: + case 214: + _vm->_sound->command(11); + break; + case 210: + if (_globals[kTwinklesStatus] == 0) + _vm->_sound->command(15); + else + _vm->_sound->command(10); + break; + case 213: + if (_globals[kMeteorologistWatch] == METEOROLOGIST_NORMAL) + _vm->_sound->command(1); + else + _vm->_sound->command(9); + break; + case 216: + _vm->_sound->command(16); + break; + default: + _vm->_sound->command(10); + break; + } + } else + _vm->_sound->command(2); +} + +/*------------------------------------------------------------------------*/ + +Scene201::Scene201(MADSEngine *vm) : Scene2xx(vm) { + _pterodactylFlag = false; +} + +void Scene201::synchronize(Common::Serializer &s) { + Scene2xx::synchronize(s); + + s.syncAsByte(_pterodactylFlag); +} + +void Scene201::setup() { + setPlayerSpritesPrefix(); + setAAName(); + + _scene->addActiveVocab(NOUN_SWOOPING_CREATURE); + _scene->addActiveVocab(NOUN_BIRDS); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene201::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('m', -1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('b', -1)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*SC002Z1"); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 0, 1, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 15, 0, 0, 50); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 4, 0, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 8); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(185, 46)); + + int idx = _scene->_dynamicHotspots.add(NOUN_BIRDS, 209, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(186, 81), FACING_NORTH); + + if ((_scene->_priorSceneId == 202) || (_scene->_priorSceneId == -1)) { + _game._player._playerPos = Common::Point(165, 152); + } else { + _game._player._playerPos = Common::Point(223, 149); + _game._player._facing = FACING_SOUTH; + } + + if (_globals[kTeleporterCommand]) { + _game._player._visible = false; + _game._player._stepEnabled = false; + int sepChar = (_globals[kSexOfRex] == SEX_MALE) ? 't' : 'u'; + // Guess values. What is the default value used by the compiler? + int suffixNum = -1; + int abortTimers = -1; + switch(_globals[kTeleporterCommand]) { + case 1: + suffixNum = 3; + abortTimers = 76; + _globals[kTeleporterUnderstood] = true; + break; + case 2: + suffixNum = 1; + abortTimers = 77; + break; + case 3: + _game._player._visible = true; + _game._player._stepEnabled = true; + suffixNum = -1; + break; + case 4: + suffixNum = 2; + abortTimers = 78; + break; + } + _globals[kTeleporterCommand] = 0; + if (suffixNum >= 0) + _scene->loadAnimation(formAnimName(sepChar, suffixNum), abortTimers); + } + + if ((_scene->_priorSceneId == 202) && (_globals[kMeteorologistStatus] == METEOROLOGIST_PRESENT) && !_scene->_roomChanged) { + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('a', 0)); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _game.loadQuoteSet(90, 91, 0); + _game._player._stepEnabled = false; + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], -1, 12); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_SPRITE, 12, 70); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 1); + _pterodactylFlag = false; + _game._player.walk(Common::Point(157, 143), FACING_NORTH); + _vm->_palette->setEntry(252, 45, 63, 45); + _vm->_palette->setEntry(253, 20, 45, 20); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 2, 0, 120, _game.getQuote(90)); + } else + _pterodactylFlag = true; + + if (_globals[kTeleporterUnderstood]) + _scene->_hotspots.activate(NOUN_STRANGE_DEVICE, false); + + sceneEntrySound(); +} + +void Scene201::step() { + if (_pterodactylFlag && (_vm->getRandomNumber(5000) == 9)) { + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 5, 1, 6, 0); + int idx = _scene->_dynamicHotspots.add(351, 13, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(270, 80), FACING_EAST); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 8); + _vm->_sound->command(14); + _pterodactylFlag = false; + } + + if (_game._trigger == 70) { + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 9, 1, 0, 0); + _game._player._visible = false; + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 12, 16); + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 9, 1, 0, 0); + _vm->_sound->command(42); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_SPRITE, 3, 81); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 73); + } + + if (_game._trigger == 81) { + _scene->_kernelMessages.reset(); + } + + if (_game._trigger == 71) { + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 9, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], -2, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 1); + } + + if (_game._trigger == 73) { + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 9, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 17, -2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 74); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 1); + } + + if (_game._trigger == 74) { + _vm->_sound->command(40); + + _scene->_kernelMessages.add(Common::Point(125, 56), 0xFDFC, 32, 82, 180, _game.getQuote(91)); + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 9, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 1); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], -2, -2); + _scene->_sequences.addTimer(180, 75); + } + + if (_game._trigger == 75) { + _globals[kMeteorologistEverSeen] = 0; + _scene->_nextSceneId = 202; + } + + if (_game._trigger == 76) { + _game._player._stepEnabled = true; + _game._player._visible = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + } + + if (_game._trigger == 77) { + _globals[kTeleporterCommand] = 1; + _scene->_nextSceneId = _globals[kTeleporterDestination]; + _scene->_reloadSceneFlag = true; + } + + if (_game._trigger == 78) { + _vm->_sound->command(40); + _vm->_dialogs->show(20114); + _scene->_reloadSceneFlag = true; + } +} + +void Scene201::actions() { + if (_action._lookFlag == false) { + if (_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_SOUTH)) + _scene->_nextSceneId = 202; + else if (_action.isAction(VERB_CLIMB_UP, NOUN_STEPS) || (_action.isAction(VERB_WALK_INSIDE, NOUN_TELEPORTER)) || (_action.isAction(VERB_WALK_INSIDE, NOUN_STRANGE_DEVICE))) { + if (_game._trigger == 0) { + _game._player._stepEnabled = false; + _game._player._visible = false; + int sepChar = (_globals[kSexOfRex] == SEX_MALE) ? 't' : 'u'; + _scene->loadAnimation(formAnimName(sepChar, 0), 1); + } else if (_game._trigger == 1) { + _scene->_nextSceneId = 213; + } + } else if (_action.isAction(VERB_LOOK, NOUN_GRASSY_FIELD)) { + _vm->_dialogs->show(20101); + } else if (_action.isAction(VERB_LOOK, NOUN_ROCKS)) { + _vm->_dialogs->show(20102); + } else if (_action.isAction(VERB_LOOK, NOUN_THORNY_BUSH)) { + _vm->_dialogs->show(20103); + } else if (_action.isAction(VERB_LOOK, NOUN_SKY)) { + _vm->_dialogs->show(20104); + } else if (_action.isAction(VERB_LOOK, NOUN_WATER)) { + _vm->_dialogs->show(20105); + } else if (_action.isAction(VERB_LOOK, NOUN_ISLAND_IN_DISTANCE)) { + _vm->_dialogs->show(20106); + } else if (_action.isAction(VERB_LOOK, NOUN_WEATHER_STATION)) { + _vm->_dialogs->show(20107); + } else if (_action.isAction(VERB_LOOK, NOUN_PATH)) { + _vm->_dialogs->show(20108); + } else if (_action.isAction(VERB_LOOK, NOUN_FIELD_TO_SOUTH)) { + _vm->_dialogs->show(20110); + } else if (_action.isAction(VERB_LOOK, NOUN_STRANGE_DEVICE)) { + if (_globals[kMeteorologistEverSeen]) + _vm->_dialogs->show(20112); + else + _vm->_dialogs->show(20109); + } else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER)) { + _vm->_dialogs->show(20113); + } else + return; + } else { + _vm->_dialogs->show(20111); + } + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene202::Scene202(MADSEngine *vm) : Scene2xx(vm) { + _activeMsgFl = false; + _ladderTopFl = false; + _waitingMeteoFl = false; + _ladderHotspotId = -1; + _meteoClock1 = 0; + _meteoClock2 = 0; + _toStationFl = false; + _toTeleportFl = false; + _lastRoute = 0; + _stationCounter = 0; + _meteoFrame = 0; + _startTime = 0; + _meteorologistSpecial = false; +} + +void Scene202::synchronize(Common::Serializer &s) { + Scene2xx::synchronize(s); + + s.syncAsByte(_activeMsgFl); + s.syncAsByte(_ladderTopFl); + s.syncAsByte(_waitingMeteoFl); + s.syncAsByte(_toStationFl); + s.syncAsByte(_toTeleportFl); + + s.syncAsSint32LE(_ladderHotspotId); + s.syncAsSint32LE(_lastRoute); + s.syncAsSint32LE(_stationCounter); + s.syncAsSint32LE(_meteoFrame); + + s.syncAsUint32LE(_meteoClock1); + s.syncAsUint32LE(_meteoClock2); + s.syncAsUint32LE(_startTime); + + s.syncAsByte(_meteorologistSpecial); +} + +void Scene202::setup() { + setPlayerSpritesPrefix(); + setAAName(); + + _scene->addActiveVocab(NOUN_LADDER); + _scene->addActiveVocab(VERB_CLIMB_DOWN); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_BONE); + _scene->addActiveVocab(NOUN_SKULL); + _scene->addActiveVocab(NOUN_BROKEN_LADDER); +} + +void Scene202::enter() { + _game._player._beenVisible = true; + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('b', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('b', 1)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('b', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('l', -1)); + if (_globals[kSexOfRex] != SEX_MALE) { + _globals._spriteIndexes[7] = _scene->_sprites.addSprites("*ROXBD_2"); + } else { + _globals._spriteIndexes[7] = _scene->_sprites.addSprites("*RXMBD_2"); + } + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('a', 0)); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('a', 2)); + + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 0, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(149, 113)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 10); + int idx = _scene->_dynamicHotspots.add(NOUN_SKULL, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(153, 97), FACING_SOUTH); + + if (!(_globals[kBone202Status] & 1)) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(130, 108)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + idx = _scene->_dynamicHotspots.add(NOUN_BONE, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(132, 97), FACING_SOUTH); + } + + if (!(_globals[kBone202Status] & 2)) { + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 6, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[6], Common::Point(166, 110)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 10); + idx = _scene->_dynamicHotspots.add(NOUN_BONE, VERB_WALKTO, _globals._sequenceIndexes[6], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(165, 99), FACING_SOUTH); + } + + if (_globals[kBone202Status]) + _scene->changeVariant(_globals[kBone202Status]); + + if (_scene->_priorSceneId == 201) { + _game._player._playerPos = Common::Point(190, 91); + _game._player._facing = FACING_SOUTH; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(178, 152); + _game._player._facing = FACING_NORTH; + } + + if (_globals[kLadderBroken]) { + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 6, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 6); + _scene->_hotspots.activate(NOUN_LADDER, false); + idx = _scene->_dynamicHotspots.add(NOUN_BROKEN_LADDER, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(246, 124), FACING_NORTH); + } + + _game.loadQuoteSet(0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x62, 0x63, 0x64, 0x65, 0x66, 0x61, 0); + _activeMsgFl = false; + + if (_scene->_priorSceneId == -2) { + if (_waitingMeteoFl) { + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1); + _game._player._visible = false; + } + } else { + _waitingMeteoFl = false; + _ladderTopFl = false; + } + + _meteoClock1 = _meteoClock2 = _scene->_frameStartTime; + + if (_scene->_roomChanged) + _game._objects.addToInventory(OBJ_BINOCULARS); + + if (_globals[kMeteorologistWatch] != METEOROLOGIST_NORMAL) { + _game._player._visible = false; + _game._player._stepEnabled = false; + _ladderTopFl = (_globals[kMeteorologistWatch] == METEOROLOGIST_TOWER); + + if (_ladderTopFl) { + _globals._sequenceIndexes[10] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], true, 8); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 1); + + _scene->_sequences.setPosition(_globals._sequenceIndexes[10], Common::Point(247, 82)); + _game._player._playerPos = Common::Point(246, 124); + _game._player._facing = FACING_NORTH; + _globals[kTeleporterUnderstood] = true; + } else { + _globals._sequenceIndexes[10] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 1); + + _scene->_sequences.setPosition(_globals._sequenceIndexes[10], Common::Point(172, 123)); + _game._player._playerPos = Common::Point(171, 122); + _game._player._facing = FACING_NORTH; + } + + _scene->loadAnimation(formAnimName('M', -1), 71); + _scene->_activeAnimation->setCurrentFrame(200); + } else { + if (_ladderTopFl) { + _game._player._visible = false; + _scene->_sequences.startCycle(_globals._sequenceIndexes[9], true, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82)); + _game._player._playerPos = Common::Point(246, 124); + _game._player._facing = FACING_NORTH; + } + } + + _meteorologistSpecial = false; +} + +void Scene202::setRandomKernelMessage() { + int vocabId = _vm->getRandomNumber(92, 96); + _scene->_kernelMessages.reset(); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 70, 120, _game.getQuote(vocabId)); + _activeMsgFl = true; +} + +void Scene202::step() { + if (!_activeMsgFl && (_game._player._playerPos == Common::Point(77, 105)) && (_game._player._facing == FACING_NORTH) && (_vm->getRandomNumber(999) == 0)) { + _scene->_kernelMessages.reset(); + _activeMsgFl = false; + if (_vm->getRandomNumber(4) == 0) + setRandomKernelMessage(); + } + + if (_game._trigger == 70) + _activeMsgFl = false; + + if (_game._trigger == 71) { + _vm->_sound->command(3); + _vm->_sound->command(9); + + _meteoClock1 = _scene->_frameStartTime + 15 * 60; + + if (_globals[kMeteorologistWatch] != METEOROLOGIST_NORMAL) { + Common::Point msgPos; + int msgFlag; + if (!_ladderTopFl) { + msgPos = Common::Point(0, 0); + msgFlag = 2; + } else { + msgPos = Common::Point(248, 15); + msgFlag = 0; + } + int msgIndex = _scene->_kernelMessages.add(msgPos, 0x1110, msgFlag | 32, 0, 120, _game.getQuote(102)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + + if (_globals[kMeteorologistWatch] == METEOROLOGIST_GROUND) { + _action._activeAction._verbId = VERB_LOOK; + _action._activeAction._objectNameId = NOUN_BINOCULARS; + _action._activeAction._indirectObjectId = NOUN_STRANGE_DEVICE; + _game._triggerSetupMode = SEQUENCE_TRIGGER_PARSER; + _scene->_sequences.addTimer(2 * 60, 2); + _meteorologistSpecial = true; + } else if (_globals[kMeteorologistWatch] == METEOROLOGIST_TOWER) { + _scene->_sequences.addTimer(2 * 60, 90); + } + } + + _globals[kMeteorologistWatch] = METEOROLOGIST_NORMAL; + } + + switch (_game._trigger) { + case 90: + _vm->_sound->command(41); + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _globals._sequenceIndexes[9] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[9], true, 6, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 91); + break; + case 91: + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], true, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1); + _scene->_sequences.addTimer(60, 92); + break; + case 92: { + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[11], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 93); + _scene->_kernelMessages.reset(); + int msgIndex = _scene->_kernelMessages.add(Common::Point(0, -65), 0x1110, 32, 0, 60, _game.getQuote(98)); + _scene->_kernelMessages.setSeqIndex(msgIndex, _globals._sequenceIndexes[11]); + } + break; + case 93: { + _globals[kLadderBroken] = false; + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 6, 0, 0, 0); + _scene->_hotspots.activate(NOUN_LADDER, false); + int idx = _scene->_dynamicHotspots.add(NOUN_BROKEN_LADDER, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(246, 124), FACING_NORTH); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[11], _globals._sequenceIndexes[5]); + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[11]); + _game._player._stepEnabled = true; + _game._player._visible = true; + _ladderTopFl = false; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(99)); + } + break; + default: + break; + } + + if (!_scene->_activeAnimation && (_globals[kMeteorologistStatus] != METEOROLOGIST_GONE) && (_meteoClock2 <= _scene->_frameStartTime) && (_meteoClock1 <= _scene->_frameStartTime)) { + int randVal = _vm->getRandomNumber(1, 500); + int threshold = 1; + if (_ladderTopFl) + threshold += 25; + if (!_globals[kMeteorologistEverSeen]) + threshold += 25; + if (threshold >= randVal) { + _vm->_sound->command(17); + _scene->loadAnimation(formAnimName('M', -1), 71); + _toStationFl = true; + _toTeleportFl = false; + _globals[kMeteorologistEverSeen] = true; + _lastRoute = 0; + _stationCounter = 0; + _meteoClock2 = _scene->_frameStartTime + 2; + } + } + + if (!_scene->_activeAnimation) + return; + + if (_waitingMeteoFl) { + if (_scene->_activeAnimation->getCurrentFrame() >= 200) { + if ((_globals[kMeteorologistWatch] == METEOROLOGIST_TOWER) || _globals[kLadderBroken]) { + _scene->_nextSceneId = 213; + } else { + _vm->_dialogs->show(20201); + _scene->_reloadSceneFlag = true; + } + } + + if ((_scene->_activeAnimation->getCurrentFrame() == 160) && (_meteoFrame != _scene->_activeAnimation->getCurrentFrame())) { + Common::Point msgPos; + int msgFlag; + if (!_ladderTopFl) { + msgPos = Common::Point(0, 0); + msgFlag = 2; + } else { + msgPos = Common::Point(248, 15); + msgFlag = 0; + } + int msgIndex = _scene->_kernelMessages.add(msgPos, 0x1110, msgFlag | 32, 0, 120, _game.getQuote(101)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + } + } + + if (_meteoClock2 + 120 * 60 <= _scene->_frameStartTime) { + _toTeleportFl = true; + } + + if (_scene->_activeAnimation->getCurrentFrame() == _meteoFrame) { + return; + } + + _meteoFrame = _scene->_activeAnimation->getCurrentFrame(); + int randVal = _vm->getRandomNumber(1, 1000); + int frameStep = -1; + + switch (_scene->_activeAnimation->getCurrentFrame()) { + case 42: + case 77: + case 96: + _stationCounter = 0; + frameStep = subStep1(randVal); + break; + case 51: + case 74: + _toStationFl = false; + frameStep = subStep2(randVal); + break; + case 27: + case 119: + case 159: + frameStep = subStep3(randVal); + break; + case 176: + frameStep = subStep4(randVal); + break; + case 59: + _lastRoute = 3; + ++_stationCounter; + if (randVal <= 800) + frameStep = 55; + break; + case 89: + _lastRoute = 1; + if (randVal <= 700) + frameStep = 83; + break; + case 137: + _lastRoute = 2; + if (randVal <= 700) + frameStep = 126; + break; + } + + if (frameStep >= 0 && frameStep != _scene->_activeAnimation->getCurrentFrame() + 1) { + _scene->_activeAnimation->setCurrentFrame(frameStep); + _meteoFrame = frameStep; + } +} + +int Scene202::subStep1(int randVal) { + if ((randVal <= 100) || _toStationFl) + return 42; + + if ((randVal <= 200) || _toTeleportFl) + return 96; + + if ((randVal <= 300) && (_lastRoute != 1)) + return 77; + + return 76; +} + +int Scene202::subStep2(int randVal) { + if ((randVal <= 150) && (_stationCounter < 5)) + return 51; + + if ((randVal <= 300) || _toTeleportFl) + return 74; + + if (randVal <= 400) + return 64; + + return 44; +} + +int Scene202::subStep3(int randVal) { + if ((randVal <= 100) || _toStationFl) + return 27; + + if ((randVal <= 200) || _toTeleportFl) + return 159; + + if ((randVal <= 300) && (_lastRoute != 2)) + return 119; + + return 110; +} + +int Scene202::subStep4(int randVal) { + if ((randVal <= 100) || _toTeleportFl) + return 176; + + if (randVal <= 200) + return 19; + + return 166; +} + +void Scene202::preActions() { + Player &player = _vm->_game->_player; + + if (player._needToWalk) + _scene->_kernelMessages.reset(); + + if (_ladderTopFl && (_action.isAction(VERB_CLIMB_DOWN, NOUN_LADDER) || player._needToWalk)) { + if (_game._trigger == 0) { + _vm->_sound->command(29); + player._readyToWalk = false; + player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _globals._sequenceIndexes[8] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[8], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + } else if (_game._trigger == 1) { + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[8]); + _scene->_dynamicHotspots.remove(_ladderHotspotId); + player._visible = true; + player._readyToWalk = true; + player._stepEnabled = true; + _ladderTopFl = false; + } + } + + if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS) && (_action._activeAction._indirectObjectId > 0)) { + if (!player._readyToWalk || _ladderTopFl) + player._needToWalk = false; + else + player._needToWalk = true; + + if (!_ladderTopFl) + player.walk(Common::Point(171, 122), FACING_NORTH); + } +} + +void Scene202::actions() { + if (_action._lookFlag) { + _vm->_dialogs->show(20219); + return; + } + + if (_action.isAction(VERB_CLIMB_DOWN, NOUN_LADDER)) { + _action._inProgress = false; + return; + } else if (_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_SOUTH)) { + _scene->_nextSceneId = 203; + } else if (_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_NORTH)) { + if (_globals[kMeteorologistStatus] != METEOROLOGIST_GONE) { + if (_scene->_activeAnimation) + _globals[kMeteorologistStatus] = METEOROLOGIST_PRESENT; + else + _globals[kMeteorologistStatus] = METEOROLOGIST_ABSENT; + } + _scene->_nextSceneId = 201; + } else if (_action.isAction(VERB_TAKE, NOUN_BONE) && (_action._savedFields._mainObjectSource == 4)) { + switch (_game._trigger) { + case 0: + if (_game._objects.isInInventory(OBJ_BONES)) { + _vm->_dialogs->show(20221); + } else { + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[7] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[7], false, 3, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[7]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_SPRITE, 6, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + case 1: + if (_game._player._playerPos == Common::Point(132, 97)) { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals[kBone202Status] |= BONE_202_LEFT_GONE; + } else { + _scene->_sequences.remove(_globals._sequenceIndexes[6]); + _globals[kBone202Status] |= BONE_202_RIGHT_GONE; + } + break; + case 2: + if (_game._objects.isInInventory(OBJ_BONE)) { + _game._objects.removeFromInventory(OBJ_BONE, NOWHERE); + _game._objects.addToInventory(OBJ_BONES); + _vm->_dialogs->showItem(OBJ_BONES, 20218); + } else { + _game._objects.addToInventory(OBJ_BONE); + _vm->_dialogs->showItem(OBJ_BONE, 20218); + } + _scene->changeVariant(_globals[kBone202Status]); + _game._player._stepEnabled = true; + _game._player._visible = true; + break; + default: + break; + } + + _action._inProgress = false; + } else if (_action.isAction(VERB_CLIMB_UP, NOUN_LADDER) && !_globals[kLadderBroken]) { + switch (_game._trigger) { + case 0: + _vm->_sound->command(29); + _meteoClock1 = _scene->_frameStartTime; + _game._player._visible = false; + _game._player._stepEnabled = false; + + _ladderHotspotId = _scene->_dynamicHotspots.add(NOUN_LADDER, 78, -1, Common::Rect(241, 68, 241 + 12, 68 + 54)); + _scene->_dynamicHotspots.setPosition(_ladderHotspotId, Common::Point(246, 124), FACING_NORTH); + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + case 1: { + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], true, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[8], _globals._sequenceIndexes[9]); + _ladderTopFl = true; + _game._player._stepEnabled = true; + int msgIndex = _scene->_kernelMessages.add(Common::Point(248, 15), 0x1110, 32, 0, 60, _game.getQuote(97)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + } + break; + default: + _action._inProgress = false; + return; + } + } else if ((_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_FIELD_TO_NORTH) || (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_STRANGE_DEVICE))) && (_globals[kSexOfRex] == SEX_MALE)) { + if (!_ladderTopFl) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible= false; + _globals._sequenceIndexes[10] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 6, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 1, 6); + _scene->_sequences.setPosition(_globals._sequenceIndexes[10], Common::Point(172, 123)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 1); + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[10]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[10], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + case 1: + _globals._sequenceIndexes[10] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[10], Common::Point(172, 123)); + if (_scene->_activeAnimation) { + _waitingMeteoFl = true; + _globals[kMeteorologistWatch] = METEOROLOGIST_GROUND; + } else { + _scene->_sequences.addTimer(120, 2); + } + break; + case 2: + if (!_scene->_activeAnimation && !_meteorologistSpecial) { + _vm->_dialogs->show(20222); + } + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _globals._sequenceIndexes[10] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[9], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 1); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 1, 6); + _scene->_sequences.setPosition(_globals._sequenceIndexes[10], Common::Point(172, 123)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[10], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + case 3: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[10]); + _game._player._stepEnabled = true; + _game._player._visible = true; + break; + default: + _action._inProgress = false; + return; + } + } else { + switch (_game._trigger) { + case 0: + _toTeleportFl = true; + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], true, 6, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + case 1: + _globals._sequenceIndexes[10] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], true, -2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[10], Common::Point(247, 82)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 1); + if (_scene->_activeAnimation) { + if (_scene->_activeAnimation->getCurrentFrame() > 200) { + _scene->_sequences.addTimer(120, 2); + } else { + _waitingMeteoFl = true; + _globals[kMeteorologistWatch] = METEOROLOGIST_GONE; + if ((_scene->_activeAnimation->getCurrentFrame() >= 44) && (_scene->_activeAnimation->getCurrentFrame() <= 75)) { + _scene->_kernelMessages.reset(); + int msgIndex = _scene->_kernelMessages.add(Common::Point(248, 15), 0x1110, 32, 0, 60, _game.getQuote(100)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, false); + } else { + _action._inProgress = false; + return; + } + } + } else { + _scene->_sequences.addTimer(120, 2); + } + break; + case 2: + if (!_scene->_activeAnimation) + _vm->_dialogs->show(20222); + _meteorologistSpecial = false; + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _globals._sequenceIndexes[9] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[9], false, 6, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + case 3: + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], true, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1); + _game._player._stepEnabled = true; + break; + default: + _action._inProgress = false; + return; + } + } + } else if (_action.isAction(VERB_WALK_INSIDE, NOUN_HUT)) { + setRandomKernelMessage(); + } else if (_action.isAction(VERB_LOOK, NOUN_ROCKS)) { + _vm->_dialogs->show(20202); + } else if (_action.isAction(VERB_LOOK, NOUN_FIRE_PIT)) { + _vm->_dialogs->show(20203); + } else if (_action.isAction(VERB_LOOK, NOUN_GRASS)) { + _vm->_dialogs->show(20204); + } else if (_action.isAction(VERB_LOOK, NOUN_FIELD_TO_NORTH)) { + if ((_globals[kMeteorologistStatus] == METEOROLOGIST_ABSENT) || (_globals[kMeteorologistStatus] == METEOROLOGIST_GONE)) + _vm->_dialogs->show(20205); + else if (_globals[kMeteorologistStatus] == METEOROLOGIST_PRESENT) + _vm->_dialogs->show(20220); + } else if (_action.isAction(VERB_LOOK, NOUN_WATCH_TOWER)) { + _vm->_dialogs->show(20206); + } else if (_action.isAction(VERB_LOOK, NOUN_TALL_GRASS)) { + _vm->_dialogs->show(20207); + } else if (_action.isAction(VERB_LOOK, NOUN_TREES)) { + _vm->_dialogs->show(20208); + } else if (_action.isAction(VERB_LOOK, NOUN_TREE)) { + _vm->_dialogs->show(20209); + } else if (_action.isAction(VERB_LOOK, NOUN_SKY)) { + _vm->_dialogs->show(20210); + } else if (_action.isAction(VERB_LOOK, NOUN_HUT)) { + if ((_game._player._playerPos == Common::Point(77, 105)) && (_game._player._facing == FACING_NORTH)) + _vm->_dialogs->show(20212); + else + _vm->_dialogs->show(20211); + } else if (_action.isAction(VERB_LOOK, NOUN_STRANGE_DEVICE)) { + _vm->_dialogs->show(20213); + } else if (_action.isAction(VERB_LOOK, NOUN_OCEAN_IN_DISTANCE)) { + _vm->_dialogs->show(20214); + } else if (_action.isAction(VERB_LOOK, NOUN_SKULL)) { + _vm->_dialogs->show(20215); + } else if (_action.isAction(VERB_TAKE, NOUN_SKULL)) { + _vm->_dialogs->show(20216); + } else if (_action.isAction(VERB_LOOK, NOUN_BONES) && _action._commandSource == 4) { + _vm->_dialogs->show(20217); + } else { + return; + } + + _action._inProgress = false; +} + +/*****************************************************************************/ + +Scene203::Scene203(MADSEngine *vm) : Scene2xx(vm) { + _rhotundaEat2Fl = false; + _rhotundaEatFl = false; +} + +void Scene203::synchronize(Common::Serializer &s) { + Scene2xx::synchronize(s); + + s.syncAsByte(_rhotundaEat2Fl); + s.syncAsByte(_rhotundaEatFl); +} + +void Scene203::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(477); +} + +void Scene203::enter() { + if (_scene->_priorSceneId == 202) { + _game._player._playerPos = Common::Point(187, 99); + _game._player._facing = FACING_SOUTH; + } else if (_scene->_priorSceneId == 209) { + _game._player._playerPos = Common::Point(308, 117); + _game._player._facing = FACING_WEST; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(155, 152); + _game._player._facing = FACING_NORTH; + } + + _rhotundaEatFl = false; + _rhotundaEat2Fl = false; + + if ((_globals[kRhotundaStatus] == 0) && (!_scene->_roomChanged)) { + _rhotundaEatFl = true; + _game._player.walk(Common::Point(158, 135), FACING_SOUTH); + int idx = _scene->_dynamicHotspots.add(131, 396, 0, Common::Rect(0, 0, 320, 156)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(155, 152), FACING_SOUTH); + _scene->_dynamicHotspots.setCursor(idx, CURSOR_GO_DOWN); + } + + if (!_rhotundaEatFl) { + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('b', -1)); + if (_vm->getRandomNumber(1, 3) == 2) { + _globals._spriteIndexes[15] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 9, 1, 0, 0); + int idx = _scene->_dynamicHotspots.add(477, 209, _globals._spriteIndexes[15], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-2, 0), FACING_NONE); + _vm->_sound->command(14); + } + } + + _game.loadQuoteSet(0x67, 0x68, 0x69, 0x6A, 0x5A, 0); + + if (_rhotundaEatFl) { + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(_vm->getRandomNumber(103, 106))); + } + + sceneEntrySound(); +} + +void Scene203::step() { + if (!_rhotundaEatFl) + return; + + if ((_game._trigger == 0) && _rhotundaEat2Fl) + return; + + if ((_game._player._playerPos != Common::Point(158, 136)) || (_game._player._facing != FACING_SOUTH)) + return; + + _rhotundaEat2Fl = true; + + if (_game._trigger == 0) { + _game._player._visible = false; + _game._player._stepEnabled = false; + _vm->_palette->lock(); + _scene->_kernelMessages.reset(); + _scene->resetScene(); + _vm->_events->setCursor2(CURSOR_WAIT); + _scene->loadAnimation(Resources::formatName(203, 'a', -1, EXT_AA, ""), 81); + } else if (_game._trigger == 81) { + _scene->_nextSceneId = 208; + _scene->_reloadSceneFlag = true; + } +} + +void Scene203::preActions() { + if (_rhotundaEatFl && !_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_SOUTH)) { + _game._player.walk(Common::Point(158, 136), FACING_SOUTH); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_WALKTO, NOUN_OPEN_AREA_TO_EAST)) + _game._player._walkOffScreenSceneId = 209; +} + +void Scene203::actions() { + if (_action._savedFields._lookFlag) { + _vm->_dialogs->show(20307); + } else if (_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_SOUTH)) { + _scene->_nextSceneId = 208; + } else if (_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_NORTH)) { + _scene->_nextSceneId = 202; + } else if (_action.isAction(VERB_LOOK, NOUN_SKY)) { + _vm->_dialogs->show(20301); + } else if (_action.isAction(VERB_LOOK, NOUN_CLIFF_FACE)) { + _vm->_dialogs->show(20302); + } else if (_action.isAction(VERB_LOOK, NOUN_PALM_TREE)) { + _vm->_dialogs->show(20303); + } else if (_action.isAction(VERB_LOOK, NOUN_FIELD_TO_NORTH)) { + _vm->_dialogs->show(20304); + } else if (_action.isAction(VERB_LOOK, NOUN_GRASSY_FIELD)) { + _vm->_dialogs->show(20305); + } else if (_action.isAction(VERB_LOOK, NOUN_BOULDERS)) { + _vm->_dialogs->show(20305); + } else + return; + + _action._inProgress = false; +} + +/*****************************************************************************/ + +void Scene205::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_CHICKEN); + _scene->addActiveVocab(NOUN_PIRANHA); +} + +Scene205::Scene205(MADSEngine *vm) : Scene2xx(vm) { + _lastFishTime = 0; + _chickenTime = 0; + _beingKicked = false; + _kernelMessage = -1; +} + +void Scene205::synchronize(Common::Serializer &s) { + Scene2xx::synchronize(s); + + s.syncAsUint32LE(_lastFishTime); + s.syncAsUint32LE(_chickenTime); + s.syncAsByte(_beingKicked); + s.syncAsSint16LE(_kernelMessage); +} + +void Scene205::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 2)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('f', -1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('c', -1)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('p', -1)); + + if (_globals[kSexOfRex] == SEX_MALE) + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('a', 1)); + + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 10, 0, 0, 3); + int idx = _scene->_dynamicHotspots.add(73, 13, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(162, 120), FACING_NORTHEAST); + + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 15, 0, 0, 0); + idx = _scene->_dynamicHotspots.add(73, 13, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(162, 120), FACING_NORTHEAST); + + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 0, 0, 0); + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 6, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 11); + + if (!_game._visitedScenes._sceneRevisited) { + _lastFishTime = _scene->_frameStartTime; + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 7, 1, 0, 0); + idx = _scene->_dynamicHotspots.add(269, 13, _globals._sequenceIndexes[6], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(49, 86), FACING_NORTH); + } + + if (_game._objects[12]._roomNumber == 205) { + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 7, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 11); + } else { + _scene->_hotspots.activate(450, false); + } + + _beingKicked = false; + _game.loadQuoteSet(0x6B, 0x70, 0x71, 0x72, 0x5A, 0x74, 0x75, 0x76, 0x77, 0x78, 0x73, 0x79, 0x7A, 0x7B, 0x7C, + 0x7D, 0x7E, 0x7F, 0x80, 0xAC, 0xAD, 0xAE, 0x6C, 0x6D, 0x6E, 0x6F, 0x2, 0); + _dialog1.setup(0x2A, 0x5A, 0x78, 0x74, 0x75, 0x76, 0x77, 0); + + if (!_game._visitedScenes._sceneRevisited) + _dialog1.set(0x5A, 0x74, 0x75, 0x77, 0); + + _vm->_palette->setEntry(250, 63, 50, 20); + _vm->_palette->setEntry(251, 50, 40, 15); + _vm->_palette->setEntry(252, 63, 63, 40); + _vm->_palette->setEntry(253, 50, 50, 30); + + _chickenTime = _vm->_game->_scene._frameStartTime; + + if (_globals[kSexOfRex] == SEX_FEMALE) + _scene->_kernelMessages.initRandomMessages(3, + Common::Rect(195, 99, 264, 134), 13, 2, 0xFDFC, 60, + 108, 108, 109, 109, 110, 110, 111, 108, 0); + + if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(99, 152); + + if (_globals[kSexOfRex] != SEX_MALE) { + _scene->loadAnimation(formAnimName('a', -1)); + _scene->_activeAnimation->_resetFlag = false; + } else { + _beingKicked = true; + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 1, 0, 0); + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_SPRITE, 6, 73); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_SPRITE, 11, 74); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + } + sceneEntrySound(); +} + +void Scene205::step() { + if (_globals[kSexOfRex] == SEX_FEMALE) { + _scene->_kernelMessages.randomServer(); + + if (_vm->_game->_scene._frameStartTime >= _chickenTime) { + int chanceMinor = _scene->_kernelMessages.checkRandom() + 1; + if (_scene->_kernelMessages.generateRandom(100, chanceMinor)) + _vm->_sound->command(28); + + _chickenTime = _vm->_game->_scene._frameStartTime + 2; + } + } + + if (_vm->_game->_scene._frameStartTime - _lastFishTime > 1300) { + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle( + _globals._spriteIndexes[6], false, 5, 1, 0, 0); + int idx = _scene->_dynamicHotspots.add(269, 13, _globals._sequenceIndexes[6], + Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(49, 86), FACING_NORTH); + _lastFishTime = _vm->_game->_scene._frameStartTime; + } + + if (_game._trigger == 73) + _scene->_kernelMessages.add(Common::Point(160, 68), 0xFBFA, 32, 0, 60, _game.getQuote(112)); + + if (_game._trigger == 74) { + _vm->_sound->command(26); + _scene->_kernelMessages.add(Common::Point(106, 90), 0x1110, 32, 0, 60, _game.getQuote(113)); + } + + if (_game._trigger == 71) { + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 6, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 2); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], -2, -2); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(160, 68), 0xFBFA, 32, 72, 180, _game.getQuote(114)); + } + + if (_game._trigger == 72) + _scene->_nextSceneId = 211; +} + +void Scene205::handleWomanSpeech(int quote) { + _kernelMessage = _scene->_kernelMessages.add(Common::Point(186, 27), 0xFBFA, 0, 0, 9999999, _game.getQuote(quote)); +} + +void Scene205::actions() { + if (_game._screenObjects._inputMode == 1) { + if (_kernelMessage >= 0) + _scene->_kernelMessages.remove(_kernelMessage); + _kernelMessage = -1; + + if (_game._trigger == 0) { + _game._player._stepEnabled = false; + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 18, 1, 120, _game.getQuote(_action._activeAction._verbId)); + } else { + if ((_game._trigger > 1) || (_action._activeAction._verbId != 0x76)) + _game._player._stepEnabled = true; + + switch (_action._activeAction._verbId) { + case 0x5A: + handleWomanSpeech(0x7A); + _dialog1.write(0x78, true); + _dialog1.write(0x5A, false); + break; + + case 0x74: + handleWomanSpeech(0x7C); + _dialog1.write(0x74, false); + _dialog1.write(0x76, true); + break; + + case 0x75: + case 0x78: + handleWomanSpeech(0x7B); + _dialog1.write(_action._activeAction._verbId, false); + _vm->_dialogs->show(20501); + break; + + case 0x76: + if (_game._trigger == 1) { + handleWomanSpeech(0x7D); + _scene->_sequences.addTimer(120, 2); + } else if (_game._trigger == 2) { + handleWomanSpeech(0x7E); + _dialog1.write(0x76, false); + _globals[kChickenPermitted] = true; + } + break; + + case 0x77: + _scene->_kernelMessages.add(Common::Point(186, 27), 0xFBFA, 0, 0, 120, _game.getQuote(0x7F)); + _scene->_userInterface.setup(kInputBuildingSentences); + break; + + default: + break; + } + + if (_action._activeAction._verbId != 0x77) + _dialog1.start(); + } + } else if (_action._lookFlag) + _vm->_dialogs->show(20502); + else if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_OPPOSITE_BANK)) + _vm->_dialogs->show(20518); + else if (_action.isAction(VERB_TALKTO, NOUN_NATIVE_WOMAN)) { + if (_game._trigger == 0) { + _game._player._stepEnabled = false; + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 18, 1, 120, _game.getQuote(0x73)); + } else if (_game._trigger == 1) { + _game._player._stepEnabled = true; + handleWomanSpeech (0x79); + _dialog1.write(0x5A, true); + _dialog1.write(0x75, true); + _dialog1.start(); + } + } else if (_action.isAction(VERB_GIVE, NOUN_NATIVE_WOMAN) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) { + if (_game._trigger == 0) { + _game._player._stepEnabled = false; + int rndVal = _vm->getRandomNumber(0xAC, 0xAE); + _scene->_kernelMessages.add(Common::Point(186, 27), 0xFBFA, 32, 1, 120, _game.getQuote(rndVal)); + } else if (_game._trigger == 1) + _game._player._stepEnabled = true; + } else if (_action.isAction(VERB_WALKTO, NOUN_OPPOSITE_BANK)) { + if (_game._trigger == 0) { + _game._player._visible = false; + _game._player._stepEnabled = false; + _vm->_palette->lock(); + _scene->_kernelMessages.reset(); + _game._player.removePlayerSprites(); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('a', 0)); + _vm->_palette->refreshSceneColors(); + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], -1); + _vm->_sound->command(27); + } else if (_game._trigger == 1) { + if (_scene->_activeAnimation != nullptr) + _scene->_activeAnimation->resetSpriteSetsCount(); + + _vm->_dialogs->show(20516); + _scene->_reloadSceneFlag = true; + } + } else { + if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_SOUTH)) + _scene->_nextSceneId = 210; + + if (_action.isAction(VERB_WALKTO, NOUN_FIRE_PIT) || _action.isAction(VERB_WALKTO, NOUN_CHICKEN_ON_SPIT)) { + if (_game._objects.isInRoom(OBJ_CHICKEN)) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x6B)); + } + } else if (_action.isAction(VERB_TAKE, NOUN_CHICKEN_ON_SPIT) && _globals[kChickenPermitted] && _game._objects.isInRoom(OBJ_CHICKEN)) { + _game._objects.addToInventory(OBJ_CHICKEN); + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _scene->_hotspots.activate(NOUN_CHICKEN_ON_SPIT, false); + _vm->_dialogs->showItem(OBJ_CHICKEN, 812); + } else if (_action.isAction(VERB_TAKE, NOUN_CHICKEN_ON_SPIT) && (!_globals[kChickenPermitted])) + _scene->_kernelMessages.add(Common::Point(186, 27), 0xFBFA, 32, 0, 120, _game.getQuote(0x80)); + else if (_action.isAction(VERB_LOOK, NOUN_NATIVE_WOMAN)) + _vm->_dialogs->show(20503); + else if (_action.isAction(VERB_LOOK, NOUN_HUT)) + _vm->_dialogs->show(20504); + else if (_action.isAction(VERB_LOOK, NOUN_CHICKEN) && (_action._mainObjectSource == 4)) + _vm->_dialogs->show(20505); + else if (_action.isAction(VERB_TAKE, NOUN_CHICKEN) && (_action._mainObjectSource == 4)) + _vm->_dialogs->show(20506); + else if (_action.isAction(VERB_LOOK, NOUN_CHICKEN_ON_SPIT)) + _vm->_dialogs->show(20507); + else if (_action.isAction(VERB_LOOK, NOUN_FIRE_PIT)) + _vm->_dialogs->show(20508); + else if (_action.isAction(VERB_TAKE, NOUN_FIRE_PIT)) + _vm->_dialogs->show(20509); + else if (_action.isAction(VERB_LOOK, NOUN_STREAM)) + _vm->_dialogs->show(20510); + else if (_action.isAction(VERB_LOOK, NOUN_OPPOSITE_BANK)) + _vm->_dialogs->show(20511); + else if (_game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId)) + && ( _action.isAction(VERB_GIVE, NOUN_STREAM) || _action.isAction(VERB_THROW, NOUN_STREAM) + || _action.isAction(VERB_GIVE, NOUN_PIRANHA) || _action.isAction(VERB_THROW, NOUN_PIRANHA))) + _vm->_dialogs->show(20512); + else if (_action.isAction(VERB_LOOK, NOUN_PIRANHA)) + _vm->_dialogs->show(20513); + else if (_action.isAction(VERB_LOOK, NOUN_TWINKIFRUIT_BUSH)) + _vm->_dialogs->show(20514); + else if (_action.isAction(VERB_TAKE, NOUN_TWINKIFRUIT_BUSH)) + _vm->_dialogs->show(20515); + else if (_action.isAction(VERB_TAKE, NOUN_NATIVE_WOMAN)) + _vm->_dialogs->show(20517); + else + return; + } + + _action._inProgress = false; +} + +/*****************************************************************************/ + +Scene207::Scene207(MADSEngine *vm) : Scene2xx(vm) { + _vultureFl = false; + _spiderFl = false; + _eyeFl = false; + _spiderHotspotId = -1; + _vultureHotspotId = -1; + _spiderTime = 0; + _vultureTime = 0; +} + +void Scene207::synchronize(Common::Serializer &s) { + Scene2xx::synchronize(s); + + s.syncAsByte(_vultureFl); + s.syncAsByte(_spiderFl); + s.syncAsByte(_eyeFl); + + s.syncAsSint32LE(_spiderHotspotId); + s.syncAsSint32LE(_vultureHotspotId); + s.syncAsSint32LE(_spiderTime); + s.syncAsSint32LE(_vultureTime); +} + +void Scene207::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_VULTURE); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_SPIDER); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene207::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('h', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('h', 1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('c', -1)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('e', 0)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('e', 1)); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('g', 1)); + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('g', 0)); + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 7, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 7); + + int var2; + if (!_game._visitedScenes._sceneRevisited) { + var2 = 1; + } else { + var2 = _vm->getRandomNumber(4) + 1; + } + + if (var2 > 2) + _vultureFl = false; + else + _vultureFl = true; + + _spiderFl = (var2 & 1); + + if (_vultureFl) { + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 30, 0, 0, 400); + _vultureTime = _game._player._priorTimer; + _vultureHotspotId = _scene->_dynamicHotspots.add(389, 13, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_vultureHotspotId, Common::Point(254, 94), FACING_WEST); + } + + if (_spiderFl) { + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], -1, -1); + _spiderTime = _game._player._priorTimer; + _spiderHotspotId = _scene->_dynamicHotspots.add(333, 13, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_spiderHotspotId, Common::Point(59, 132), FACING_SOUTH); + } + + _eyeFl = false; + if (_scene->_priorSceneId == 211) { + _game._player._playerPos = Common::Point(13, 105); + _game._player._facing = FACING_EAST; + } else if (_scene->_priorSceneId == 214) { + _game._player._playerPos = Common::Point(164, 117); + _game._player._facing = FACING_SOUTH; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(305, 131); + } + + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 22); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 6); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 70); +} + +void Scene207::moveVulture() { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _vm->_sound->command(43); + _vultureFl = false; + _vultureTime = _game._player._priorTimer; + _scene->_dynamicHotspots.remove(_vultureHotspotId); +} + +void Scene207::moveSpider() { + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 5, 1, 0, 0); + _spiderFl = false; + _spiderTime = _game._player._priorTimer; + _scene->_dynamicHotspots.remove(_spiderHotspotId); +} + +void Scene207::step() { + if (!_vultureFl) + moveVulture(); + + if (_spiderFl) + moveSpider(); + + if (_game._trigger == 70) { + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 10, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 23, 34); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 6); + } + + if (_game._trigger == 71) + _eyeFl = false; + + if (_eyeFl) + return; + + if ((_game._player._playerPos.x >= 124) && (_game._player._playerPos.x <= 201)) { + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 10, 1, 0, 0); + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 6); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + _eyeFl = true; + } +} + +void Scene207::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_WEST)) + _game._player._walkOffScreenSceneId = 211; + + if (_action.isAction(VERB_WALK_TOWARDS, NOUN_OPEN_FIELD_TO_EAST)) + _game._player._walkOffScreenSceneId = 208; + + if (_action.isAction(VERB_WALKTO) || _action.isAction(VERB_LOOK)) { + if (_action.isObject(NOUN_VULTURE)) { + _vultureTime = -9999; + } else if (_action.isObject(NOUN_SPIDER)) { + _spiderTime = -9999; + } + } +} + +void Scene207::actions() { + if (_action._savedFields._lookFlag) + _vm->_dialogs->show(20711); + else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY)) + _scene->_nextSceneId = 214; + else { + if ((_game._player._playerPos.x > 150) && (_game._player._playerPos.x < 189) && + (_game._player._playerPos.y > 111) && (_game._player._playerPos.y < 130)) { + if ((_game._player._playerPos.x <= 162) || (_game._player._playerPos.x >= 181) || + (_game._player._playerPos.y <= 115) || (_game._player._playerPos.y >= 126)) { + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 10, 2, 0, 0); + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 2, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 6); + } + } else if (_eyeFl) { + _scene->_sequences.remove(_globals._sequenceIndexes[7]); + _scene->_sequences.remove(_globals._sequenceIndexes[8]); + _eyeFl = false; + } + + if (_action.isAction(VERB_LOOK, NOUN_DENSE_FOREST)) + _vm->_dialogs->show(20701); + else if (_action.isAction(VERB_LOOK, NOUN_HEDGE)) + _vm->_dialogs->show(20702); + else if (_action.isAction(VERB_LOOK, NOUN_SKULL_AND_CROSSBONES)) + _vm->_dialogs->show(20703); + else if (_action.isAction(VERB_LOOK, NOUN_CAULDRON)) + _vm->_dialogs->show(20704); + else if (_action.isAction(VERB_LOOK, NOUN_WITCHDOCTOR_HUT)) + _vm->_dialogs->show(20705); + else if (_action.isAction(VERB_LOOK, NOUN_PATH_TO_WEST)) + _vm->_dialogs->show(20706); + else if (_action.isAction(VERB_LOOK, NOUN_MOUNTAINS)) + _vm->_dialogs->show(20707); + else if (_action.isAction(VERB_LOOK, NOUN_ALOE_PLANT)) + _vm->_dialogs->show(20708); + else if (_action.isAction(VERB_LOOK, NOUN_LAWN)) + _vm->_dialogs->show(20709); + else if (_action.isAction(VERB_LOOK, NOUN_VULTURE)) + _vm->_dialogs->show(20710); + else if (_action.isAction(VERB_TAKE, NOUN_SKULL_AND_CROSSBONES)) + _vm->_dialogs->show(20712); + else if (_action.isAction(VERB_TAKE, NOUN_ALOE_PLANT)) + _vm->_dialogs->show(20713); + else if (_action.isAction(VERB_LOOK, NOUN_SPIDER)) + _vm->_dialogs->show(20714); + else if (_action.isAction(VERB_TAKE, NOUN_SPIDER)) + _vm->_dialogs->show(20715); + else + return; + } + + _action._inProgress = false; +} + +/*****************************************************************************/ + +Scene208::Scene208(MADSEngine *vm) : Scene2xx(vm) { + _rhotundaTurnFl = false; + _boundingFl = false; + _rhotundaTime = 0; +} + +void Scene208::synchronize(Common::Serializer &s) { + Scene2xx::synchronize(s); + + s.syncAsByte(_rhotundaTurnFl); + s.syncAsByte(_boundingFl); + s.syncAsSint32LE(_rhotundaTime); +} + +void Scene208::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_HUGE_LEGS); + _scene->addActiveVocab(NOUN_LEAF_COVERED_PIT); + _scene->addActiveVocab(NOUN_PILE_OF_LEAVES); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene208::updateTrap() { + if (_globals[kRhotundaStatus] == 1) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 8, 0, 0, 24); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); + int idx = _scene->_dynamicHotspots.add(NOUN_HUGE_LEGS, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(100, 146), FACING_NORTH); + _scene->_hotspots.activate(414, false); + return; + } + + switch (_globals[kLeavesStatus]) { + case 0: { + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 15); + int idx = _scene->_dynamicHotspots.add(NOUN_PILE_OF_LEAVES, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(60, 152), FACING_NORTH); + } + break; + case 2: { + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 15); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_hotspots.activate(NOUN_DEEP_PIT, false); + int idx = _scene->_dynamicHotspots.add(NOUN_LEAF_COVERED_PIT, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(100, 146), FACING_NORTH); + _scene->_dynamicHotspots[idx]._articleNumber = PREP_ON; + } + break; + } +} + +void Scene208::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 2)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RXMBD_8"); + + updateTrap(); + + _rhotundaTurnFl = false; + _boundingFl = false; + _scene->_kernelMessages._talkFont = _vm->_font->getFont(FONT_INTERFACE); + _scene->_textSpacing = 0; + + if (_scene->_priorSceneId == 207) { + _game._player._playerPos = Common::Point(8, 122); + _game._player._facing = FACING_EAST; + } else if (_scene->_priorSceneId == 203) { + _game._player._playerPos = Common::Point(142, 108); + _game._player._facing = FACING_SOUTH; + } else if (_scene->_priorSceneId == 209) { + _game._player._playerPos = Common::Point(307, 123); + _game._player._facing = FACING_WEST; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(162, 149); + _game._player._facing = FACING_NORTH; + } + + _game.loadQuoteSet(0x81, 0x46, 0); + + if ((_scene->_priorSceneId == 207) && (_globals[kMonkeyStatus] == MONKEY_HAS_BINOCULARS)) { + int msgIndex = _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(129)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + } + + _vm->_palette->setEntry(16, 0, 0, 63); + _vm->_palette->setEntry(17, 0, 0, 45); + sceneEntrySound(); +} + +void Scene208::step() { + if (_boundingFl && (_rhotundaTime <= _scene->_activeAnimation->getCurrentFrame())) { + _rhotundaTime = _scene->_activeAnimation->getCurrentFrame(); + + if (_rhotundaTime == 125) + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + } + + if (!_rhotundaTurnFl) + return; + + if ((_game._player._playerPos != Common::Point(20, 148)) || (_game._player._facing != FACING_EAST)) + return; + + if ((_game._trigger == 0) && _boundingFl) + return; + + _boundingFl = true; + + switch (_game._trigger) { + case 0: + _scene->loadAnimation(formAnimName('A', -1), 81); + _rhotundaTime = 0; + break; + case 81: + _scene->_sequences.remove(_globals._spriteIndexes[15]); + _globals[kRhotundaStatus] = 1; + updateTrap(); + _scene->_sequences.addTimer(90, 82); + break; + case 82: + _game._player._stepEnabled = true; + break; + } +} + +void Scene208::preActions() { + Player &player = _vm->_game->_player; + + if (_action.isAction(VERB_LOOK) && player._readyToWalk) + player._needToWalk = true; + + if (_action.isAction(VERB_WALK_TOWARDS, NOUN_GRASSLAND_TO_EAST)) + player._walkOffScreenSceneId = 209; + + if (_action.isAction(VERB_WALK_TOWARDS, NOUN_OPEN_AREA_TO_WEST)) + player._walkOffScreenSceneId = 207; +} + +void Scene208::subAction(int mode) { + + switch (_game._trigger) { + case 0: { + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 6, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + + int abortVal; + if ((mode == 1) || (mode == 2)) + abortVal = 1; + else + abortVal = 2; + + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, abortVal); + } + break; + case 1: { + int oldVal = _globals._sequenceIndexes[5]; + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 12, 3, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 3, 4); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], oldVal); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + _vm->_sound->command(20); + } + break; + + case 2: { + switch (mode) { + case 1: + _game._objects.addToInventory(OBJ_BIG_LEAVES); + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals[kLeavesStatus] = 1; + break; + + case 2: + _game._objects.setRoom(OBJ_BIG_LEAVES, 1); + _globals[kLeavesStatus] = 2; + updateTrap(); + break; + + case 3: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _game._objects.removeFromInventory(OBJ_TWINKIFRUIT, 1); + _vm->_sound->command(34); + break; + + case 4: + _game._objects.removeFromInventory(OBJ_BURGER, 1); + _vm->_sound->command(33); + break; + + case 5: + _game._objects.removeFromInventory(OBJ_DEAD_FISH, 1); + _vm->_sound->command(33); + break; + + default: + break; + } + + int oldVal = _globals._sequenceIndexes[5]; + _globals._sequenceIndexes[5] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[5], false, 6, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], oldVal); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + } + break; + + case 3: + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } +} + +void Scene208::actions() { + if (_action.isAction(VERB_WALK_TOWARDS, NOUN_LOWLANDS_TO_NORTH)) { + if (_globals[kRhotundaStatus]) + _scene->_nextSceneId = 203; + else if (_game._trigger == 0) { + _game._player._stepEnabled = false; + int msgIndex = _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 1, 120, _game.getQuote(70)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + } else if (_game._trigger == 1) + _scene->_nextSceneId = 203; + } else if (_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_SOUTH)) + _scene->_nextSceneId = 212; + else if (_action.isAction(VERB_TAKE, NOUN_PILE_OF_LEAVES) && (!_globals[kLeavesStatus] || _game._trigger)) { + subAction(1); + if (_game._player._stepEnabled) + _vm->_dialogs->showItem(OBJ_BIG_LEAVES, 0x326, 0); + } else if (_action.isAction(VERB_PUT, NOUN_BIG_LEAVES, NOUN_DEEP_PIT) && (_globals[kLeavesStatus] == 1 || _game._trigger)) + subAction(2); + else if (_action.isAction(VERB_PUT, NOUN_TWINKIFRUIT, NOUN_LEAF_COVERED_PIT)) { + subAction(3); + if (_game._player._stepEnabled) { + _game._player._stepEnabled = false; + _rhotundaTurnFl = true; + _game._player.walk(Common::Point(20, 148), FACING_EAST); + } + } else if (_action.isAction(VERB_PUT, NOUN_BURGER, NOUN_LEAF_COVERED_PIT)) { + subAction(4); + if (_game._player._stepEnabled) + _vm->_dialogs->show(20812); + } else if (_action.isAction(VERB_PUT, NOUN_DEAD_FISH, NOUN_LEAF_COVERED_PIT)) { + subAction(5); + if (_game._player._stepEnabled) + _vm->_dialogs->show(20812); + } else if (_action.isAction(VERB_LOOK, NOUN_CUMULOUS_CLOUD)) + _vm->_dialogs->show(20801); + else if (_action.isAction(VERB_LOOK, NOUN_OPEN_AREA_TO_WEST)) + _vm->_dialogs->show(20802); + else if (_action.isAction(VERB_LOOK, NOUN_THORNY_BUSH)) + _vm->_dialogs->show(20803); + else if (_action.isAction(VERB_LOOK, NOUN_ROCKS)) + _vm->_dialogs->show(20804); + else if (_action.isAction(VERB_LOOK, NOUN_SMALL_CACTUS)) + _vm->_dialogs->show(20805); + else if (_action.isAction(VERB_TAKE, NOUN_SMALL_CACTUS)) + _vm->_dialogs->show(20806); + else if (_action.isAction(VERB_LOOK, NOUN_GRASSLAND_TO_EAST)) + _vm->_dialogs->show(20807); + else if (_action.isAction(VERB_LOOK, NOUN_DEEP_PIT)) + _vm->_dialogs->show(20808); + else if (_action.isAction(VERB_LOOK, NOUN_PILE_OF_LEAVES)) + _vm->_dialogs->show(20809); + else if (_action.isAction(VERB_LOOK, NOUN_LEAF_COVERED_PIT)) { + if (_game._difficulty == DIFFICULTY_EASY) + _vm->_dialogs->show(20810); + else + _vm->_dialogs->show(20811); + } else if (_action.isAction(VERB_LOOK, NOUN_TREE) || _action.isAction(VERB_LOOK, NOUN_TREES)) + _vm->_dialogs->show(20813); + else if (_action.isAction(VERB_TAKE, NOUN_LEAF_COVERED_PIT)) + _vm->_dialogs->show(20814); + else if (_action.isAction(VERB_LOOK, NOUN_HUGE_LEGS)) + _vm->_dialogs->show(20815); + else if (_action.isAction(VERB_TAKE, NOUN_HUGE_LEGS) || _action.isAction(VERB_PULL, NOUN_HUGE_LEGS)) + _vm->_dialogs->show(20816); + else if (_action._savedFields._lookFlag && (_globals[kRhotundaStatus] == 1)) + _vm->_dialogs->show(20819); + else if (_action._savedFields._lookFlag && (_globals[kLeavesStatus] == 2)) + _vm->_dialogs->show(20818); + else if (_action._savedFields._lookFlag) + _vm->_dialogs->show(20817); + else + return; + + _action._inProgress = false; +} + +/*****************************************************************************/ + +Scene209::Scene209(MADSEngine *vm) : Scene2xx(vm) { + _dodgeFl = false; + _forceDodgeFl = false; + _pitchFl = false; + _fallFl = false; + _forceFallFl = false; + _playingAnimFl = false; + _shouldFallFl = false; + _shouldDodgeFl = false; + _monkeyPosition = 0; + _counter = 0; + _pauseMode = 0; + _binocularsDroppedFl = false; + _startShootingInTimerFl = false; + _dialogAbortVal = 0; + _playingDialogFl = false; + _shootMissedLastFl = false; + _removeMonkeyFl = false; + _shootReadyFl = false; + _pauseCounterThreshold = 0; + _pauseCounter = 0; +} + +void Scene209::synchronize(Common::Serializer &s) { + Scene2xx::synchronize(s); + + s.syncAsByte(_dodgeFl); + s.syncAsByte(_forceDodgeFl); + s.syncAsByte(_shouldDodgeFl); + s.syncAsByte(_pitchFl); + s.syncAsByte(_fallFl); + s.syncAsByte(_forceFallFl); + s.syncAsByte(_shouldFallFl); + s.syncAsByte(_playingAnimFl); + s.syncAsByte(_playingDialogFl); + + s.syncAsSint32LE(_pauseMode); + s.syncAsSint32LE(_pauseCounterThreshold); + s.syncAsSint32LE(_pauseCounter); + + s.syncAsByte(_removeMonkeyFl); + + s.syncAsSint32LE(_monkeyPosition); + + s.syncAsByte(_shootReadyFl); + s.syncAsByte(_startShootingInTimerFl); + s.syncAsByte(_shootMissedLastFl); + s.syncAsByte(_binocularsDroppedFl); + + s.syncAsSint32LE(_dialogAbortVal); + s.syncAsSint32LE(_counter); +} + +void Scene209::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_PLANT_STALK); +} + +void Scene209::handlePause() { + switch (_game._trigger) { + case 124: + if (++_pauseCounter <= _pauseCounterThreshold) + _scene->_sequences.addTimer(60, 124); + else + _pauseMode = 0; + break; + } +} + +void Scene209::initPauseCounterThreshold() { + switch (_game._trigger) { + case 226: + _scene->_sequences.addTimer(1, 124); + _pauseCounterThreshold = _vm->getRandomNumber(7,12); + _pauseMode = 2; + _pauseCounter = 0; + break; + } +} + +void Scene209::handlePeek() { + switch (_game._trigger) { + case 133: + _vm->_sound->command(18); + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 51, 52); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 134); + break; + + case 134: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addTimer(60, 135); + } + break; + + case 135: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 7); + _scene->_sequences.addTimer(10, 136); + break; + + case 136: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6); + _scene->_sequences.addTimer(50, 137); + break; + + case 137: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 51, 52); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 138); + break; + + case 138: + _pauseMode = 1; + _scene->_hotspots.activate(227, false); + _playingAnimFl = false; + break; + } +} + +void Scene209::handleVerticalMove() { + switch (_game._trigger) { + case 140: + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 8, 0, 1); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 141); + break; + + case 141: { + _vm->_sound->command(18); + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 5); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addTimer(60, 142); + } + break; + + case 142: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 143); + break; + + case 143: + _pauseMode = 1; + _playingAnimFl = false; + _scene->_hotspots.activate(227, false); + break; + } +} + +void Scene209::handleLookStay() { + switch (_game._trigger) { + case 145: + _vm->_sound->command(18); + _monkeyPosition = 2; + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 51, 52); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 146); + break; + + case 146: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addTimer(15, 147); + } + break; + + case 147: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 7); + _scene->_sequences.addTimer(8, 148); + break; + + case 148: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6); + + if (!_dodgeFl) { + _scene->_sequences.addTimer(90, 149); + } else { + _scene->_sequences.addTimer(1, 149); + _shouldDodgeFl = true; + } + break; + + case 149: + _playingAnimFl = false; + break; + } +} + +void Scene209::handleLookRight() { + switch (_game._trigger) { + case 151: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 8, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 8, 14); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 152); + break; + + case 152: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addTimer(60, 153); + } + break; + + case 153: + _playingAnimFl = false; + if (_dodgeFl) + _shouldDodgeFl = true; + break; + } +} + +void Scene209::handleBlink() { + switch (_game._trigger) { + case 155: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6); + _scene->_sequences.addTimer(50, 156); + break; + + case 156: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 7); + _scene->_sequences.addTimer(10, 157); + break; + + case 157: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6); + _scene->_sequences.addTimer(50, 158); + break; + + case 158: + _playingAnimFl = false; + if (_dodgeFl) + _shouldDodgeFl = true; + break; + } +} + +void Scene209::handleGetBinoculars() { + switch (_game._trigger) { + case 161: + _vm->_sound->command(18); + _monkeyPosition = 3; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 8, 24); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 20, 165); + if (!_fallFl && !_dodgeFl) { + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 162); + } else { + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 163); + } + break; + + case 162: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 8, 6, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 25); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 163); + } + break; + + case 163: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 8, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 24); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addTimer(8, 164); + } + break; + + case 164: + _playingAnimFl = false; + if (_fallFl) + _shouldFallFl = true; + break; + + case 165: + _vm->_sound->command(18); + break; + } +} + +void Scene209::handleBinocularBlink() { + switch (_game._trigger) { + case 167: { + int oldIdx = _globals._sequenceIndexes[3]; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 8, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 25); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 168); + } + break; + + case 168: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 8, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 24); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addTimer(30, 169); + } + break; + + case 169: + _playingAnimFl = false; + if (_fallFl) + _shouldFallFl = true; + break; + } +} + +void Scene209::handleBinocularScan() { + switch (_game._trigger) { + case 171: { + int oldIdx = _globals._sequenceIndexes[3]; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 43, 45); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 172); + } + break; + + case 172: { + int oldIdx = _globals._sequenceIndexes[3]; + int randAction = _vm->getRandomNumber(1,2); + switch (randAction) { + case 1: + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0); + break; + case 2: + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 4, 0, 0); + break; + } + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 25); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 173); + } + break; + + case 173: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 26, 30); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 174); + } + break; + + case 174: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 24); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addTimer(60, 175); + } + break; + + case 175: + _playingAnimFl = false; + if (_fallFl) + _shouldFallFl = true; + break; + } +} + +void Scene209::handleJumpInTree() { + switch (_game._trigger) { + case 178: { + int oldIdx = 0; + _monkeyPosition = 1; + if (_removeMonkeyFl) + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + else + oldIdx = _globals._sequenceIndexes[3]; + + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 46, 49); + if (!_removeMonkeyFl) + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 179); + } + break; + + case 179: { + _vm->_sound->command(18); + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 53, 61); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 180); + } + break; + + case 180: + _removeMonkeyFl = true; + _pauseMode = 1; + _playingAnimFl = false; + _scene->_hotspots.activate(227, false); + break; + } +} + +void Scene209::handleTongue() { + switch (_game._trigger) { + case 182: { + int oldIdx = _globals._sequenceIndexes[3]; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 26, 30); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 183); + } + break; + + case 183: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 31, 33); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 184); + } + break; + + case 184: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 36, 37); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 185); + } + break; + + case 185: { + _vm->_sound->command(18); + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 6, 20, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 38, 39); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 186); + } + break; + + case 186: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 40, 41); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 178); + _removeMonkeyFl = false; + } + break; + } +} + +void Scene209::handleStandFromPeek() { + switch (_game._trigger) { + case 189: + _monkeyPosition = 4; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 50); + _scene->_sequences.addTimer(8, 190); + break; + + case 190: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6); + _scene->_sequences.addTimer(8, 191); + break; + + case 191: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 192); + break; + + case 192: { + _vm->_sound->command(18); + int oldIdx = _globals._sequenceIndexes[6]; + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], oldIdx); + _scene->_sequences.addTimer(8, 193); + } + break; + + case 193: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 22); + _scene->_sequences.addTimer(5, 194); + break; + + case 194: + _playingAnimFl = false; + _counter = 0; + break; + } +} + +void Scene209::handleStandBlink() { + switch (_game._trigger) { + case 246: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 22); + _scene->_sequences.addTimer(10, 247); + break; + + case 247: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 23); + _scene->_sequences.addTimer(8, 248); + break; + + case 248: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 22); + _scene->_sequences.addTimer(10, 249); + break; + + case 249: + _playingAnimFl = false; + break; + } +} + +void Scene209::handleJumpAndHide() { + switch (_game._trigger) { + case 196: + _vm->_sound->command(18); + _monkeyPosition = 1; + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 16); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 197); + break; + + case 197: + _pauseMode = 1; + _scene->_hotspots.activate(227, false); + _playingAnimFl = false; + break; + } +} + +void Scene209::handleMonkeyEating() { + switch (_game._trigger) { + case 199: + _vm->_sound->command(18); + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 14); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 200); + break; + + case 200: { + int oldIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 10, 10, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 15, 16); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 201); + } + break; + + case 201: { + int oldIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 12); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); + _scene->_sequences.addTimer(20, 202); + } + break; + + case 202: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 19); + _scene->_sequences.addTimer(20, 203); + break; + + case 203: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 17); + _scene->_sequences.addTimer(20, 204); + break; + + case 204: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 10, 8, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 18, 19); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 205); + break; + + case 205: { + int oldIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 10, 8, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 20, 21); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 206); + } + break; + + case 206: { + int oldIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 22, 25); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); + if (!_dodgeFl && !_fallFl) + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 207); + else + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 209); + } + break; + + case 207: { + _vm->_sound->command(18); + int msgIndex = _scene->_kernelMessages.add(Common::Point(180, 25), 0xFDFC, 0, 0, 90, _game.getQuote(130)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + + int oldIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 15, 4, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 26, 27); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 208); + } + break; + + case 208: { + _scene->_kernelMessages.add(Common::Point(180, 39), 0xFDFC, 0, 0, 90, _game.getQuote(131)); + int oldIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 10, 4, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 28, 29); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 209); + } + break; + + case 209: { + int oldIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 22); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); + _scene->_sequences.addTimer(1, 210); + } + break; + + case 210: + _playingAnimFl = false; + break; + } +} + +void Scene209::handleMonkeyFall() { + switch (_game._trigger) { + case 219: { + _vm->_sound->command(25); + _scene->_sprites.remove(_globals._spriteIndexes[7]); + _scene->_sprites.remove(_globals._spriteIndexes[6]); + _scene->_sprites.remove(_globals._spriteIndexes[5]); + _scene->_sprites.remove(_globals._spriteIndexes[4]); + + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('m', 4)); + _scene->_kernelMessages.add(Common::Point(180, 26), 0xFDFC, 0, 0, 90, _game.getQuote(151)); + _scene->_sequences.addTimer(40, 100); + _scene->_hotspots.activate(227, false); + int oldIdx = _globals._sequenceIndexes[3]; + _monkeyPosition = 1; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 1, 35); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 6); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 220); + } + break; + + case 220: { + _vm->_sound->command(18); + _scene->_kernelMessages.add(Common::Point(182, 109), 0xFDFC, 0, 0, 90, _game.getQuote(159)); + _scene->_hotspots.activate(227, false); + int oldIdx = _globals._sequenceIndexes[3]; + _monkeyPosition = 1; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 36, 42); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 6); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 221); + } + break; + + case 221: { + _game._objects.setRoom(OBJ_BINOCULARS, 209); + _binocularsDroppedFl = true; + int oldIdx = _globals._sequenceIndexes[8]; + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 1, 0, 0); + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], oldIdx); + _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(201, 131)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[8], oldIdx); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 43, 72); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 222); + int idx = _scene->_dynamicHotspots.add(39, 13, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(200, 133), FACING_NORTH); + } + break; + + case 222: { + _scene->_kernelMessages.add(Common::Point(182, 109), 0xFDFC, 0, 0, 70, _game.getQuote(160)); + int oldIdx = _globals._sequenceIndexes[8]; + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 73, 78); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[8], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 223); + } + break; + + case 223: + _scene->loadAnimation(Resources::formatName(209, 'e', -1, EXT_AA, ""), 224); + _vm->_sound->command(38); + break; + + case 224: + _playingAnimFl = false; + _fallFl = false; + _counter = 0; + _pauseMode = 0; + _vm->_dialogs->show(20910); + _game._player._stepEnabled = true; + break; + } +} + +void Scene209::handleMonkey1() { + switch (_game._trigger) { + case 212: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 9, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 13); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 213); + break; + + case 213: { + int oldIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 1, 22); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[7], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 214); + } + break; + + case 214: { + int oldIdx = _globals._sequenceIndexes[7]; + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 23, 26); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[7], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 215); + int msgIndex = _scene->_kernelMessages.add(Common::Point(170, 21), 0xFDFC, 0, 0, 90, _game.getQuote(156)); + _scene->_kernelMessages.setQuoted(msgIndex, 3, true); + } + break; + + case 215: { + _vm->_sound->command(18); + _scene->loadAnimation(Resources::formatName(209, 'a', -1, EXT_AA, ""), 251); + int oldIdx = _globals._sequenceIndexes[7]; + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 27, 35); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[7], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 216); + } + break; + + case 216: { + int oldIdx = _globals._sequenceIndexes[7]; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 22); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); + _scene->_sequences.addTimer(25, 217); + } + break; + + case 217: + _pitchFl = false; + _counter = 0; + _pauseMode = 0; + _scene->_sequences.addTimer(1, 196); + break; + } +} + +void Scene209::handleMonkey2() { + switch (_game._trigger) { + case 251: + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 60, _game.getQuote(137)); + _vm->_sound->command(22); + _globals._sequenceIndexes[12] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[12], false, 11, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[12], Common::Point(111, 133)); + _scene->_sequences.setScale(_globals._sequenceIndexes[12], 79); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[12], 1, 6); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 252); + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._visible = false; + break; + + case 252: { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(132)); + int oldIdx = _globals._sequenceIndexes[12]; + _globals._sequenceIndexes[12] = _scene->_sequences.startCycle(_globals._spriteIndexes[12], false, 7); + _scene->_sequences.setPosition(_globals._sequenceIndexes[12], Common::Point(111, 133)); + _scene->_sequences.setScale(_globals._sequenceIndexes[12], 79); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[12], oldIdx); + _scene->_sequences.addTimer(120, 253); + } + break; + + case 253: + _scene->_sequences.remove(_globals._sequenceIndexes[12]); + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + } +} + +void Scene209::handleDodge() { + switch (_game._trigger) { + case 241: + _scene->_hotspots.activate(227, true); + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 7); + _scene->_sequences.addTimer(6, 242); + break; + + case 242: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 5); + _scene->_sequences.addTimer(25, 243); + _vm->_sound->command(24); + break; + + case 243: + _vm->_sound->command(18); + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6); + _playingAnimFl = false; + _pauseMode = 0; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(180, 21), 0xFDFC, 0, 0, 90, _game.getQuote(155)); + if (!_shootMissedLastFl) { + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(135)); + _shootMissedLastFl = true; + } else { + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(136)); + } + break; + } +} + +void Scene209::enter() { + _globals._spriteIndexes[12] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('e', -1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 0)); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('b', 1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('m', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('m', 1)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('m', 3)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('m', 6)); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('m', 8)); + + _game.loadQuoteSet(0x82, 0x83, 0x84, 0x9C, 0x97, 0x95, 0x99, 0x9E, 0x98, 0x9B, 0xA0, 0x96, 0x9F, + 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x91, 0x92, 0x93, 0x94, 0x89, 0x85, 0x8A, 0x86, 0x87, 0x88, 0); + + _vm->_palette->setEntry(252, 63, 44, 30); + _vm->_palette->setEntry(253, 63, 20, 22); + + if (_game._objects.isInRoom(OBJ_PLANT_STALK)) { + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + int idx = _scene->_dynamicHotspots.add(271, 13, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(263, 129), FACING_SOUTH); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 13); + } + + if (_scene->_priorSceneId == 208) { + _game._player._playerPos = Common::Point(11, 121); + _game._player._facing = FACING_EAST; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(28, 121); + _game._player._facing = FACING_SOUTH; + } + + if (_game._objects.isInRoom(OBJ_BINOCULARS)) { + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(201, 131)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + int idx = _scene->_dynamicHotspots.add(39, 13, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(200, 133), FACING_NORTH); + } + + if (_scene->_roomChanged) { + _game._objects.addToInventory(OBJ_POISON_DARTS); + _game._objects.addToInventory(OBJ_BLOWGUN); + _globals[kMonkeyStatus] = MONKEY_HAS_BINOCULARS; + } + + _pitchFl = false; + _fallFl = false; + _dodgeFl = false; + _playingAnimFl = false; + _monkeyPosition = 1; + _counter = 0; + _pauseMode = 0; + _forceFallFl = false; + _shouldFallFl = false; + _forceDodgeFl = false; + _binocularsDroppedFl = false; + _shouldDodgeFl = false; + _startShootingInTimerFl = false; + _dialogAbortVal = 5; + _playingDialogFl = false; + _shootMissedLastFl = false; + _removeMonkeyFl = true; + _shootReadyFl = false; + + _scene->_hotspots.activate(227, false); + + sceneEntrySound(); +} + +void Scene209::step() { + if (!_playingAnimFl && !_pitchFl && !_fallFl && !_dodgeFl && (_pauseMode == 0) && (_globals[kMonkeyStatus] == MONKEY_HAS_BINOCULARS)) { + int randAction = _vm->getRandomNumber(1,50); + switch (randAction) { + case 1: + if ((_monkeyPosition == 1) && (_counter < 2)) { + _scene->_sequences.addTimer(1, 133); + _playingAnimFl = true; + _scene->_hotspots.activate(227, true); + ++_counter; + } + break; + + case 2: + if ((_monkeyPosition == 1) && (_counter < 2)) { + _scene->_sequences.addTimer(1, 140); + _scene->_hotspots.activate(227, true); + _playingAnimFl = true; + ++_counter; + } + break; + + case 3: + if (_monkeyPosition == 1) { + _scene->_sequences.addTimer(1, 145); + _scene->_hotspots.activate(227, true); + _playingAnimFl = true; + _counter = 0; + } + break; + + case 4: + if ((_monkeyPosition == 2) && (_counter < 2)) { + _scene->_sequences.addTimer(1, 151); + _scene->_hotspots.activate(227, true); + ++_counter; + _playingAnimFl = true; + } + break; + + case 5: + if (_monkeyPosition == 2) { + _scene->_sequences.addTimer(1, 161); + _scene->_hotspots.activate(227, true); + _counter = 0; + _playingAnimFl = true; + } + break; + + case 6: + if (_monkeyPosition == 2) { + _scene->_sequences.addTimer(1, 189); + _scene->_hotspots.activate(227, true); + _counter = 0; + _playingAnimFl = true; + } + break; + case 7: + if (_monkeyPosition == 3) { + _scene->_hotspots.activate(227, true); + _scene->_sequences.addTimer(1, 167); + _playingAnimFl = true; + } + break; + + case 8: + if (_monkeyPosition == 3) { + _scene->_sequences.addTimer(1, 178); + _playingAnimFl = true; + _scene->_hotspots.activate(227, true); + _counter = 0; + } + break; + + case 9: + if ((_monkeyPosition == 3) && (_game._player._playerPos.x<120)) { + _scene->_sequences.addTimer(1, 182); + _scene->_hotspots.activate(227, true); + _counter = 0; + _playingAnimFl = true; + } + break; + + case 10: + if (_monkeyPosition == 4) { + _scene->_sequences.addTimer(1, 196); + _scene->_hotspots.activate(227, true); + _playingAnimFl = true; + _counter = 0; + } + break; + + case 11: + if ((_monkeyPosition == 4) && (_counter < 3)) { + _scene->_sequences.addTimer(1, 199); + _scene->_hotspots.activate(227, true); + ++_counter; + _playingAnimFl = true; + } + break; + + case 30: + if (_monkeyPosition == 4) { + _scene->_sequences.addTimer(1, 246); + _scene->_hotspots.activate(227, true); + _counter = 0; + _playingAnimFl = true; + } + break; + + default: + if ((randAction >= 12) && (randAction <= 20) && (_monkeyPosition == 2) && (_counter < 5)) { + _scene->_sequences.addTimer(1, 155); + ++_counter; + _playingAnimFl = true; + } + + if ((randAction >= 21) && (randAction <= 29) && (_monkeyPosition == 3) && (_counter < 3)) { + _scene->_sequences.addTimer(1, 171); + _playingAnimFl = true; + ++_counter; + } + break; + } + } + + if (!_dodgeFl && !_pitchFl && !_fallFl && (_pauseMode == 1)) + _scene->_sequences.addTimer(1, 226); + + if (!_dodgeFl && !_pitchFl && !_fallFl && (_pauseMode == 2)) + handlePause(); + + if (!_dodgeFl && !_pitchFl && !_fallFl && (_pauseMode == 1)) + initPauseCounterThreshold(); + + handlePeek(); + handleVerticalMove(); + handleLookStay(); + handleLookRight(); + handleBlink(); + handleGetBinoculars(); + handleStandFromPeek(); + handleDodge(); + handleBinocularBlink(); + handleBinocularScan(); + handleJumpInTree(); + handleTongue(); + handleMonkeyFall(); + handleJumpAndHide(); + handleMonkeyEating(); + handleMonkey1(); + handleStandBlink(); + handleMonkey2(); + + if ((_monkeyPosition == 1) && !_playingAnimFl && _fallFl) { + _scene->_sequences.addTimer(1, 145); + _playingAnimFl = true; + } + + if ((_monkeyPosition == 2) && !_playingAnimFl && _fallFl) { + _scene->_sequences.addTimer(1, 161); + _playingAnimFl = true; + } + + if ((_monkeyPosition == 4) && !_playingAnimFl && _fallFl) { + _scene->_sequences.addTimer(1, 196); + _playingAnimFl = true; + } + + if ((_monkeyPosition == 3) && !_playingAnimFl && _fallFl && _forceFallFl) { + _scene->_sequences.addTimer(1, 219); + _playingAnimFl = true; + } + + if ((_monkeyPosition == 1) && !_playingAnimFl && _pitchFl) { + _scene->_sequences.addTimer(1, 145); + _playingAnimFl = true; + } + + if ((_monkeyPosition == 2) && !_playingAnimFl && _pitchFl) { + _scene->_sequences.addTimer(1, 189); + _playingAnimFl = true; + } + + if ((_monkeyPosition == 4) && !_playingAnimFl && _pitchFl) { + _scene->_sequences.addTimer(1, 212); + _playingAnimFl = true; + } + + if ((_monkeyPosition == 3) && !_playingAnimFl && _pitchFl) { + _scene->_sequences.addTimer(1, 178); + _playingAnimFl = true; + } + + if ((_monkeyPosition == 1) && !_playingAnimFl && _dodgeFl) { + _scene->_sequences.addTimer(1, 145); + _playingAnimFl = true; + } + + if ((_monkeyPosition == 4) && !_playingAnimFl && _dodgeFl) { + _scene->_sequences.addTimer(1, 196); + _playingAnimFl = true; + } + + if ((_monkeyPosition == 3) && !_playingAnimFl && _dodgeFl) { + _scene->_sequences.addTimer(1, 178); + _playingAnimFl = true; + } + + if ((_monkeyPosition == 2) && !_playingAnimFl && _dodgeFl && _forceDodgeFl) { + _scene->_sequences.addTimer(1, 241); + _playingAnimFl = true; + } + + if (_dodgeFl || _fallFl) { /* if want to dodge or fall */ + if (!_playingAnimFl && (_monkeyPosition == 2)) + _shouldDodgeFl = true; + + if (!_playingAnimFl && (_monkeyPosition == 3)) + _shouldFallFl = true; + + switch (_game._trigger) { + case 228: + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 7); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 229); + break; + + case 229: { + int oldIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 7); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx); + _scene->_sequences.addTimer(35, 230); + } + break; + + case 230: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 7); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 231); + break; + + case 231: { + int oldIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 8, 10); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 232); + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], -1); + _game._player._visible = false; + } + break; + + case 232: { + int oldIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 10); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx); + _scene->_sequences.addTimer(2, 233); + _scene->_kernelMessages.reset(); + if (_dodgeFl && (_monkeyPosition != 1) && (_monkeyPosition != 2)) + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 34463, _game.getQuote(138)); + if (_fallFl && (_monkeyPosition != 3)) + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 34463, _game.getQuote(138)); + } + break; + + case 233: + _shootReadyFl = true; + break; + + case 234: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _scene->_kernelMessages.reset(); + if (_action.isAction(VERB_HOSE_DOWN, NOUN_BLOWGUN, NOUN_MONKEY)) { + _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 7, 16, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 11, 12); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 12, 239); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 235); + } else if (_action.isAction(VERB_SHOOT, NOUN_BLOWGUN, NOUN_MONKEY)) { + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 11, 12); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 235); + _vm->_sound->command(23); + } + break; + + case 235: { + int oldIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 13); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx); + _scene->_sequences.addTimer(12, 236); + _forceFallFl = true; + _forceDodgeFl = true; + } + break; + + case 236: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 14, 16); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 237); + break; + + case 237: + _game._player._visible = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _scene->_sequences.addTimer(1, 238); + break; + + case 238: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + if (_dodgeFl) + _game._player._stepEnabled = true; + + _startShootingInTimerFl = false; + + if (_fallFl) { + _globals[kMonkeyStatus] = MONKEY_IS_GONE; + _game._objects.setRoom(OBJ_POISON_DARTS, NOWHERE); + } + _dodgeFl = false; + _fallFl = false; + _forceFallFl = false; + _forceDodgeFl = false; + _shouldFallFl = false; + _shouldDodgeFl = false; + break; + + case 239: + _vm->_sound->command(23); + break; + } + } + + if (_game._trigger == 100) + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(134)); + + if (_shootReadyFl && (_shouldFallFl || _shouldDodgeFl)) { + _scene->_sequences.addTimer(4, 234); + _shootReadyFl = false; + } +} + +void Scene209::preActions() { + if (_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_WEST)) + _game._player._walkOffScreenSceneId = 208; + + if (_globals[kMonkeyStatus] == MONKEY_HAS_BINOCULARS) { + if ((_action.isAction(VERB_SHOOT) || _action.isAction(VERB_HOSE_DOWN)) && _action.isTarget(NOUN_MONKEY) + && _action.isObject(NOUN_BLOWGUN) && _game._objects.isInInventory(OBJ_BLOWGUN) && _game._objects.isInInventory(OBJ_POISON_DARTS)) { + _game._player._prepareWalkPos = Common::Point(111, 129); + _game._player._prepareWalkFacing = FACING_NORTHEAST; + _game._player._needToWalk = true; + _game._player._readyToWalk = true; + } + + if (_action.isAction(VERB_LOOK, NOUN_MONKEY) || _action.isAction(VERB_TALKTO, NOUN_MONKEY)) { + _game._player._prepareWalkPos = Common::Point(111, 129); + _game._player._prepareWalkFacing = FACING_NORTHEAST; + _game._player._needToWalk = true; + _game._player._readyToWalk = true; + } + } +} + +void Scene209::actions() { + if (_action._lookFlag) { + _vm->_dialogs->show(20912); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_WALK_TOWARDS, NOUN_ROCKY_AREA_TO_NORTH)) { + _scene->_nextSceneId = 203; + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TALKTO, NOUN_MONKEY) && !_pitchFl && !_playingDialogFl) { + _scene->_sequences.addTimer(1, _dialogAbortVal); + _playingDialogFl = true; + _game._player._stepEnabled = false; + _action._inProgress = false; + return; + } + + switch (_game._trigger) { + case 130: + _game._player._stepEnabled = true; + _playingDialogFl = false; + _action._inProgress = false; + return; + + case 5: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 6, 180, _game.getQuote(139)); + _action._inProgress = false; + return; + + case 6: + _scene->_kernelMessages.add(Common::Point(180, 21), 0xFDFC, 0, 0, 60, _game.getQuote(151)); + _scene->_sequences.addTimer(60, 130); + _dialogAbortVal = 7; + _action._inProgress = false; + return; + + case 7: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 8, 180, _game.getQuote(140)); + _action._inProgress = false; + return; + + case 8: + _scene->_kernelMessages.add(Common::Point(180, 21), 0xFDFC, 0, 0, 60, _game.getQuote(149)); + _scene->_sequences.addTimer(60, 130); + _dialogAbortVal = 9; + _action._inProgress = false; + return; + + case 9: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 180, _game.getQuote(141)); + _scene->_sequences.addTimer(200, 10); + _action._inProgress = false; + return; + + case 10: + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 11, 180, _game.getQuote(142)); + _action._inProgress = false; + return; + + case 11: + _scene->_kernelMessages.add(Common::Point(180, 21), 0xFDFC, 0, 0, 60, _game.getQuote(152)); + _scene->_sequences.addTimer(60, 130); + _dialogAbortVal = 12; + _action._inProgress = false; + return; + + case 12: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 130, _game.getQuote(143)); + _scene->_sequences.addTimer(150, 13); + _action._inProgress = false; + return; + + case 13: + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 14, 180, _game.getQuote(145)); + _action._inProgress = false; + return; + + case 14: + _scene->_kernelMessages.add(Common::Point(180, 21), 0xFDFC, 0, 0, 60, _game.getQuote(151)); + _scene->_sequences.addTimer(60, 130); + _dialogAbortVal = 15; + _action._inProgress = false; + return; + + case 15: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 16, 180, _game.getQuote(146)); + _action._inProgress = false; + return; + + case 16: + _scene->_kernelMessages.add(Common::Point(180, 21), 0xFDFC, 0, 17, 60, _game.getQuote(154)); + _action._inProgress = false; + return; + + case 17: + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 130, 60, _game.getQuote(147)); + _dialogAbortVal = 18; + _action._inProgress = false; + return; + + case 18: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 180, _game.getQuote(148)); + _pitchFl = true; + _playingDialogFl = false; + _dialogAbortVal = 5; + _action._inProgress = false; + return; + } + + if (_globals[kMonkeyStatus] == MONKEY_HAS_BINOCULARS) { + if ((_action.isAction(VERB_SHOOT) || _action.isAction(VERB_HOSE_DOWN)) && _action.isTarget(NOUN_MONKEY) + && _action.isObject(NOUN_BLOWGUN) && _game._objects.isInInventory(OBJ_BLOWGUN) && _game._objects.isInInventory(OBJ_POISON_DARTS)) { + if (_action.isAction(VERB_SHOOT, NOUN_BLOWGUN, NOUN_MONKEY) && !_startShootingInTimerFl) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 231); + _startShootingInTimerFl = true; + _game._player._stepEnabled = false; + _dodgeFl = true; + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_HOSE_DOWN, NOUN_BLOWGUN, NOUN_MONKEY) && !_startShootingInTimerFl) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 228); + _game._player._stepEnabled = false; + _fallFl = true; + _startShootingInTimerFl = true; + _action._inProgress = false; + return; + } + } + + if (_action.isAction(VERB_LOOK, NOUN_MONKEY)) { + _pitchFl = true; + _game._player._stepEnabled = false; + _vm->_dialogs->show(20914); + _action._inProgress = false; + return; + } + } + + if (_action.isAction(VERB_TAKE, NOUN_PLANT_STALK) && (_game._trigger || _game._objects.isInRoom(OBJ_PLANT_STALK))) { + switch (_game._trigger) { + case 0: + _globals._spriteIndexes[11] = _scene->_sprites.addSprites("*RXMBD_2"); + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[11] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[11], false, 3, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[11]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_SPRITE, 4, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _game._objects.addToInventory(OBJ_PLANT_STALK); + break; + + case 2: + _game._player._visible = true; + _game._player._stepEnabled = true; + _scene->_sequences.addTimer(4, 3); + _vm->_dialogs->showItem(OBJ_PLANT_STALK, 0x328); + break; + + case 3: + _scene->_sprites.remove(_globals._spriteIndexes[11]); + break; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_BINOCULARS) && (_game._trigger || _game._objects.isInRoom(OBJ_BINOCULARS))) { + switch (_game._trigger) { + case 0: + _globals._spriteIndexes[10] = _scene->_sprites.addSprites("*RXMBD_8"); + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[10] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[10], false, 3, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[10]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[10], SEQUENCE_TRIGGER_SPRITE, 4, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[10], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _game._objects.addToInventory(OBJ_BINOCULARS); + break; + + case 2: + _game._player._visible = true; + _game._player._stepEnabled = true; + _binocularsDroppedFl = false; + _scene->_sequences.addTimer(4, 3); + break; + + case 3: + _vm->_dialogs->showItem (OBJ_BINOCULARS, 0x51AF); + _scene->_sprites.remove(_globals._spriteIndexes[10]); + break; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_SKY)) { + _vm->_dialogs->show(20901); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_BAMBOO_LIKE_PLANT)) { + _vm->_dialogs->show(20902); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_MOUNTAINSIDE)) { + _vm->_dialogs->show(20903); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_GRASSY_FIELD)) { + _vm->_dialogs->show(20904); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_FIELD_TO_WEST)) { + _vm->_dialogs->show(20905); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_ROCKY_AREA_TO_NORTH)) { + _vm->_dialogs->show(20906); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_PLANT_STALK) && (_action._savedFields._mainObjectSource == 4)) { + _vm->_dialogs->show(20907); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_GIVE, NOUN_TWINKIFRUIT, NOUN_MONKEY) || _action.isAction(VERB_THROW, NOUN_TWINKIFRUIT, NOUN_MONKEY)) { + _vm->_dialogs->show(20909); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_TREES)) { + _vm->_dialogs->show(20913); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_THROW, NOUN_MONKEY) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) { + if (!_action.isObject(NOUN_POISON_DARTS)) { + _vm->_dialogs->show(20915); + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_THROW, NOUN_POISON_DARTS, NOUN_MONKEY)) { + _vm->_dialogs->show(20916); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_PALM_TREE)) { + if (_globals[kMonkeyStatus] == MONKEY_HAS_BINOCULARS) { + if (_monkeyPosition == 1) + _vm->_dialogs->show(20917); + else + _vm->_dialogs->show(20918); + } else { + if (_globals[kMonkeyStatus] == MONKEY_AMBUSH_READY) + _vm->_dialogs->show(20917); + else + _vm->_dialogs->show(20919); + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_MELON_MUSH)) { + _vm->_dialogs->show(20920); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_MELON_MUSH)) { + _vm->_dialogs->show(20921); + _action._inProgress = false; + return; + } +} + +/*****************************************************************************/ + +Scene210::Scene210(MADSEngine *vm) : Scene2xx(vm) { + _curDialogNode = -1; + _nextHandsPlace = 0; + _twinkleAnimationType = 0; + _twinklesCurrentFrame = 0; + _shouldTalk = false; + _shouldFaceRex = false; + _shouldMoveHead = false; + _stopWalking = false; + _twinklesTalking = false; + _twinklesTalk2 = false; + _doorway = 0; + _subQuote2 = ""; +} + +void Scene210::synchronize(Common::Serializer &s) { + Scene2xx::synchronize(s); + + s.syncAsSint32LE(_curDialogNode); + s.syncAsSint32LE(_nextHandsPlace); + s.syncAsSint32LE(_twinkleAnimationType); + s.syncAsSint32LE(_twinklesCurrentFrame); + + s.syncAsByte(_shouldTalk); + s.syncAsByte(_shouldFaceRex); + s.syncAsByte(_shouldMoveHead); + s.syncAsByte(_stopWalking); + s.syncAsByte(_twinklesTalking); + s.syncAsByte(_twinklesTalk2); + + s.syncAsSint32LE(_doorway); + + s.syncString(_subQuote2); +} + +void Scene210::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_DOORWAY); + _scene->addActiveVocab(VERB_WALK_THROUGH); +} + +void Scene210::handleConversations() { + if (_game._trigger == 0) { + _scene->_kernelMessages.reset(); + _game._player._stepEnabled = false; + Common::String curQuote = _game.getQuote(_action._activeAction._verbId); + if (_scene->_kernelMessages._talkFont->getWidth(curQuote, _scene->_textSpacing) > 200) { + Common::String subQuote1; + _game.splitQuote(curQuote, subQuote1, _subQuote2); + _scene->_kernelMessages.add(Common::Point(0, -14), 0x1110, 34, 0, 240, subQuote1); + _scene->_sequences.addTimer(60, 50); + } else { + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 1, 120, curQuote); + } + } else if (_game._trigger == 50) { + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 240, _subQuote2); + _scene->_sequences.addTimer(180, 1); + } else { + if (_game._trigger == 1) + _scene->_kernelMessages.reset(); + + switch (_curDialogNode) { + case 1: + handleConversation1(); + break; + + case 2: + handleConversation2(); + break; + + case 3: + handleConversation3(); + break; + + case 5: + handleConversation5(); + break; + + case 6: + handleConversation6(); + break; + + case 7: + handleConversation7(); + break; + + case 8: + handleConversation8(); + break; + } + } +} + +void Scene210::handleConversation1() { + switch (_action._activeAction._verbId) { + case 180: + setDialogNode(2); + break; + + case 181: + setDialogNode(6); + break; + + case 182: + setDialogNode(4); + break; + + case 183: + setDialogNode(9); + break; + + case 184: + setDialogNode(0); + break; + } +} + +void Scene210::handleConversation2() { + switch (_action._activeAction._verbId) { + case 187: + setDialogNode(3); + break; + + case 188: + setDialogNode(4); + break; + + case 189: + setDialogNode(0); + break; + } +} + +void Scene210::handleConversation3() { + switch (_action._activeAction._verbId) { + case 193: + setDialogNode(6); + break; + + case 194: + setDialogNode(5); + break; + + case 195: + setDialogNode(4); + break; + + case 196: + setDialogNode(0); + break; + } +} + +void Scene210::handleConversation5() { + switch (_action._activeAction._verbId) { + case 204: + setDialogNode(6); + break; + + case 205: + case 206: + setDialogNode(4); + break; + + case 207: + setDialogNode(0); + break; + } +} + +void Scene210::handleConversation6() { + switch (_action._activeAction._verbId) { + case 211: + setDialogNode(7); + break; + + case 212: + setDialogNode(4); + break; + + case 213: + setDialogNode(0); + break; + } +} + +void Scene210::handleConversation7() { + switch (_action._activeAction._verbId) { + case 216: + case 217: + case 219: + setDialogNode(4); + break; + + case 218: + setDialogNode(8); + break; + + case 220: + setDialogNode(0); + break; + } +} + +void Scene210::handleConversation8() { + switch (_action._activeAction._verbId) { + case 223: + case 224: + setDialogNode(4); + break; + + case 225: + case 226: + setDialogNode(9); + break; + + case 227: + setDialogNode(0); + break; + } +} + +void Scene210::setDialogNode(int node) { + switch (node) { + case 0: + _scene->_userInterface.setup(kInputBuildingSentences); + _shouldFaceRex = false; + _shouldTalk = false; + _game._player._stepEnabled = true; + _curDialogNode = 0; + break; + + case 2: + switch (_game._trigger) { + case 1: + _nextHandsPlace = 1; + _shouldTalk = true; + _game._player._stepEnabled = false; + if (_twinklesTalking) { + handleTwinklesSpeech(0xB9, -1, 0); + _scene->_sequences.addTimer(180, 2); + } else { + _scene->_sequences.addTimer(6, 1); + } + break; + + case 2: + _nextHandsPlace = 0; + handleTwinklesSpeech(186, 0, 0); + _scene->_sequences.addTimer(180, 3); + break; + + default: + _nextHandsPlace = 0; + _shouldTalk = false; + _game._player._stepEnabled = true; + newNode(2); + break; + } + break; + + case 3: + switch (_game._trigger) { + case 1: + _nextHandsPlace = 0; + _shouldTalk = true; + _game._player._stepEnabled = false; + if (_twinklesTalking) { + handleTwinklesSpeech(0xBE, -2, 0); + _scene->_sequences.addTimer(180, 2); + } else { + _scene->_sequences.addTimer(6, 1); + } + break; + case 2: + _nextHandsPlace = 2; + handleTwinklesSpeech(191, -1, 0); + _scene->_sequences.addTimer(180, 3); + break; + case 3: + _nextHandsPlace = 0; + handleTwinklesSpeech(192, 0, 0); + _scene->_sequences.addTimer(180, 4); + break; + default: + _shouldTalk = false; + _game._player._stepEnabled = true; + newNode(3); + break; + } + break; + + case 4: + if (_game._trigger == 1) { + _nextHandsPlace = 1; + _shouldTalk = true; + _game._player._stepEnabled = false; + + int quote; + if (_game._storyMode == STORYMODE_NAUGHTY) + quote = _vm->getRandomNumber(199, 201); + else + quote = _vm->getRandomNumber(197, 198); + + if (_twinklesTalking) { + handleTwinklesSpeech(quote, 0, 360); + _scene->_sequences.addTimer(120, 2); + } else { + _scene->_sequences.addTimer(6, 1); + } + } else { + _scene->_userInterface.setup(kInputBuildingSentences); + _shouldFaceRex = false; + _shouldTalk = false; + _game._player._stepEnabled = true; + } + break; + + case 5: + switch (_game._trigger) { + case 1: + _nextHandsPlace = 2; + _shouldTalk = true; + _game._player._stepEnabled = false; + if (_twinklesTalking) { + handleTwinklesSpeech(0xCA, -1, 0); + _scene->_sequences.addTimer(180, 2); + } else { + _scene->_sequences.addTimer(6, 1); + } + break; + + case 2: + _nextHandsPlace = 1; + handleTwinklesSpeech(0xCB, 0, 0); + _scene->_sequences.addTimer(180, 3); + break; + + default: + _nextHandsPlace = 2; + _shouldTalk = false; + _game._player._stepEnabled = true; + newNode(5); + break; + } + break; + + case 6: + switch (_game._trigger) { + case 1: + _nextHandsPlace = 1; + _shouldTalk = true; + _game._player._stepEnabled = false; + if (_twinklesTalking) { + handleTwinklesSpeech(0xD0, -2, 0); + _scene->_sequences.addTimer(180, 2); + } else { + _scene->_sequences.addTimer(6, 1); + } + break; + + case 2: + handleTwinklesSpeech(0xD1, -1, 0); + _scene->_sequences.addTimer(180, 3); + break; + + case 3: + _nextHandsPlace = 1; + handleTwinklesSpeech(0xD2, 0, 0); + _scene->_sequences.addTimer(180, 4); + break; + + default: + _nextHandsPlace = 0; + _shouldTalk = false; + _game._player._stepEnabled = true; + newNode(6); + break; + } + break; + + case 7: + switch (_game._trigger) { + case 1: + _nextHandsPlace = 2; + _shouldTalk = true; + _game._player._stepEnabled = false; + if (_twinklesTalking) { + handleTwinklesSpeech(0xD6, -1, 0); + _scene->_sequences.addTimer(180, 2); + } else { + _scene->_sequences.addTimer(6, 1); + } + break; + + case 2: + handleTwinklesSpeech(0xD7, 0, 0); + _scene->_sequences.addTimer(180, 3); + break; + + default: + _shouldTalk = false; + _game._player._stepEnabled = true; + newNode(7); + break; + } + break; + + case 8: + switch (_game._trigger) { + case 1: + _nextHandsPlace = 2; + _shouldTalk = true; + _game._player._stepEnabled = false; + if (_twinklesTalking) { + handleTwinklesSpeech(0xDD, -1, 0); + _scene->_sequences.addTimer(180, 2); + } else { + _scene->_sequences.addTimer(6, 1); + } + break; + + case 2: + handleTwinklesSpeech(0xDE, 0, 0); + _scene->_sequences.addTimer(180, 3); + break; + + default: + _shouldTalk = false; + _game._player._stepEnabled = true; + newNode(8); + break; + } + break; + + + case 9: + switch (_game._trigger) { + case 1: + _nextHandsPlace = 0; + _shouldTalk = true; + _game._player._stepEnabled = false; + if (_twinklesTalking) { + _scene->_userInterface.emptyConversationList(); + _scene->_userInterface.setup(kInputConversation); + handleTwinklesSpeech(0xE4, -1, 0); + _scene->_sequences.addTimer(180, 2); + } else { + _scene->_sequences.addTimer(6, 1); + } + break; + + case 2: + handleTwinklesSpeech(0xE5, 0, 0); + _scene->_sequences.addTimer(180, 3); + break; + + case 3: + _twinkleAnimationType = 2; + _globals[kCurtainOpen] = true; + _game._player._visible = false; + _vm->_palette->lock(); + _scene->_kernelMessages.reset(); + _scene->freeAnimation(); + _scene->_activeAnimation = nullptr; + _scene->resetScene(); + + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', -1)); + _game.loadQuoteSet(0xE6, 0xE9, 0xEA, 0xE7, 0xE8, 0); + _scene->loadAnimation(formAnimName('B', -1), 4); + break; + + case 4: { + _globals._spriteIndexes[8] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 5); + _scene->_sequences.setDepth(_globals._spriteIndexes[8], 1); + + int msgIndex = _scene->_kernelMessages.add(Common::Point(160, 20), 0x1110, 32, 5, 180, _game.getQuote(231)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + } + break; + + case 5: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(160, 40), 0xFDFC, 32, 6, 180, _game.getQuote(233)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + } + break; + + case 6: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(160, 60), 0x1110, 32, 7, 180, _game.getQuote(232)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + } + break; + + case 7: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(160, 80), 0xFDFC, 32, 8, 180, _game.getQuote(234)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + } + break; + + case 8: + _globals[kTwinklesStatus] = TWINKLES_GONE; + _scene->_nextSceneId = 216; + break; + } + break; + } +} + +void Scene210::handleTwinklesSpeech(int quoteId, int shiftX, uint32 delay) { + _scene->_kernelMessages.add(Common::Point(10, 70 + (shiftX * 14)), 0xFDFC, 0, 0, (delay == 0) ? 9999999 : delay, _game.getQuote(quoteId)); +} + +void Scene210::newNode(int node) { + _curDialogNode = node; + + switch (_curDialogNode) { + case 1: + _conv1.start(); + break; + + case 2: + _conv2.start(); + break; + + case 3: + _conv3.start(); + break; + + case 5: + _conv5.start(); + break; + + case 6: + _conv6.start(); + break; + + case 7: + _conv7.start(); + break; + + case 8: + _conv8.start(); + break; + + default: + break; + } +} + +void Scene210::restoreDialogNode(int node, int msgId, int posY) { + int curQuoteId = msgId; + int curY = 1 - posY; + for (int count = 0; count < posY; count++) { + handleTwinklesSpeech(curQuoteId, curY, 0); + curY++; + curQuoteId++; + } + + newNode(node); +} + +void Scene210::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', -1)); + + if (!_game._visitedScenes._sceneRevisited) + _globals[kCurtainOpen] = 0; + + if (_scene->_priorSceneId == 205) + _game._player._playerPos = Common::Point(277, 56); + else if (_scene->_priorSceneId == 215) { + _game._player._playerPos = Common::Point(168, 128); + _game._player._facing = FACING_SOUTH; + _globals[kCurtainOpen] = true; + } else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(308, 132); + + if (!_globals[kCurtainOpen]) { + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); + } else { + int idx = _scene->_dynamicHotspots.add(112, 395, -1, Common::Rect(163, 87, 163 + 19, 87 + 36)); + _doorway = _scene->_dynamicHotspots.setPosition(idx, Common::Point(168, 127), FACING_NORTH); + _scene->_dynamicHotspots.setCursor(_doorway, CURSOR_GO_UP); + } + + _game.loadQuoteSet(0x5A, 0x73, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB8, 0xB7, + 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, + 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, + 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0); + + _conv1.setup(0x2E, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0); + + if (!_game._visitedScenes._sceneRevisited) { + _conv1.set(0x2E, 0xB4, 0xB5, 0xB6, 0xB8, 0); + + if (_game._widepipeCtr >= 2) + _conv1.write(0xB7, true); + } + + bool sceneRevisited = _game._visitedScenes._sceneRevisited; + _conv2.setup(0x2F, 0xBC, 0xBB, 0xBD, sceneRevisited ? 0 : -1); + _conv3.setup(0x30, 0xC3, 0xC2, 0xC1, 0xC4, sceneRevisited ? 0 : -1); + _conv5.setup(0x31, 0xCD, 0xCC, 0xCE, 0xCF, sceneRevisited ? 0 : -1); + _conv6.setup(0x32, 0xD3, 0xD4, 0xD5, sceneRevisited ? 0 : -1); + _conv7.setup(0x33, 0xD8, 0xDA, 0xD9, 0xDB, 0xDC, sceneRevisited ? 0 : -1); + _conv8.setup(0x34, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, sceneRevisited ? 0 : -1); + + _twinkleAnimationType = 0; + _twinklesCurrentFrame = 0; + + if (_scene->_priorSceneId != -2) { + _shouldMoveHead = false; + _shouldFaceRex = false; + _shouldTalk = false; + _nextHandsPlace = 0; + _twinklesTalking = false; + _curDialogNode = 0; + _stopWalking = false; + _twinklesTalk2 = (_globals[kTwinklesApproached] > 0); + } + + if (_globals[kTwinklesStatus] == 0) { + _scene->loadAnimation(formAnimName('A', -1)); + _twinkleAnimationType = 1; + } else + _scene->_hotspots.activate(476, false); + + if (_curDialogNode) { + int quote = 0; + int number = 0; + + switch (_curDialogNode) { + case 1: + quote = 0xB3; + number = 1; + break; + case 2: + quote = 0xB9; + number = 2; + break; + case 3: + quote = 0xBE; + number = 3; + break; + case 5: + quote = 0xCA; + number = 2; + break; + case 6: + quote = 0xD0; + number = 3; + break; + case 7: + quote = 0xD6; + number = 2; + break; + case 8: + quote = 0xDD; + number = 2; + break; + } + + restoreDialogNode(_curDialogNode, quote, number); + if (_scene->_activeAnimation) + _scene->_activeAnimation->setCurrentFrame(131); + } + + _vm->_palette->setEntry(252, 63, 63, 10); + _vm->_palette->setEntry(253, 45, 45, 5); + + sceneEntrySound(); +} + +void Scene210::step() { + if ((_twinkleAnimationType == 1) && _scene->_activeAnimation) { + if (_twinklesCurrentFrame != _scene->_activeAnimation->getCurrentFrame()) { + _twinklesCurrentFrame = _scene->_activeAnimation->getCurrentFrame(); + int reset_frame = -1; + int random = _vm->getRandomNumber(1, 1000); + + switch (_twinklesCurrentFrame) { + case 31: + case 58: + case 74: + case 108: + case 190: + if (_shouldFaceRex) + reset_frame = 108; + else if ((random <= 100) || _shouldMoveHead) + reset_frame = 74; + else if (random <= 300) + reset_frame = 58; + else if (random <= 500) + reset_frame = 31; + else + reset_frame = 0; + break; + + case 80: + case 90: + _twinklesTalking = false; + if (_shouldMoveHead) { + reset_frame = 90; + } else if (_twinklesCurrentFrame == 90) { + if ((random <= 400) || _shouldFaceRex) + reset_frame = 99; + else + reset_frame = 79; + } + break; + + case 98: + if (_shouldMoveHead) + reset_frame = 91; + break; + + case 99: + if ((random <= 400) && !_shouldFaceRex) + reset_frame = 79; + break; + + case 124: + case 136: + case 174: + case 143: + case 152: + if (_nextHandsPlace == 3) + reset_frame = 174; + else if (!_shouldFaceRex) + reset_frame = 174; + else if (_nextHandsPlace == 1) + reset_frame = 136; + else if (_nextHandsPlace == 2) + reset_frame = 152; + else if (_shouldTalk) + reset_frame = 124; + else + reset_frame = (random <= 200) ? 131 : 143; + break; + + case 131: + if (_shouldTalk) { + switch (_nextHandsPlace) { + case 1: + reset_frame = 136; + break; + case 2: + reset_frame = 152; + break; + default: + reset_frame = 124; + break; + } + } + break; + + case 138: + case 141: + if ((_nextHandsPlace == 0) || !_shouldFaceRex) + reset_frame = 141; + else if (_nextHandsPlace == 2) + reset_frame = 152; + else if (!_shouldTalk || (_twinklesCurrentFrame == 141)) + reset_frame = 137; + break; + + case 153: + case 169: + if ((_nextHandsPlace == 0) || !_shouldFaceRex) + reset_frame = 169; + else if (_nextHandsPlace == 1) + reset_frame = 136; + else if (_shouldTalk) + reset_frame = 153; + else + reset_frame = 162; + break; + + case 162: + if (_shouldTalk) { + switch (_nextHandsPlace) { + case 0: + reset_frame = 124; + break; + case 1: + reset_frame = 136; + break; + default: + reset_frame = 153; + break; + } + } + break; + } + + if (reset_frame >= 0) { + if (reset_frame != _scene->_activeAnimation->getCurrentFrame()) { + _scene->_activeAnimation->setCurrentFrame(reset_frame); + _twinklesCurrentFrame = reset_frame; + } + + if ((reset_frame == 90) || (reset_frame == 91) || (reset_frame == 124) || (reset_frame == 153) + || ((reset_frame == 137) && _shouldTalk)) { + _twinklesTalking = true; + } else { + _twinklesTalking = false; + } + } + } + } + + if ((_twinkleAnimationType == 2) && _scene->_activeAnimation) { + if (_twinklesCurrentFrame != _scene->_activeAnimation->getCurrentFrame()) { + _twinklesCurrentFrame = _scene->_activeAnimation->getCurrentFrame(); + int reset_frame = -1; + + if (_twinklesCurrentFrame == 53) { + _scene->_kernelMessages.add(Common::Point(151, 61), 0xFDFC, 32, 70, 180, _game.getQuote(230)); + _shouldTalk = true; + } else if ((_twinklesCurrentFrame == 75) && _shouldTalk) + reset_frame = 60; + + if ((reset_frame >= 0) && (reset_frame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(reset_frame); + _twinklesCurrentFrame = reset_frame; + } + } + + if (_game._trigger == 70) + _shouldTalk = false; + } + + if ((_twinkleAnimationType == 1) && (_scene->_rails.getNext() > 0)) { + _game._player.walk(Common::Point(214, 150), FACING_NORTHWEST); + _scene->_rails.resetNext(); + _stopWalking = true; + } +} + +void Scene210::preActions() { + _stopWalking = false; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_EAST)) + _game._player._walkOffScreenSceneId = 211; +} + +void Scene210::actions() { + if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_HUT_TO_NORTH)) { + _vm->_dialogs->show(21017); + } else if (_game._screenObjects._inputMode == 1) { + handleConversations(); + } else if (_action.isAction(VERB_TALKTO, NOUN_NATIVE_WOMAN) || + ((_game._player._playerPos == Common::Point(214, 150)) && (_game._player._facing == FACING_NORTHWEST) && (_twinkleAnimationType == 1) && _stopWalking)) { + switch (_game._trigger) { + case 0: { + _game._player._stepEnabled = false; + int quote; + if (_globals[kTwinklesApproached] == 0) + quote = 90; + else if (_globals[kTwinklesApproached] == 1) + quote = 115; + else + quote = 171; + + _shouldFaceRex = true; + _nextHandsPlace = 0; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.addQuote(quote, 1, 120); + } + break; + + case 1: + _shouldTalk = true; + if (!_twinklesTalking) { + _scene->_sequences.addTimer(6, 1); + } else { + if (_globals[kTwinklesApproached] == 0) { + handleTwinklesSpeech(0xAF, -1, 0); + handleTwinklesSpeech(0xB0, 0, 0); + } else if (_globals[kTwinklesApproached] == 1) { + handleTwinklesSpeech(0xB1, 0, 0); + } else { + int quote = _twinklesTalk2 ? 0xB3 : 0xB2; + _twinklesTalk2 = true; + handleTwinklesSpeech(quote, 0, 0); + } + _scene->_sequences.addTimer(60, 3); + } + break; + + case 3: + _game._player._stepEnabled = true; + _shouldMoveHead = false; + _shouldTalk = false; + + if (_globals[kTwinklesApproached] < 2) + _globals[kTwinklesApproached]++; + + _conv1.start(); + _curDialogNode = 1; + break; + } + } else if (_action.isAction(VERB_GIVE, NOUN_NATIVE_WOMAN) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) { + switch (_game._trigger) { + case 0: { + int quote = _vm->getRandomNumber(172, 174); + _shouldMoveHead = true; + _game._player._stepEnabled = false; + handleTwinklesSpeech(quote, 0, 120); + _scene->_sequences.addTimer(120, 1); + } + break; + + case 1: + _game._player._stepEnabled = true; + _shouldMoveHead = false; + break; + } + } else if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_NORTH) || _action.isAction(VERB_WALK_TOWARDS, NOUN_HUT_TO_NORTH)) { + _scene->_nextSceneId = 205; + } else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY)) { + _scene->_nextSceneId = 215; + } else if ((_action.isAction(VERB_PULL, NOUN_CURTAIN) || _action.isAction(VERB_OPEN, NOUN_CURTAIN)) && !_globals[kCurtainOpen]) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[1], false, 12, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: + _game._player._stepEnabled = true; + _globals[kCurtainOpen] = true; + _doorway = _scene->_dynamicHotspots.add(112, 395, -1, Common::Rect(163, 87, 163 + 19, 87 + 36)); + _scene->_dynamicHotspots.setPosition(_doorway, Common::Point(168, 127), FACING_NORTH); + _scene->_dynamicHotspots.setCursor(_doorway, CURSOR_GO_UP); + break; + } + } else if ((_action.isAction(VERB_PULL, NOUN_CURTAIN) || _action.isAction(VERB_CLOSE, NOUN_CURTAIN)) && _globals[kCurtainOpen]) { + switch (_game._trigger) { + case 0: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _game._player._stepEnabled = false; + _game._player._facing = FACING_NORTH; + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 12, 0, 0, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _game._player._stepEnabled = false; + break; + case 1: + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); + _scene->_sequences.addTimer(48, 2); + break; + case 2: + _scene->_dynamicHotspots.remove(_doorway); + _game._player._stepEnabled = true; + _globals[kCurtainOpen] = false; + break; + } + } else if (_action.isAction(VERB_LOOK, NOUN_HUT)) { + if (_globals[kTwinklesStatus] == TWINKLES_GONE) { + if (_game._storyMode == STORYMODE_NAUGHTY) + _vm->_dialogs->show(21003); + else + _vm->_dialogs->show(21002); + } else { + _vm->_dialogs->show(21001); + } + } else if (_action.isAction(VERB_LOOK, NOUN_BRA)) { + _vm->_dialogs->show(21004); + } else if (_action.isAction(VERB_LOOK, NOUN_HOTPANTS)) { + _vm->_dialogs->show(21005); + } else if (_action.isAction(VERB_TAKE, NOUN_HOTPANTS) || _action.isAction(VERB_TAKE, NOUN_BRA)) { + _vm->_dialogs->show(21006); + } else if (_action.isAction(VERB_LOOK, NOUN_STREAM)) { + _vm->_dialogs->show(21007); + } else if (_action.isAction(VERB_LOOK, NOUN_BUSHY_FERN)) { + _vm->_dialogs->show(21008); + } else if (_action.isAction(VERB_LOOK, NOUN_VILLAGE_PATH)) { + _vm->_dialogs->show(21009); + } else if (_action.isAction(VERB_LOOK, NOUN_NATIVE_WOMAN)) { + _vm->_dialogs->show(21010); + } else if (_action.isAction(VERB_SHOOT, NOUN_NATIVE_WOMAN) || _action.isAction(VERB_HOSE_DOWN, NOUN_NATIVE_WOMAN)) { + _vm->_dialogs->show(21011); + } else if (_action.isAction(VERB_LOOK, NOUN_PATH_TO_NORTH)) { + _vm->_dialogs->show(21012); + } else if (_action.isAction(VERB_LOOK, NOUN_CURTAIN)) { + _vm->_dialogs->show(21013); + } else if (_action.isAction(VERB_LOOK, NOUN_CLOTHESLINE)) { + _vm->_dialogs->show(21014); + } else if (_action.isAction(VERB_TAKE, NOUN_CLOTHESLINE)) { + _vm->_dialogs->show(21015); + } else if (_action.isAction(VERB_LOOK, NOUN_HUT_TO_NORTH)) { + _vm->_dialogs->show(21016); + } else { + // Not handled + return; + } + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene211::Scene211(MADSEngine *vm) : Scene2xx(vm) { + _ambushFl = false; + _wakeFl = false; + _monkeyFrame = 0; + _scrollY = 0; + _monkeyTime = 0; +} + +void Scene211::synchronize(Common::Serializer &s) { + Scene2xx::synchronize(s); + + s.syncAsByte(_ambushFl); + s.syncAsByte(_wakeFl); + + s.syncAsSint32LE(_monkeyFrame); + s.syncAsSint32LE(_scrollY); + s.syncAsUint32LE(_monkeyTime); +} + +void Scene211::setup() { + setPlayerSpritesPrefix(); + setAAName(); + + _scene->addActiveVocab(NOUN_SLITHERING_SNAKE); +} + +void Scene211::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*SC002Z2"); + _wakeFl = false; + + if (_scene->_priorSceneId == 210) + _game._player._playerPos = Common::Point(25, 148); + else if (_scene->_priorSceneId == 205) { + _game._player._playerPos = Common::Point(49, 133); + _game._player._facing = FACING_WEST; + _wakeFl = true; + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->loadAnimation(formAnimName('A', -1), 100); + _scene->_activeAnimation->setCurrentFrame(169); + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(310, 31); + _game._player._facing = FACING_SOUTHWEST; + } + + if (_vm->getRandomNumber(1, 8) == 1) { + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(202, 126)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 8); + _scene->_sequences.setMotion(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, -200, 0); + _scene->_dynamicHotspots.add(324, 13, _globals._sequenceIndexes[2], Common::Rect(1, 1, 1 + 41, 1 + 10)); + } + + if (_scene->_roomChanged) + _game._objects.addToInventory(OBJ_BINOCULARS); + + _vm->_palette->setEntry(252, 63, 44, 30); + _vm->_palette->setEntry(253, 63, 20, 22); + _game.loadQuoteSet(0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 1, 0); + + if (_globals[kMonkeyStatus] == MONKEY_AMBUSH_READY) + _scene->_kernelMessages.initRandomMessages(2, + Common::Rect(0, 0, 54, 30), 13, 2, 0xFDFC, 60, + 151, 152, 153, 154, 0); + + _monkeyTime = _vm->_game->_scene._frameStartTime; + _scrollY = 30; + + _ambushFl = false; + _monkeyFrame = 0; + + sceneEntrySound(); +} + +void Scene211::step() { + if (_globals[kMonkeyStatus] == MONKEY_AMBUSH_READY) { + _scene->_kernelMessages.randomServer(); + + if (!_ambushFl && !_wakeFl && (_vm->_game->_scene._frameStartTime >= _monkeyTime)) { + int chanceMinor = _scene->_kernelMessages.checkRandom() * 4 + 1; + if (_scene->_kernelMessages.generateRandom(80, chanceMinor)) + _vm->_sound->command(18); + + _monkeyTime = _vm->_game->_scene._frameStartTime + 2; + } + + if ((_game._player._playerPos == Common::Point(52, 132)) && (_game._player._facing == FACING_WEST) && !_game._player._moving && + (_game._trigger || !_ambushFl)) { + switch (_game._trigger) { + case 0: + if (_game._objects.isInInventory(OBJ_BINOCULARS)) { + _ambushFl = true; + _monkeyFrame = 0; + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_kernelMessages.reset(); + _scene->loadAnimation(formAnimName('A', -1), 90); + _vm->_sound->command(19); + int count = (int)_game._objects._inventoryList.size(); + for (int idx = 0; idx < count; idx++) { + if ((_game._objects._inventoryList[idx] == OBJ_BINOCULARS) && (_scene->_userInterface._selectedInvIndex != idx)) + _scene->_userInterface.selectObject(idx); + } + } + break; + + case 90: + _vm->_sound->command(10); + _game._player._stepEnabled = true; + _game._player._visible = true; + _game._player._playerPos = Common::Point(49, 133); + _ambushFl = false; + _globals[kMonkeyStatus] = MONKEY_HAS_BINOCULARS; + break; + } + } + } + + if (_ambushFl && (_scene->_activeAnimation->getCurrentFrame() > _monkeyFrame)) { + _monkeyFrame = _scene->_activeAnimation->getCurrentFrame(); + switch (_monkeyFrame) { + case 2: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(12, 4), 0xFDFC, 0, 0, 60, _game.getQuote(157)); + _scene->_kernelMessages.setQuoted(msgIndex, 2, true); + } + break; + + case 12: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(35, 20), 0xFDFC, 0, 0, 60, _game.getQuote(155)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + } + break; + + case 42: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(60, 45), 0xFDFC, 0, 0, 60, _game.getQuote(156)); + _scene->_kernelMessages.setQuoted(msgIndex, 6, true); + } + break; + + case 73: + _scene->_kernelMessages.add(Common::Point(102, 95), 0xFDFC, 32, 0, 75, _game.getQuote(157)); + break; + + case 90: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(102, 95), 0xFDFC, 32, 0, 60, _game.getQuote(158)); + _scene->_kernelMessages.setQuoted(msgIndex, 6, true); + } + break; + + case 97: + _scene->_userInterface.selectObject(-1); + _game._objects.removeFromInventory(OBJ_BINOCULARS, 1); + break; + + case 177: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(161)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + _scrollY += 14; + } + break; + + case 181: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(162)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + _scrollY += 14; + } + break; + + case 188: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(163)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + _scrollY += 14; + } + break; + + case 200: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(164)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + _scrollY += 14; + } + break; + } + } + + if (_wakeFl) { + if (_game._trigger == 100) { + _game._player._visible = true; + _game._player._stepEnabled = true; + _wakeFl = false; + } + + if (_scene->_activeAnimation->getCurrentFrame() > _monkeyFrame) { + _monkeyFrame = _scene->_activeAnimation->getCurrentFrame(); + switch (_scene->_activeAnimation->getCurrentFrame()) { + case 177: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(165)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + _scrollY += 14; + } + break; + + case 181: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(166)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + _scrollY += 14; + } + break; + + case 188: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(167)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + _scrollY += 14; + } + break; + + case 200: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(168)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + _scrollY += 14; + } + break; + } + } + } +} + +void Scene211::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_JUNGLE_PATH) && _game._objects.isInInventory(OBJ_BINOCULARS) && (_globals[kMonkeyStatus] == MONKEY_AMBUSH_READY) + && (_scene->_customDest.x <= 52) && (_scene->_customDest.y >= 132)) + _game._player.walk(Common::Point(52, 132), FACING_WEST); + + if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_WEST)) { + if (_game._objects.isInInventory(OBJ_BINOCULARS) && (_globals[kMonkeyStatus] == MONKEY_AMBUSH_READY)) + _game._player.walk(Common::Point(52, 132), FACING_WEST); + else + _game._player._walkOffScreenSceneId = 210; + } + + if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_NORTHEAST)) + _game._player._walkOffScreenSceneId = 207; +} + +void Scene211::actions() { + if (_action._lookFlag && (_globals[kMonkeyStatus] == MONKEY_AMBUSH_READY)) + _vm->_dialogs->show(21111); + else if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_PALM_TREE)) + _vm->_dialogs->show(21116); + else if (_action.isAction(VERB_LOOK, NOUN_BUSHY_FERN)) + _vm->_dialogs->show(21101); + else if (_action.isAction(VERB_LOOK, NOUN_JUNGLE_PATH)) + _vm->_dialogs->show(21102); + else if (_action.isAction(VERB_LOOK, NOUN_PALM_TREE)) { + if (_globals[kMonkeyStatus] == MONKEY_AMBUSH_READY) { + if (_game._storyMode == STORYMODE_NAUGHTY) + _vm->_dialogs->show(21103); + else + _vm->_dialogs->show(21104); + } else { + _vm->_dialogs->show(21105); + } + } else if (_action.isAction(VERB_LOOK, NOUN_THICK_UNDERGROWTH)) { + if (_game._storyMode == STORYMODE_NAUGHTY) + _vm->_dialogs->show(21106); + else + _vm->_dialogs->show(21107); + } else if (_action.isAction(VERB_LOOK, NOUN_JUNGLE)) + _vm->_dialogs->show(21108); + else if (_action.isAction(VERB_LOOK, NOUN_PATH_TO_NORTHEAST)) + _vm->_dialogs->show(21109); + else if (_action.isAction(VERB_LOOK, NOUN_PATH_TO_WEST)) + _vm->_dialogs->show(21110); + else if (_action.isAction(VERB_LOOK, NOUN_SLITHERING_SNAKE)) + _vm->_dialogs->show(21113); + else if (_action.isAction(VERB_TAKE, NOUN_SLITHERING_SNAKE)) + _vm->_dialogs->show(21114); + else if (_action.isAction(VERB_LOOK, NOUN_ROCKS)) + _vm->_dialogs->show(21115); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene212::setup() { + setPlayerSpritesPrefix(); + setAAName(); + + _scene->addActiveVocab(NOUN_BOUNCING_REPTILE); +} + +void Scene212::enter() { + // CHECKME: Some useless variables have been remove here + + if (_scene->_priorSceneId == 208) { + _game._player._playerPos = Common::Point(195, 85); + _game._player._facing = FACING_SOUTH; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(67, 117); + _game._player._facing = FACING_NORTHEAST; + } + + sceneEntrySound(); +} + +void Scene212::step() { +// CHECKME: Could we move the dino? +} + +void Scene212::preActions() { + if (_action.isAction(VERB_WALK_THROUGH, NOUN_CAVE_ENTRANCE)) + _game._player._walkOffScreenSceneId = 111; +} + +void Scene212::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(21209); + else if (_action.isAction(VERB_WALK_TOWARDS) && (_action.isObject(NOUN_FIELD_TO_NORTH) || _action.isObject(NOUN_MOUNTAINS))) + _scene->_nextSceneId = 208; + else if (_action.isAction(VERB_WALK_TOWARDS, NOUN_CAVE)) + _scene->_nextSceneId = 111; + else if (_action.isAction(VERB_LOOK, NOUN_GRASS)) + _vm->_dialogs->show(21201); + else if (_action.isAction(VERB_LOOK, NOUN_ROCKS)) + _vm->_dialogs->show(21202); + else if (_action.isAction(VERB_LOOK, NOUN_CAVE_ENTRANCE)) + _vm->_dialogs->show(21203); + else if (_action.isAction(VERB_LOOK, NOUN_SKY)) + _vm->_dialogs->show(21204); + else if (_action.isAction(VERB_LOOK, NOUN_FIELD_TO_NORTH)) + _vm->_dialogs->show(21205); + else if (_action.isAction(VERB_LOOK, NOUN_TREES)) + _vm->_dialogs->show(21206); + else if (_action.isAction(VERB_LOOK, NOUN_PLANTS)) + _vm->_dialogs->show(21207); + else if (_action.isAction(VERB_LOOK, NOUN_MOUNTAINS)) + _vm->_dialogs->show(21208); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene213::setup() { + _game._player._spritesPrefix = ""; + + // The original is calling Scene2xx::setAAName() + _game._aaName = Resources::formatAAName(2); +} + +void Scene213::enter() { + if (_globals[kMeteorologistWatch] != METEOROLOGIST_NORMAL) + _handSpriteId = _scene->_sprites.addSprites("*METHAND"); + else if (_globals[kSexOfRex] == REX_MALE) + _handSpriteId = _scene->_sprites.addSprites("*REXHAND"); + else + _handSpriteId = _scene->_sprites.addSprites("*ROXHAND"); + + teleporterEnter(); + + // The original is calling Scene2xx::sceneEntrySound() + if (_vm->_musicFlag) { + if (_globals[kMeteorologistWatch] == METEOROLOGIST_NORMAL) + _vm->_sound->command(1); + else + _vm->_sound->command(9); + } else { + _vm->_sound->command(2); + } +} + +void Scene213::step() { + teleporterStep(); +} + +void Scene213::actions() { + if (teleporterActions()) { + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_CONTROL_PANEL)) + _vm->_dialogs->show(21301); + else if (_action.isAction(VERB_LOOK, NOUN_KEYPAD) || _action.isAction (VERB_INSPECT, NOUN_KEYPAD)) + _vm->_dialogs->show(21302); + else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY)) + _vm->_dialogs->show(21303); + else if (_action.isAction(VERB_LOOK, NOUN_VIEWPORT) || _action.isAction(VERB_PEER_THROUGH, NOUN_VIEWPORT)) + _vm->_dialogs->show(21304); + else if (_action.isAction(VERB_LOOK, NOUN_DEVICE)) + _vm->_dialogs->show(21305); + else if (_action.isAction(VERB_LOOK, NOUN_0_KEY) || _action.isAction(VERB_LOOK, NOUN_1_KEY) + || _action.isAction(VERB_LOOK, NOUN_2_KEY) || _action.isAction(VERB_LOOK, NOUN_3_KEY) + || _action.isAction(VERB_LOOK, NOUN_4_KEY) || _action.isAction(VERB_LOOK, NOUN_5_KEY) + || _action.isAction(VERB_LOOK, NOUN_6_KEY) || _action.isAction(VERB_LOOK, NOUN_7_KEY) + || _action.isAction(VERB_LOOK, NOUN_8_KEY) || _action.isAction(VERB_LOOK, NOUN_9_KEY) + || _action.isAction(VERB_LOOK, NOUN_SMILE_KEY) || _action.isAction(VERB_LOOK, NOUN_FROWN_KEY) + || _action.isAction(VERB_LOOK, NOUN_ENTER_KEY)) + _vm->_dialogs->show(21306); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene214::Scene214(MADSEngine *vm) : Scene2xx(vm) { + _devilTime = 0; + _devilRunningFl = false; +} + +void Scene214::synchronize(Common::Serializer &s) { + Scene2xx::synchronize(s); + + s.syncAsUint32LE(_devilTime); + s.syncAsByte(_devilRunningFl); +} + +void Scene214::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_CAPTIVE_CREATURE); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene214::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('e', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('e', 1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('t', -1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXMRD_7"); + + _devilTime = _game._player._priorTimer; + _devilRunningFl = false; + + if (_game._objects.isInRoom(OBJ_POISON_DARTS)) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(103, 86)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 11); + } else { + _scene->_hotspots.activate(NOUN_POISON_DARTS, false); + } + + if (_game._objects.isInRoom(OBJ_BLOWGUN)) { + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(90, 87)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 13); + } else { + _scene->_hotspots.activate(NOUN_BLOWGUN, false); + } + + if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(191, 152); + + sceneEntrySound(); +} + +void Scene214::step() { + if ((_game._player._priorTimer - _devilTime > 800) && !_devilRunningFl) { + _devilRunningFl = true; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 1, 6, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 2); + _scene->_dynamicHotspots.add(451, 13, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + } + + if (_devilRunningFl) { + switch (_game._trigger) { + case 71: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 5, 0, 0); + _scene->_sequences.updateTimeout(oldIdx, _globals._sequenceIndexes[3]); + _scene->_dynamicHotspots.add(451, VERB_WALKTO, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 5, 8); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + } + break; + + case 72: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); + _scene->_sequences.updateTimeout(oldIdx, _globals._sequenceIndexes[3]); + _scene->_dynamicHotspots.add(451, VERB_WALKTO, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 9, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 2); + _devilTime = _game._player._priorTimer; + _devilRunningFl = false; + } + break; + } + } +} + +void Scene214::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(21427); + else if (_action.isAction(VERB_WALK_OUTSIDE, NOUN_HUT)) + _scene->_nextSceneId = 207; + else if (_action.isAction(VERB_TAKE, NOUN_POISON_DARTS) && (_game._trigger || _game._objects.isInRoom(OBJ_POISON_DARTS))) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], true, 6, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: + _globals._sequenceIndexes[4] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[4], true, 6, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _game._objects.addToInventory(OBJ_POISON_DARTS); + _scene->_hotspots.activate(NOUN_POISON_DARTS, false); + break; + + case 2: + _game._player._visible = true; + _scene->_sequences.addTimer(48, 3); + break; + + case 3: + _game._player._stepEnabled = true; + _vm->_dialogs->showItem(OBJ_POISON_DARTS, 0x53A5); + break; + } + } else if (_action.isAction(VERB_TAKE, NOUN_BLOWGUN) && (_game._trigger || _game._objects.isInRoom(OBJ_BLOWGUN))) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: + _globals._sequenceIndexes[4] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[4], false, 6, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _game._objects.addToInventory(OBJ_BLOWGUN); + _scene->_hotspots.activate(NOUN_BLOWGUN, false); + break; + + case 2: + _game._player._visible = true; + _scene->_sequences.addTimer(48, 3); + break; + + case 3: + _game._player._stepEnabled = true; + _vm->_dialogs->showItem(OBJ_BLOWGUN, 0x329); + break; + } + } else if (_action.isAction(VERB_LOOK, NOUN_WINDOW)) + _vm->_dialogs->show(21401); + else if (_action.isAction(VERB_LOOK, NOUN_EXPERIMENT_CAGE)) + _vm->_dialogs->show(21402); + else if (_action.isAction(VERB_LOOK, NOUN_CAPTIVE_CREATURE)) + _vm->_dialogs->show(21403); + else if (_action.isAction(VERB_LOOK, NOUN_BEAR_RUG)) + _vm->_dialogs->show(21404); + else if (_action.isAction(VERB_LOOK, NOUN_TROPHY)) + _vm->_dialogs->show(21405); + else if (_action.isAction(VERB_LOOK, NOUN_LARGE_BOWL)) { + if (_game._storyMode == STORYMODE_NAUGHTY) { + _vm->_dialogs->show(21406); + } else { + _vm->_dialogs->show(21407); + } + } else if (_action.isAction(VERB_LOOK, NOUN_SPECIMEN_JARS)) + _vm->_dialogs->show(21408); + else if (_action.isAction(VERB_TAKE, NOUN_LARGE_BOWL) || _action.isAction(VERB_TAKE, NOUN_SPECIMEN_JARS)) + _vm->_dialogs->show(21409); + else if (_action.isAction(VERB_LOOK, NOUN_SHRUNKEN_HEADS)) + _vm->_dialogs->show(21410); + else if (_action.isAction(VERB_TAKE, NOUN_SHRUNKEN_HEADS) || _action.isAction(VERB_TAKE, NOUN_LARGE_HEADS)) + _vm->_dialogs->show(21411); + else if (_action.isAction(VERB_LOOK, NOUN_LARGE_HEADS)) + _vm->_dialogs->show(21428); + else if (_action.isAction(VERB_LOOK, NOUN_POISON_DARTS) && (_action._savedFields._mainObjectSource == 4)) + _vm->_dialogs->show(21412); + else if (_action.isAction(VERB_OPEN, NOUN_EXPERIMENT_CAGE)) + _vm->_dialogs->show(21414); + else if (_action.isAction(VERB_TALKTO, NOUN_CAPTIVE_CREATURE)) + _vm->_dialogs->show(21415); + else if (_action.isAction(VERB_GIVE, NOUN_TWINKIFRUIT, NOUN_CAPTIVE_CREATURE)) + _vm->_dialogs->show(21416); + else if (_action.isAction(VERB_SHOOT, NOUN_BLOWGUN, NOUN_CAPTIVE_CREATURE) || _action.isAction(VERB_HOSE_DOWN, NOUN_BLOWGUN, NOUN_CAPTIVE_CREATURE)) + _vm->_dialogs->show(21417); + else if (_action.isAction(VERB_LOOK, NOUN_BIG_HEADS)) + _vm->_dialogs->show(21418); + else if (_action.isAction(VERB_TAKE, NOUN_BIG_HEADS)) + _vm->_dialogs->show(21419); + else if (_action.isAction(VERB_TAKE, NOUN_BEAR_RUG)) + _vm->_dialogs->show(21420); + else if (_action.isAction(VERB_LOOK, NOUN_FLOOR_OF_HUT)) + _vm->_dialogs->show(21421); + else if (_action.isAction(VERB_LOOK, NOUN_BLOWGUN)) + _vm->_dialogs->show(21422); + else if (_action.isAction(VERB_LOOK, NOUN_TABLE)) { + if (_game._objects.isInRoom(OBJ_POISON_DARTS) && _game._objects.isInRoom(OBJ_BLOWGUN)) { + _vm->_dialogs->show(21423); + } else if (_game._objects.isInRoom(OBJ_POISON_DARTS) && !_game._objects.isInRoom(OBJ_BLOWGUN)) { + _vm->_dialogs->show(21424); + } else if (!_game._objects.isInRoom(OBJ_POISON_DARTS) && _game._objects.isInRoom(OBJ_BLOWGUN)) { + _vm->_dialogs->show(21425); + } else { + _vm->_dialogs->show(21426); + } + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene215::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene215::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('e', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 0)); + + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle (_globals._spriteIndexes[1], false, 7, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(235, 83)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + + if (_globals[kSexOfRex] == REX_MALE) + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMRC_9"); + else + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*ROXRC_9"); + + if (_scene->_priorSceneId == 216) { + _game._player._playerPos = Common::Point(140, 119); + _game._player._facing = FACING_SOUTHWEST; + _game._player._visible = false; + _game._player._stepEnabled = false; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.addTimer(120, 70); + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(204, 152); + _game._player._facing = FACING_NORTH; + } + + _game.loadQuoteSet(0xA9, 0xAA, 0); + sceneEntrySound(); +} + +void Scene215::step() { + if (_game._trigger == 70) { + _scene->_sequences.remove (_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + } + + if (_game._trigger == 71) { + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]); + _game._player._visible = true; + _game._player._stepEnabled = true; + } +} + +void Scene215::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(21509); + else if (_action.isAction(VERB_TAKE, NOUN_TWINKIFRUIT)) { + if (!_game._objects.isInInventory(OBJ_TWINKIFRUIT) || _game._trigger) { + switch (_game._trigger) { + case 0: + if (_globals[kSexOfRex] == REX_MALE) { + _game._player._visible = false; + _game._player._stepEnabled = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 4); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_LOOP, 0, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } else { + _game._objects.addToInventory(OBJ_TWINKIFRUIT); + _vm->_dialogs->showItem(OBJ_TWINKIFRUIT, 0x5404); + } + break; + + case 1: + if (!_game._objects.isInInventory(OBJ_TWINKIFRUIT)) { + _game._objects.addToInventory(OBJ_TWINKIFRUIT); + _vm->_dialogs->showItem(OBJ_TWINKIFRUIT, 0x5404); + } + break; + + case 2: + _game._player._visible = true; + _game._player._stepEnabled = true; + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + break; + } + } else { + int idx = _vm->getRandomNumber(169, 170); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(idx)); + } + } else if (_action.isAction(VERB_WALK_OUTSIDE, NOUN_HUT)) + _scene->_nextSceneId = 210; + else if (_action.isAction(VERB_LOOK, NOUN_BEAR_RUG)) + _vm->_dialogs->show(21501); + else if (_action.isAction(VERB_LOOK, NOUN_BED)) + _vm->_dialogs->show(21502); + else if (_action.isAction(VERB_LOOK, NOUN_WELCOME_MAT)) + _vm->_dialogs->show(21503); + else if (_action.isAction(VERB_LOOK, NOUN_LOVE_ALTAR)) + _vm->_dialogs->show(21504); + else if (_action.isAction(VERB_LOOK, NOUN_WINDOW)) + _vm->_dialogs->show(21505); + else if (_action.isAction(VERB_LOOK, NOUN_PICTURE)) + _vm->_dialogs->show(21506); + else if (_action.isAction(VERB_LOOK, NOUN_TWINKIFRUIT) && (_action._savedFields._mainObjectSource == 4)) + _vm->_dialogs->show(21507); + else if (_action.isAction(VERB_TAKE, NOUN_BEAR_RUG)) + _vm->_dialogs->show(21510); + else if (_action.isAction(VERB_TAKE, NOUN_LOVE_ALTAR)) + _vm->_dialogs->show(21511); + else if (_action.isAction(VERB_LOOK, NOUN_BAG_OF_TWINKIFRUITS)) + _vm->_dialogs->show(21512); + else if (_action.isAction(VERB_TAKE, NOUN_BAG_OF_TWINKIFRUITS)) + _vm->_dialogs->show(21513); + else if (_action.isAction(VERB_TAKE, NOUN_WELCOME_MAT)) + _vm->_dialogs->show(21514); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene216::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene216::enter() { + _game._player._stepEnabled = false; + _game._player._visible = false; + + _scene->_userInterface.emptyConversationList(); + _scene->_userInterface.setup(kInputConversation); + _scene->loadAnimation(formAnimName('A', -1), 60); + + sceneEntrySound(); +} + +void Scene216::step() { + if (_game._trigger == 60) + _scene->_nextSceneId = 215; +} + +/*------------------------------------------------------------------------*/ + +} // End of namespace Nebular +} // End of namespace MADS diff --git a/engines/mads/nebular/nebular_scenes2.h b/engines/mads/nebular/nebular_scenes2.h new file mode 100644 index 0000000000..c860db9470 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes2.h @@ -0,0 +1,325 @@ +/* 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. + * + */ + +#ifndef MADS_NEBULAR_SCENES2_H +#define MADS_NEBULAR_SCENES2_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" + +namespace MADS { + +namespace Nebular { + +class Scene2xx : public NebularScene { +protected: + /** + * Plays an appropriate sound when entering a scene + */ + void setAAName(); + + /** + * Updates the prefix used for getting player sprites for the scene + */ + void setPlayerSpritesPrefix(); + + void sceneEntrySound(); +public: + Scene2xx(MADSEngine *vm) : NebularScene(vm) {} +}; + +class Scene201 : public Scene2xx { +private: + bool _pterodactylFlag; + +public: + Scene201(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene202 : public Scene2xx { +private: + bool _activeMsgFl, _ladderTopFl, _waitingMeteoFl, _toStationFl, _toTeleportFl; + int _ladderHotspotId, _lastRoute, _stationCounter, _meteoFrame; + uint32 _meteoClock1, _meteoClock2, _startTime; + bool _meteorologistSpecial; + + int subStep1(int randVal); + int subStep2(int randVal); + int subStep3(int randVal); + int subStep4(int randVal); + +public: + Scene202(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); + + void setRandomKernelMessage(); +}; + +class Scene203 : public Scene2xx { +private: + bool _rhotundaEat2Fl, _rhotundaEatFl; + +public: + Scene203(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene205 : public Scene2xx { +private: + uint32 _lastFishTime, _chickenTime; + bool _beingKicked; + int _kernelMessage; + Conversation _dialog1; + + void handleWomanSpeech(int quoteId); + +public: + Scene205(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene207 : public Scene2xx { +private: + bool _vultureFl, _spiderFl, _eyeFl; + int _spiderHotspotId, _vultureHotspotId; + int32 _spiderTime, _vultureTime; + + void moveVulture(); + void moveSpider(); + +public: + Scene207(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene208 : public Scene2xx { +private: + bool _rhotundaTurnFl, _boundingFl; + int32 _rhotundaTime; + + void updateTrap(); + void subAction(int mode); + +public: + Scene208(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene209 : public Scene2xx { +private: + bool _dodgeFl, _forceDodgeFl, _shouldDodgeFl; + bool _pitchFl; + bool _fallFl, _forceFallFl, _shouldFallFl; + bool _playingAnimFl, _playingDialogFl; + int _pauseMode, _pauseCounterThreshold, _pauseCounter; + bool _removeMonkeyFl; + int _monkeyPosition; + bool _shootReadyFl, _startShootingInTimerFl, _shootMissedLastFl; + bool _binocularsDroppedFl; + int _dialogAbortVal; + int _counter; + + void handlePause(); + void initPauseCounterThreshold(); + void handlePeek(); + void handleVerticalMove(); + void handleLookStay(); + void handleLookRight(); + void handleBlink(); + void handleGetBinoculars(); + void handleStandFromPeek(); + void handleDodge(); + void handleBinocularBlink(); + void handleBinocularScan(); + void handleJumpInTree(); + void handleTongue(); + void handleMonkeyFall(); + void handleJumpAndHide(); + void handleMonkeyEating(); + void handleMonkey1(); + void handleStandBlink(); + void handleMonkey2(); + +public: + Scene209(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene210 : public Scene2xx { +private: + int _curDialogNode; + int _nextHandsPlace; + int _twinkleAnimationType; + int _twinklesCurrentFrame; + bool _shouldTalk, _shouldFaceRex, _shouldMoveHead; + bool _stopWalking; + bool _twinklesTalking; + bool _twinklesTalk2; + int _doorway; + Common::String _subQuote2; + Conversation _conv1, _conv2, _conv3; + Conversation _conv5, _conv6, _conv7, _conv8; + + void handleConversations(); + void handleConversation1(); + void handleConversation2(); + void handleConversation3(); + void handleConversation5(); + void handleConversation6(); + void handleConversation7(); + void handleConversation8(); + void setDialogNode(int node); + void handleTwinklesSpeech(int quoteId, int shiftX, uint32 delay); + void newNode(int node); + void restoreDialogNode(int node, int msgId, int posY); + +public: + Scene210(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene211 : public Scene2xx { +private: + bool _ambushFl, _wakeFl; + int _monkeyFrame, _scrollY; + uint32 _monkeyTime; + +public: + Scene211(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene212 : public Scene2xx { +public: + Scene212(MADSEngine *vm) : Scene2xx(vm) {} + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene213 : public SceneTeleporter { +public: + Scene213(MADSEngine *vm) : SceneTeleporter(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene214 : public Scene2xx { +private: + uint32 _devilTime; + bool _devilRunningFl; + +public: + Scene214(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene215 : public Scene2xx { +public: + Scene215(MADSEngine *vm) : Scene2xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene216 : public Scene2xx { +public: + Scene216(MADSEngine *vm) : Scene2xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions() {}; +}; + +} // End of namespace Nebular + +} // End of namespace MADS + +#endif /* MADS_NEBULAR_SCENES2_H */ diff --git a/engines/mads/nebular/nebular_scenes3.cpp b/engines/mads/nebular/nebular_scenes3.cpp new file mode 100644 index 0000000000..a963484bd0 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes3.cpp @@ -0,0 +1,5818 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "mads/mads.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/nebular/nebular_scenes3.h" + +namespace MADS { + +namespace Nebular { + +void Scene3xx::setAAName() { + _game._aaName = Resources::formatAAName(4); +} + +void Scene3xx::setPlayerSpritesPrefix() { + _vm->_sound->command(5); + + Common::String oldName = _game._player._spritesPrefix; + + if (_globals[kSexOfRex] == REX_MALE) + _game._player._spritesPrefix = "RXM"; + else + _game._player._spritesPrefix = "ROX"; + + if ((_scene->_nextSceneId == 313) || (_scene->_nextSceneId == 366) + || ((_scene->_nextSceneId >= 301) && (_scene->_nextSceneId <= 303)) + || ((_scene->_nextSceneId == 304) && (_scene->_currentSceneId == 303)) + || ((_scene->_nextSceneId == 311) && (_scene->_currentSceneId == 304)) + || ((_scene->_nextSceneId >= 308) && (_scene->_nextSceneId <= 310)) + || ((_scene->_nextSceneId >= 319) && (_scene->_nextSceneId <= 322)) + || ((_scene->_nextSceneId >= 387) && (_scene->_nextSceneId <= 391))) { + _game._player._spritesPrefix = ""; + _game._player._spritesChanged = true; + } + + _game._player._scalingVelocity = true; + if (oldName != _game._player._spritesPrefix) + _game._player._spritesChanged = true; + + _vm->_palette->setEntry(16, 10, 63, 63); + _vm->_palette->setEntry(17, 10, 45, 45); +} + +void Scene3xx::sceneEntrySound() { + if (!_vm->_musicFlag) { + _vm->_sound->command(2); + return; + } + + switch (_scene->_nextSceneId) { + case 301: + case 302: + case 303: + case 304: + case 308: + case 309: + case 310: + _vm->_sound->command(11); + break; + + case 311: + if (_scene->_priorSceneId == 304) + _vm->_sound->command(11); + else + _vm->_sound->command(10); + break; + + case 313: + case 316: + case 320: + case 322: + case 357: + case 358: + case 359: + case 360: + case 361: + case 387: + case 388: + case 389: + case 390: + case 391: + case 399: + _vm->_sound->command(10); + break; + + case 318: + if ((_scene->_priorSceneId == 357) || (_scene->_priorSceneId == 407)) + _vm->_sound->command(10); + else if (_scene->_priorSceneId == 319) + _vm->_sound->command(16); + else + _vm->_sound->command(3); + + _vm->_sound->command(50); + break; + + case 319: + _vm->_sound->command(16); + break; + + case 321: + _vm->_sound->command(18); + break; + + default: + break; + } +} + +void Scene3xx::initForceField(ForceField *force, bool flag) { + force->_flag = flag; + force->_vertical = 0; + force->_horizontal = 0; + force->_timer = 0; + + for (int count = 0; count < 40; count++) + force->_seqId[count] = -1; + + if (force->_flag) + _vm->_sound->command(24); +} + +int Scene3xx::computeScale(int low, int high, int id) { + int diff = high - (low + 2); + int quotient = diff / 20; + int remainder = diff % 20; + int value = low + 2 + (quotient * id) + (remainder / (id + 1)); + + return (value); +} + +void Scene3xx::handleForceField(ForceField *force, int *sprites) { + if (_game._trigger >= 150) { + int id = _game._trigger - 150; + if (id < 40) { + if (id < 20) + force->_vertical--; + else + force->_horizontal--; + + force->_seqId[id] = -1; + } + return; + } + + if (!force->_flag || (_scene->_frameStartTime < force->_timer) || (force->_vertical + force->_horizontal >= 5)) + return; + + if (_vm->getRandomNumber(1, 1000) <= (200 + ((40 - (force->_vertical + force->_horizontal)) << 5))) { + int id = -1; + for (int i = 0; i < 100; i++) { + int randIdx = _vm->getRandomNumber(0, 39); + if (force->_seqId[randIdx] < 0) { + id = randIdx; + break; + } + } + + if (id < 0) { + for (int i = 0; i < 40; i++) { + if (force->_seqId[i] < 0) { + id = i; + break; + } + } + } + + int speedX, speedY; + int posX, posY; + int randVal = _vm->getRandomNumber(1, 100); + int spriteId; + bool mirror; + + if (id >= 20) { + spriteId = 2; + mirror = (randVal <= 50); + posX = mirror ? 315 : 5; + posY = computeScale(15, 119, id - 20); + speedX = 1000 * (mirror ? -1 : 1); + speedY = 0; + } else if (randVal <= 50) { + spriteId = 1; + mirror = false; + posX = computeScale(21, 258, id); + posY = 0; + speedX = 0; + speedY = 600; + } else { + spriteId = 0; + mirror = false; + posX = computeScale(21, 258, id); + posY = 155; + speedX = 0; + speedY = -600; + } + + if (id >= 0) { + force->_seqId[id] = _scene->_sequences.addSpriteCycle(sprites[spriteId], mirror, 2, 0, 0, 0); + _scene->_sequences.setDepth(force->_seqId[id], 8); + _scene->_sequences.setPosition(force->_seqId[id], Common::Point(posX, posY)); + _scene->_sequences.setMotion(force->_seqId[id], 2, speedX, speedY); + _scene->_sequences.addSubEntry(force->_seqId[id], SEQUENCE_TRIGGER_EXPIRE, 0, 150 + id); + if (spriteId == 2) + force->_horizontal++; + else + force->_vertical++; + } + } + + force->_timer = _scene->_frameStartTime + 4; +} + +/*------------------------------------------------------------------------*/ + +void Scene300s::preActions() { + _game._player._needToWalk = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene301::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene301::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 0, 0, 0); + + _globals[kMeteorologistStatus] = METEOROLOGIST_GONE; + _globals[kTeleporterCommand] = TELEPORTER_NONE; + + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->loadAnimation(formAnimName('a', -1), 60); + + sceneEntrySound(); +} + +void Scene301::step() { + if (_game._trigger == 60) + _scene->_nextSceneId = 302; +} + +/*------------------------------------------------------------------------*/ + +Scene302::Scene302(MADSEngine *vm) : Scene3xx(vm) { + _oldFrame = 0; +} + +void Scene302::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + s.syncAsSint32LE(_oldFrame); +} + +void Scene302::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene302::enter() { + _game._player._stepEnabled = false; + _game._player._visible = false; + + _scene->loadAnimation(formAnimName('a', -1), 71); + sceneEntrySound(); +} + +void Scene302::step() { + if (_game._trigger == 71) + _scene->_nextSceneId = 303; + + if ((_scene->_activeAnimation != nullptr) && (_scene->_activeAnimation->getCurrentFrame() != _oldFrame)) { + _oldFrame = _scene->_activeAnimation->getCurrentFrame(); + if (_oldFrame == 147) { + _game._objects.setRoom(OBJ_POISON_DARTS, 1); + _game._objects.setRoom(OBJ_BLOWGUN, 1); + _game._objects.setRoom(OBJ_REBREATHER, 1); + _game._objects.setRoom(OBJ_STUFFED_FISH, 1); + _game._objects.setRoom(OBJ_DEAD_FISH, 1); + _game._objects.setRoom(OBJ_BURGER, 1); + + int count = (int)_game._objects._inventoryList.size(); + for (int idx = 0; idx < count; idx++) { + if (_game._objects.isInInventory(idx)) + _game._objects.setRoom(idx, 50); + } + } + } +} + +/*------------------------------------------------------------------------*/ + +void Scene303::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene303::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('b', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('b', 1)); + + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 10, 0, 50, 120); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 10, 0, 0, 0); + + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->loadAnimation(formAnimName('a', -1), 60); + + sceneEntrySound(); +} + +void Scene303::step() { + if (_game._trigger == 60) + _scene->_nextSceneId = 304; +} + +/*------------------------------------------------------------------------*/ + +Scene304::Scene304(MADSEngine *vm) : Scene3xx(vm) { + _explosionSpriteId = -1; +} + +void Scene304::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + s.syncAsSint32LE(_explosionSpriteId); +} + +void Scene304::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene304::enter() { + if (_scene->_priorSceneId == 303) { + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->loadAnimation(formAnimName('a', -1), 60); + } else { + if (_globals[kSexOfRex] == REX_MALE) + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 0)); + else + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('a', 2)); + + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('b', 0)); + + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 150, 0, 3, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 2); + _vm->_palette->setEntry(252, 45, 63, 45); + _vm->_palette->setEntry(253, 20, 45, 20); + + if (_globals[kSexOfRex] == REX_MALE) + _game._player._playerPos = Common::Point(111, 117); + else + _game._player._playerPos = Common::Point(113, 116); + + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 11, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, -1); + _scene->_sequences.addTimer(48, 70); + } + + sceneEntrySound(); + _game.loadQuoteSet(0xEB, 0xEC, 0); +} + +void Scene304::step() { + if (_game._trigger == 60) + _scene->_nextSceneId = 311; + + if (_game._trigger >= 70) { + switch (_game._trigger) { + case 70: { + _game._player._visible = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 2, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + if (_globals[kSexOfRex] == REX_MALE) + _explosionSpriteId = _globals._spriteIndexes[1]; + else + _explosionSpriteId = _globals._spriteIndexes[4]; + + int sprIdx = _scene->_sequences.addSpriteCycle(_explosionSpriteId, false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(sprIdx, -1, 4); + _scene->_sequences.setDepth(sprIdx, 1); + _scene->_sequences.addSubEntry(sprIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 71); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 74); + } + break; + + case 71: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 60, _game.getQuote(0xEB)); + _scene->_sequences.addTimer(1, 72); + break; + + case 72: { + _vm->_sound->command(43); + int sprIdx = _scene->_sequences.addSpriteCycle(_explosionSpriteId, false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(sprIdx, 5, -2); + _scene->_sequences.setDepth(sprIdx, 1); + _scene->_sequences.addSubEntry(sprIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 73); + if (_game._storyMode == STORYMODE_NICE) + _scene->_sequences.addSubEntry(sprIdx, SEQUENCE_TRIGGER_SPRITE, 8, 78); + } + break; + + case 73: { + int sprIdx = _scene->_sequences.addSpriteCycle(_explosionSpriteId, false, 8, 0, 0, 0); + _scene->_sequences.setAnimRange(sprIdx, -2, -2); + _scene->_sequences.setDepth(sprIdx, 1); + } + break; + + case 74: + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 5, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 75); + break; + + case 75: + _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 2, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 76); + break; + + case 76: + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 2, 2); + _scene->_sequences.addTimer(48, 77); + break; + + case 77: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(211, 45), 0xFDFC, 32, 0, 180, _game.getQuote(0xEC)); + _scene->_sequences.addTimer(120, 78); + break; + + case 78: + _scene->_nextSceneId = 316; + break; + + default: + break; + } + } +} + +/*------------------------------------------------------------------------*/ + +Scene307::Scene307(MADSEngine *vm) : Scene3xx(vm) { + _afterPeeingFl = false; + _duringPeeingFl = false; + _grateOpenedFl = false; + _activePrisonerFl = false; + + _animationMode = -1; + _prisonerMessageId = -1; + _fieldCollisionCounter = -1; + + _lastFrameTime = 0; + _guardTime = 0; + _prisonerTimer = 0; + + _subQuote2 = ""; + + _forceField.init(); +} + +void Scene307::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + _forceField.synchronize(s); + + s.syncAsByte(_afterPeeingFl); + s.syncAsByte(_duringPeeingFl); + s.syncAsByte(_grateOpenedFl); + s.syncAsByte(_activePrisonerFl); + + s.syncAsSint32LE(_animationMode); + s.syncAsSint32LE(_prisonerMessageId); + s.syncAsSint32LE(_fieldCollisionCounter); + + s.syncAsUint32LE(_lastFrameTime); + s.syncAsUint32LE(_guardTime); + s.syncAsUint32LE(_prisonerTimer); + + s.syncString(_subQuote2); +} + +void Scene307::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_AIR_VENT); + _scene->addActiveVocab(NOUN_CLIMB_INTO); +} + +void Scene307::handleRexDialog(int quote) { + Common::String curQuote = _game.getQuote(_action._activeAction._verbId); + if (_vm->_font->getWidth(curQuote, _scene->_textSpacing) > 200) { + Common::String subQuote1; + _game.splitQuote(curQuote, subQuote1, _subQuote2); + _scene->_kernelMessages.add(Common::Point(0, -14), 0x1110, 34, 0, 240, subQuote1); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 1, 180, _subQuote2); + } else + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 1, 120, curQuote); +} + +void Scene307::handlePrisonerEncounter() { + switch (_action._activeAction._verbId) { + case 275: + setDialogNode(5); + break; + + case 277: + setDialogNode(4); + break; + + case 276: + setDialogNode(6); + break; + } +} + +void Scene307::handlePrisonerSpeech(int firstQuoteId, int number, long timeout) { + int height = number * 14; + int posY; + + if (height < 60) + posY = 65 - height; + else + posY = 78 - (height / 2); + + _scene->_kernelMessages.reset(); + _activePrisonerFl = true; + + int quoteId = firstQuoteId; + for (int count = 0; count < number; count++) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_kernelMessages.add(Common::Point(5, posY), 0xFDFC, 0, 81, timeout, _game.getQuote(quoteId)); + posY += 14; + quoteId++; + } +} + +void Scene307::setDialogNode(int node) { + switch (node) { + case 0: + handlePrisonerSpeech(0x153, 2, 120); + _scene->_userInterface.setup(kInputBuildingSentences); + break; + + case 1: + _globals[kMetBuddyBeast] = true; + handlePrisonerSpeech(0x10F, 2, 9999999); + _dialog1.start(); + break; + + case 2: + _globals[kMetBuddyBeast] = true; + handlePrisonerSpeech(0x111, 2, 9999999); + _dialog1.start(); + break; + + case 4: + handlePrisonerSpeech(0x116, 1, 120); + _scene->_userInterface.setup(kInputBuildingSentences); + break; + + case 5: + _globals[kKnowsBuddyBeast] = true; + handlePrisonerSpeech(0x117, 2, 9999999); + _dialog2.start(); + break; + + case 6: + handlePrisonerSpeech(0x123, 1, 120); + _scene->_userInterface.setup(kInputBuildingSentences); + break; + + case 7: + _globals[kKnowsBuddyBeast] = true; + handlePrisonerSpeech(0x124, 10, 9999999); + _dialog2.write(0x11A, false); + _dialog2.write(0x11B, true); + _dialog2.write(0x120, true); + _dialog2.start(); + break; + + case 8: + handlePrisonerSpeech(0x12E, 6, 9999999); + _dialog2.write(0x11A, false); + _dialog2.write(0x11B, false); + _dialog2.write(0x11C, true); + _dialog2.write(0x11D, true); + _dialog2.write(0x11F, true); + _dialog2.start(); + break; + + case 9: + handlePrisonerSpeech(0x134, 4, 9999999); + _dialog2.write(0x11D, false); + _dialog2.start(); + break; + + case 10: + handlePrisonerSpeech(0x138, 6, 9999999); + _dialog2.write(0x11E, false); + _dialog2.start(); + break; + + case 11: + handlePrisonerSpeech(0x13E, 6, 9999999); + _dialog2.write(0x11F, false); + _dialog2.write(0x121, true); + _dialog2.start(); + break; + + case 12: + handlePrisonerSpeech(0x144, 4, 9999999); + _dialog2.write(0x11C, false); + _dialog2.start(); + break; + + case 13: + handlePrisonerSpeech(0x148, 7, 9999999); + _dialog2.write(0x120, false); + _dialog2.start(); + break; + + case 14: + handlePrisonerSpeech(0x14F, 3, 9999999); + _dialog2.write(0x121, false); + _dialog2.start(); + break; + + case 15: + handlePrisonerSpeech(0x152, 1, 120); + _scene->_userInterface.setup(kInputBuildingSentences); + break; + + case 16: + _globals[kKnowsBuddyBeast] = true; + handlePrisonerSpeech(0x10C, 1, 9999999); + _dialog2.start(); + break; + + default: + break; + } +} + +void Scene307::handlePrisonerDialog() { + switch (_action._activeAction._verbId) { + case 0x11A: + setDialogNode(7); + break; + + case 0x11B: + setDialogNode(8); + break; + + case 0x11C: + setDialogNode(12); + break; + + case 0x11D: + setDialogNode(9); + break; + + case 0x11E: + setDialogNode(10); + break; + + case 0x11F: + setDialogNode(11); + break; + + case 0x120: + setDialogNode(13); + break; + + case 0x121: + setDialogNode(14); + break; + + case 0x122: + setDialogNode(15); + break; + } +} + +void Scene307::handleDialog() { + if (_game._trigger == 0) { + _scene->_kernelMessages.reset(); + _game._player._stepEnabled = false; + handleRexDialog(_action._activeAction._verbId); + } else { + _game._player._stepEnabled = true; + + if (!_globals[kKnowsBuddyBeast]) { + handlePrisonerEncounter(); + } else { + handlePrisonerDialog(); + } + } +} + +void Scene307::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*SC003x0"); + _globals._spriteIndexes[0] = _scene->_sprites.addSprites("*SC003x1"); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*SC003x2"); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 0)); + + initForceField(&_forceField, true); + + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 15); + + _animationMode = 0; + _fieldCollisionCounter = 0; + + _scene->changeVariant(1); + + _game.loadQuoteSet(0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0x10C, 0x104, 0x106, 0x107, 0x108, 0x105, + 0x109, 0x10A, 0x10B, 0x10D, 0x10E, 0x10F, 0x110, 0x111, 0x112, 0x113, 0x114, 0x115, 0x116, 0x117, + 0x118, 0x119, 0x11A, 0x11B, 0x11C, 0x11D, 0x11E, 0x11F, 0x120, 0x121, 0x122, 0x123, 0x124, 0x125, + 0x126, 0x127, 0x128, 0x129, 0x12A, 0x12B, 0x12C, 0x12D, 0x12E, 0x12F, 0x130, 0x131, 0x132, 0x133, + 0x134, 0x135, 0x136, 0x137, 0x138, 0x139, 0x13A, 0x13B, 0x13C, 0x13D, 0x13E, 0x13F, 0x140, 0x141, + 0x142, 0x143, 0x144, 0x145, 0x146, 0x147, 0x148, 0x149, 0x14A, 0x14B, 0x14C, 0x14D, 0x14E, 0x14F, + 0x150, 0x151, 0x152, 0x153, 0); + + _dialog1.setup(0x3F, 0x113, 0x114, 0x115, -1); + _dialog2.setup(0x40, 0x11A, 0x11B, 0x11C, 0x11D, 0x11E, 0x11F, 0x120, 0x121, 0x122, 0); + + if (!_game._visitedScenes._sceneRevisited) + _dialog2.set(0x11A, 0x122, 0); + else if (_scene->_priorSceneId == 318) + _dialog2.write(0x11E, true); + + + if (_scene->_priorSceneId == -2) { + if (_grateOpenedFl) + _vm->_sound->command(10); + else + _vm->_sound->command(3); + } else { + _afterPeeingFl = false; + _duringPeeingFl = false; + _guardTime = 0; + _grateOpenedFl = false; + _activePrisonerFl = false; + _prisonerTimer = 0; + _prisonerMessageId = 0x104; + + if (_scene->_priorSceneId == 308) { + _game._player._visible = false; + _game._player._stepEnabled = false; + _game._player._playerPos = Common::Point(156, 113); + _game._player._facing = FACING_NORTH; + _animationMode = 1; + _vm->_sound->command(11); + _scene->loadAnimation(formAnimName('a', -1), 60); + } else if (_scene->_priorSceneId == 387) { + _game._player._playerPos = Common::Point(129, 108); + _game._player._facing = FACING_NORTH; + _vm->_sound->command(3); + _grateOpenedFl = true; + } else { + _game._player._playerPos = Common::Point(159, 109); + _game._player._facing = FACING_SOUTH; + _vm->_sound->command(3); + } + } + + if (_grateOpenedFl) { + _scene->_hotspots.activate(17, false); + + int idx = _scene->_dynamicHotspots.add(17, VERB_CLIMB_INTO, -1, Common::Rect(117, 67, 117 + 19, 67 + 13)); + int hotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(129, 104), FACING_NORTH); + _scene->_dynamicHotspots.setCursor(hotspotId, CURSOR_GO_UP); + + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 15); + } + + _vm->_palette->setEntry(252, 63, 30, 20); + _vm->_palette->setEntry(253, 45, 15, 12); + + sceneEntrySound(); + + if ((_scene->_priorSceneId == 318) || (_scene->_priorSceneId == 387)) + _scene->_kernelMessages.addQuote(0xF3, 120, 0); +} + +void Scene307::step() { + handleForceField(&_forceField, &_globals._spriteIndexes[0]); + + if ((_animationMode == 1) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() == 126) { + _forceField._flag = false; + _vm->_sound->command(5); + } + + if (_scene->_activeAnimation->getCurrentFrame() == 194) { + _forceField._flag = true; + _vm->_sound->command(24); + } + } + + if ((_animationMode == 2) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() == 54) + _forceField._flag = false; + + if (_scene->_activeAnimation->getCurrentFrame() == 150) { + _game._player._visible = false; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + } + } + + if (_game._trigger == 60) { + _game._player._visible = true; + _game._player._stepEnabled = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _animationMode = 0; + _vm->_sound->command(9); + } + + if ((_lastFrameTime != _scene->_frameStartTime) && !_duringPeeingFl) { + int32 elapsedTime = _lastFrameTime - _scene->_frameStartTime; + if ((elapsedTime > 0) && (elapsedTime <= 4)) { + _guardTime += elapsedTime; + _prisonerTimer += elapsedTime; + } else { + _guardTime++; + _prisonerTimer++; + } + _lastFrameTime = _scene->_frameStartTime; + + if ((_guardTime > 3000) && !_duringPeeingFl && (_scene->_activeAnimation == nullptr) + && (_game._screenObjects._inputMode != 1) && _globals[kMetBuddyBeast] && !_activePrisonerFl) { + if (!_game._objects.isInInventory(OBJ_SCALPEL) && !_grateOpenedFl) { + _game._player._stepEnabled = false; + _game._player.walk(Common::Point(151, 119), FACING_SOUTHEAST); + _animationMode = 2; + _vm->_sound->command(11); + _scene->loadAnimation(formAnimName('b', -1), 70); + } + _guardTime = 0; + } else if ((_prisonerTimer > 300) && (_game._screenObjects._inputMode != 1) && (_scene->_activeAnimation == nullptr) && !_activePrisonerFl) { + if (!_globals[kMetBuddyBeast]) { + int idx = _scene->_kernelMessages.add(Common::Point(5, 51), 0xFDFC, 0, 81, 120, _game.getQuote(_prisonerMessageId)); + _scene->_kernelMessages.setQuoted(idx, 4, true); + _prisonerMessageId++; + if (_prisonerMessageId > 0x10A) + _prisonerMessageId = 0x104; + } else if (_globals[kKnowsBuddyBeast] && (_dialog2.read(0) > 1) && (_vm->getRandomNumber(1, 3) == 1)) { + int idx = _scene->_kernelMessages.add(Common::Point(5, 51), 0xFDFC, 0, 81, 120, _game.getQuote(267)); + _scene->_kernelMessages.setQuoted(idx, 4, true); + } + _prisonerTimer = 0; + } + } + + if (_game._trigger == 70) + _scene->_nextSceneId = 318; + + if (_game._trigger == 81) { + _prisonerTimer = 0; + if (_activePrisonerFl && (_guardTime > 2600)) + _guardTime = 3000 - _vm->getRandomNumber(1, 800); + + _activePrisonerFl = false; + } +} + +void Scene307::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(30715); + else if (_game._screenObjects._inputMode == 1) + handleDialog(); + else if (_action.isAction(VERB_TALKTO, NOUN_CELL_WALL) || _action.isAction(VERB_TALKTO, NOUN_WALL) || _action.isAction(VERB_TALKTO, NOUN_TOILET)) { + int node, say; + if (_globals[kKnowsBuddyBeast]) { + say = 0x10E; + node = 16; + } else if (_globals[kMetBuddyBeast]) { + say = 0x10E; + node = 2; + } else { + say = 0x10D; + node = 1; + } + + switch (_game._trigger) { + case 0: + handleRexDialog(say); + break; + + case 1: + setDialogNode(node); + break; + } + } else if (_action.isAction(VERB_PRY, NOUN_SCALPEL, NOUN_AIR_VENT)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(239)); + _scene->_sequences.addTimer(120, 1); + break; + + case 1: + _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RXCL_8"); + _game._player._visible = false; + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], -1, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 2: { + int oldIdx = _globals._sequenceIndexes[5]; + _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 12, 6, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 2, 3); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + } + break; + + case 3: { + int oldIdx = _globals._sequenceIndexes[5]; + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], oldIdx); + _scene->_sequences.addTimer(48, 4); + } + break; + + case 4: + _vm->_sound->command(26); + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 15); + _scene->_sequences.addTimer(90, 5); + break; + + case 5: + _vm->_sound->command(10); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(241)); + _scene->_sequences.addTimer(120, 6); + break; + + case 6: { + _game._player._visible = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _grateOpenedFl = true; + _scene->_hotspots.activate(17, false); + int idx = _scene->_dynamicHotspots.add(17, NOUN_CLIMB_INTO, -1, Common::Rect(117, 67, 117 + 19, 67 + 13)); + int hotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(129, 104), FACING_NORTH); + _scene->_dynamicHotspots.setCursor(hotspotId, CURSOR_GO_UP); + _game._objects.removeFromInventory(OBJ_SCALPEL, NOWHERE); + _scene->_kernelMessages.addQuote(0xF2, 120, 7); + } + break; + + case 7: + _scene->_sprites.remove(_globals._spriteIndexes[5]); + _game._player._stepEnabled = true; + break; + + default: + break; + } + }else if (_action.isAction(VERB_CLIMB_INTO, NOUN_AIR_VENT)) { + if (_grateOpenedFl) { + switch (_game._trigger) { + case 0: + _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RXCL_8"); + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 60, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 3, -2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 15); + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 18, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], -1, 4); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 15); + break; + + case 2: { + int oldIdx = _globals._sequenceIndexes[5]; + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 4, 10); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + } + break; + + case 3: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 3); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 11); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(129, 102)); + _scene->_sequences.addTimer(48, 4); + break; + + case 4: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 12, 14); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(129, 102)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 5); + break; + + case 5: + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 15); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(129, 102)); + _scene->_sequences.addTimer(48, 6); + break; + + case 6: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + _scene->_sequences.addTimer(48, 7); + break; + + case 7: + _scene->_nextSceneId = 313; + break; + + default: + break; + } + } + } else if (_action.isAction(VERB_USE, NOUN_TOILET) && (_game._storyMode != STORYMODE_NAUGHTY)) + _vm->_dialogs->show(30723); + else if (_action.isAction(VERB_USE, NOUN_TOILET)) { + if (!_afterPeeingFl) { + switch (_game._trigger) { + case 0: + _vm->_sound->command(25); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 0)); + _duringPeeingFl = true; + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], -1, 2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 5, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 3, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]); + _game._player._visible = true; + _scene->_sequences.addTimer(48, 3); + break; + + case 3: { + _scene->_sprites.remove(_globals._spriteIndexes[3]); + _scene->_kernelMessages.reset(); + int idx = _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 4, 120, _game.getQuote(237)); + _scene->_kernelMessages.setQuoted(idx, 4, true); + } + break; + + case 4: + _game._player._stepEnabled = true; + _duringPeeingFl = false; + _afterPeeingFl = true; + break; + + default: + break; + } + } else { + _scene->_kernelMessages.reset(); + int idx = _scene->_kernelMessages.add(Common::Point(85, 39), 0x1110, 0, 0, 180, _game.getQuote(238)); + _scene->_kernelMessages.setQuoted(idx, 4, true); + } + } else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT)) { + if (!_grateOpenedFl) + _vm->_dialogs->show(30710); + else + _vm->_dialogs->show(30711); + } else if (_action.isAction(VERB_LOOK, NOUN_BED)) + _vm->_dialogs->show(30712); + else if (_action.isAction(VERB_LOOK, NOUN_SINK)) + _vm->_dialogs->show(30713); + else if (_action.isAction(VERB_LOOK, NOUN_TOILET)) + _vm->_dialogs->show(30714); + else if (_action.isAction(VERB_SHARPEN, NOUN_SCALPEL)) + _vm->_dialogs->show(30716); + else if (_action.isAction(VERB_LOOK, NOUN_CELL_WALL)) + _vm->_dialogs->show(30717); + else if (_action.isAction(VERB_LOOK, NOUN_LIGHT)) + _vm->_dialogs->show(30718); + else if (_action.isAction(VERB_WALK_INTO, NOUN_CORRIDOR)) { + switch (_fieldCollisionCounter) { + case 0: + _vm->_dialogs->show(30719); + _fieldCollisionCounter = 1; + break; + + case 1: + _vm->_dialogs->show(30720); + _fieldCollisionCounter = 2; + break; + + case 2: + _vm->_dialogs->show(30721); + _fieldCollisionCounter = 3; + break; + + case 3: + _vm->_dialogs->show(30722); + break; + } + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene308::Scene308(MADSEngine *vm) : Scene3xx(vm) { + _forceField.init(); +} + +void Scene308::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + _forceField.synchronize(s); +} + + +void Scene308::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene308::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*SC003x0"); + _globals._spriteIndexes[0] = _scene->_sprites.addSprites("*SC003x1"); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*SC003x2"); + + initForceField(&_forceField, true); + + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('b', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, "")); + + _vm->_palette->setEntry(252, 63, 30, 20); + _vm->_palette->setEntry(253, 45, 15, 12); + + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 15); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); + _scene->_sequences.addTimer(48, 70); + + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->loadAnimation(formAnimName('a', -1), 60); + + sceneEntrySound(); + _game.loadQuoteSet(0xF4, 0xF5, 0xF6, 0); +} + +void Scene308::step() { + handleForceField(&_forceField, &_globals._spriteIndexes[0]); + + if (_game._trigger == 60) + _scene->_nextSceneId = 307; + + if (_game._trigger < 70) + return; + + switch (_game._trigger) { + case 70: { + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 18, 9, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, 3); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); + _scene->_kernelMessages.reset(); + int idx = _scene->_kernelMessages.add(Common::Point(171, 21), 0xFDFC, 0, 0, 120, _game.getQuote(244)); + _scene->_kernelMessages.setQuoted(idx, 2, true); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + } + break; + + case 71: { + int seqIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], seqIdx); + _scene->_sequences.addTimer(48, 72); + } + break; + + case 72: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 20, 5, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 3, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); + _scene->_kernelMessages.reset(); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 73); + break; + + case 73: { + int seqIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], seqIdx); + _scene->_sequences.addTimer(48, 74); + } + break; + + case 74: { + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 20, 8, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 6, 7); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); + _scene->_kernelMessages.reset(); + int idx = _scene->_kernelMessages.add(Common::Point(171, 21), 0xFDFC, 0, 0, 120, _game.getQuote(245)); + _scene->_kernelMessages.setQuoted(idx, 2, true); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 75); + } + break; + + case 75: { + int seqIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 23, 5, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 8, 10); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 76); + } + break; + + case 76: { + int seqIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 26, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, 3); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); + _scene->_kernelMessages.reset(); + int idx = _scene->_kernelMessages.add(Common::Point(171, 21), 0xFDFC, 0, 0, 120, _game.getQuote(246)); + _scene->_kernelMessages.setQuoted(idx, 2, true); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], seqIdx); + } + break; + + default: + break; + } +} + +/*------------------------------------------------------------------------*/ + +Scene309::Scene309(MADSEngine *vm) : Scene3xx(vm) { + for (int i = 0; i < 3; i++) { + _characterSpriteIndexes[i] = -1; + _messagesIndexes[i] = -1; + } + + _lastFrame = -1; + _forceField.init(); +} + +void Scene309::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + _forceField.synchronize(s); + + for (int i = 0; i < 3; ++i) + s.syncAsSint32LE(_characterSpriteIndexes[i]); + for (int i = 0; i < 3; ++i) + s.syncAsSint32LE(_messagesIndexes[i]); + s.syncAsSint32LE(_lastFrame); +} + +void Scene309::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene309::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*SC003x0"); + _globals._spriteIndexes[0] = _scene->_sprites.addSprites("*SC003x1"); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*SC003x2"); + + initForceField(&_forceField, true); + + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, "")); + + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 15); + + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], -1, 3); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 3, 70); + + _vm->_palette->setEntry(252, 63, 37, 26); + _vm->_palette->setEntry(253, 45, 24, 17); + _vm->_palette->setEntry(16, 63, 63, 63); + _vm->_palette->setEntry(17, 45, 45, 45); + _vm->_palette->setEntry(250, 63, 20, 20); + _vm->_palette->setEntry(251, 45, 10, 10); + + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->loadAnimation(formAnimName('a', -1), 60); + + _characterSpriteIndexes[0] = _scene->_activeAnimation->_spriteListIndexes[2]; + _characterSpriteIndexes[1] = _scene->_activeAnimation->_spriteListIndexes[2]; + _characterSpriteIndexes[2] = _scene->_activeAnimation->_spriteListIndexes[1]; + + _messagesIndexes[0] = -1; + _messagesIndexes[1] = -1; + _messagesIndexes[2] = -1; + + sceneEntrySound(); + + _game.loadQuoteSet(0xF7, 0xF8, 0xF9, 0x15C, 0x15D, 0x15E, 0); +} + +void Scene309::step() { + handleForceField(&_forceField, &_globals._spriteIndexes[0]); + + if (_game._trigger == 61) { + _messagesIndexes[0] = -1; + _messagesIndexes[1] = -1; + } + + if (_game._trigger == 62) + _messagesIndexes[2] = -1; + + if (_scene->_activeAnimation != nullptr) { + if (_lastFrame != _scene->_activeAnimation->getCurrentFrame()) { + _lastFrame = _scene->_activeAnimation->getCurrentFrame(); + if (_lastFrame == 39) { + _messagesIndexes[0] = _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 32, 61, 210, _game.getQuote(348)); + _messagesIndexes[1] = _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 32, 0, 210, _game.getQuote(349)); + } + + if (_lastFrame == 97) + _messagesIndexes[2] = _scene->_kernelMessages.add(Common::Point(0, 0), 0xFBFA, 32, 62, 180, _game.getQuote(350)); + + for (int charIdx = 0; charIdx < 3; charIdx++) { + if (_messagesIndexes[charIdx] >= 0) { + bool match = false; + int j = -1; + for (j = _scene->_activeAnimation->_oldFrameEntry; j < _scene->_activeAnimation->_header._frameEntriesCount; j++) { + if (_scene->_activeAnimation->_frameEntries[j]._spriteSlot._spritesIndex == _characterSpriteIndexes[charIdx]) { + match = true; + break; + } + } + + if (match) { + SpriteSlotSubset *curSpriteSlot = &_scene->_activeAnimation->_frameEntries[j]._spriteSlot; + _scene->_kernelMessages._entries[_messagesIndexes[charIdx]]._position.x = curSpriteSlot->_position.x; + _scene->_kernelMessages._entries[_messagesIndexes[charIdx]]._position.y = curSpriteSlot->_position.y - (50 + (14 * ((charIdx == 0) ? 2 : 1))); + } + } + } + } + } + + if (_game._trigger >= 70) { + switch (_game._trigger) { + case 70: { + int idx = _scene->_dynamicHotspots.add(689, 690, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(142, 146), FACING_NORTHEAST); + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 4, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, 3); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + } + break; + + case 71: { + int _oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 4, 7); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], _oldIdx); + int idx = _scene->_kernelMessages.add(Common::Point(85, 37), 0xFDFC, 0, 0, 120, _game.getQuote(248)); + _scene->_kernelMessages.setQuoted(idx, 2, true); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + } + break; + + case 72: { + int _oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 8, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 8, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], _oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 73); + } + break; + + case 73: { + int _oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 12, 20); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], _oldIdx); + int idx = _scene->_kernelMessages.add(Common::Point(170, 49), 0xFDFC, 0, 0, 120, _game.getQuote(249)); + _scene->_kernelMessages.setQuoted(idx, 2, true); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 74); + } + break; + + case 74: { + int _oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 6, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 21, 23); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], _oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 75); + } + break; + + case 75: { + int _oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 6, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 24, 25); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], _oldIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 76); + } + break; + + case 76: { + int _oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 26, 28); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], _oldIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 77); + } + break; + + case 77: { + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 90, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 29, 30); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); + int idx = _scene->_kernelMessages.add(Common::Point(15, 46), 0xFDFC, 0, 0, 120, _game.getQuote(247)); + _scene->_kernelMessages.setQuoted(idx, 2, true); + _scene->_sequences.addTimer(120, 78); + } + break; + } + } + + if (_game._trigger == 60) + _scene->_nextSceneId = 308; +} + +/*------------------------------------------------------------------------*/ + +Scene310::Scene310(MADSEngine *vm) : Scene3xx(vm) { + _forceField.init(); +} + +void Scene310::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + _forceField.synchronize(s); +} + +void Scene310::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene310::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*SC003x0"); + _globals._spriteIndexes[0] = _scene->_sprites.addSprites("*SC003x1"); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*SC003x2"); + + initForceField(&_forceField, true); + + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, "")); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 15); + + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->loadAnimation(formAnimName('a', -1), 70); + + sceneEntrySound(); +} + +void Scene310::step() { + handleForceField(&_forceField, &_globals._spriteIndexes[0]); + + if (_game._trigger == 70) + _scene->_nextSceneId = 309; +} + +/*------------------------------------------------------------------------*/ + +Scene311::Scene311(MADSEngine *vm) : Scene3xx(vm) { + _checkGuardFl = false; +} + +void Scene311::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + s.syncAsByte(_checkGuardFl); +} + +void Scene311::setup() { + if (_scene->_currentSceneId == 391) + _globals[kSexOfRex] = REX_MALE; + + setPlayerSpritesPrefix(); + setAAName(); + + if (_scene->_currentSceneId == 304) + _game._player._spritesPrefix = ""; +} + +void Scene311::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, "")); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXCL_8"); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXCL_2"); + + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + + _checkGuardFl = false; + _game.loadQuoteSet(0xFA, 0); + + if (_scene->_priorSceneId == 391) { + _globals[kSexOfRex] = REX_MALE; + _game._player._stepEnabled = false; + _game._player._visible = false; + _game._player._facing = FACING_SOUTH; + _game._player._playerPos = Common::Point(166, 101); + _scene->_sequences.addTimer(120, 71); + } else if (_scene->_priorSceneId == 310) + _game._player._playerPos = Common::Point(302, 145); + else if (_scene->_priorSceneId == 320) { + _game._player._playerPos = Common::Point(129, 113); + _game._player._facing = FACING_SOUTH; + } else if (_scene->_priorSceneId != -2) { + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->loadAnimation(formAnimName('a', -1), 70); + } + + sceneEntrySound(); +} + +void Scene311::step() { + if (_game._trigger == 70) + _scene->_nextSceneId = 310; + + if (_game._trigger >= 71) { + switch (_game._trigger) { + case 71: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 72); + break; + + case 72: + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 73); + break; + + case 73: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 3); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 74); + break; + + case 74: + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 4, 5); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 75); + break; + + case 75: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addTimer(15, 76); + } + break; + + case 76: + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 7); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 77); + break; + + case 77: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 8); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 78); + break; + + case 78: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 9); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 79); + break; + + case 79: + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 10, -2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 80); + break; + + case 80: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]); + _game._player._stepEnabled = true; + _game._player._visible = true; + break; + + default: + break; + } + } + + if (_game._player._moving && (_scene->_rails.getNext() > 0)) { + int x = _game._player._prepareWalkPos.x; + if (x < 75) + x = 75; + if (x > 207) + x = 207; + + _checkGuardFl = true; + _game._player.startWalking(Common::Point(x, 122), FACING_SOUTH); + _scene->_rails.resetNext(); + } +} + +void Scene311::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(31119); + else if (_checkGuardFl) { + _checkGuardFl = false; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.addQuote(0xFA, 120, 0); + } else if (_action.isAction(VERB_SIT_AT, NOUN_DESK)) + _scene->_nextSceneId = 320; + else if (_action.isAction(VERB_CLIMB_INTO, NOUN_AIR_VENT)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 50, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 3, -2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 15, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, 4); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: { + int oldIdx = _globals._sequenceIndexes[1]; + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], oldIdx); + } + break; + + case 2: { + int oldIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 4, 10); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + } + break; + + case 3: { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 3); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + int oldIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 11); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(167, 100)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx); + _scene->_sequences.addTimer(15, 4); + } + break; + + case 4: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 12, 14); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(167, 100)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 5); + break; + + case 5: { + int oldIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 15); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(167, 100)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx); + _scene->_sequences.addTimer(15, 6); + } + break; + + case 6: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _scene->_sequences.addTimer(15, 7); + break; + + case 7: + _scene->_nextSceneId = 313; + break; + + default: + break; + } + } else if (_action.isAction(VERB_LOOK, NOUN_DESK)) + _vm->_dialogs->show(31110); + else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(31111); + else if (_action.isAction(VERB_LOOK, NOUN_LIGHTING_FIXTURE) || _action.isAction(VERB_STARE_AT, NOUN_LIGHTING_FIXTURE)) + _vm->_dialogs->show(31112); + else if (_action.isAction(VERB_LOOK, NOUN_LIGHTS) || _action.isAction(VERB_STARE_AT, NOUN_LIGHTS)) + _vm->_dialogs->show(31113); + else if (_action.isAction(VERB_TAKE, NOUN_LIGHTS)) + _vm->_dialogs->show(31114); + else if (_action.isAction(VERB_LOOK, NOUN_LIGHT) || _action.isAction(VERB_STARE_AT, NOUN_LIGHT)) + _vm->_dialogs->show(31115); + else if (_action.isAction(VERB_TAKE, NOUN_LIGHT)) + _vm->_dialogs->show(31116); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST)) + _vm->_dialogs->show(31117); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST)) + _vm->_dialogs->show(31118); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT)) + _vm->_dialogs->show(31120); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene313::setup() { + setPlayerSpritesPrefix(); + _game._player._spritesPrefix = "RM313A"; + setAAName(); +} + +void Scene313::enter() { + _scene->_userInterface.setup(kInputLimitedSentences); + + if ((_scene->_priorSceneId == 366) || (_scene->_priorSceneId == 316)) { + _game._player._playerPos = Common::Point(30, 80); + _game._player._facing = FACING_NORTH; + } else if ((_scene->_priorSceneId == 311) || (_scene->_priorSceneId == 361) || (_scene->_priorSceneId == 391)) { + _game._player._playerPos = Common::Point(90, 70); + _game._player._facing = FACING_EAST; + } else if (_scene->_priorSceneId == 390) { + _game._player._playerPos = Common::Point(126, 70); + _game._player._facing = FACING_EAST; + } else if ((_scene->_priorSceneId == 389) || (_scene->_priorSceneId == 399)) { + _game._player._playerPos = Common::Point(163, 70); + _game._player._facing = FACING_WEST; + } else if (_scene->_priorSceneId == 388) { + _game._player._playerPos = Common::Point(199, 70); + _game._player._facing = FACING_WEST; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(234, 70); + _game._player._facing = FACING_WEST; + } + + if (_globals[kAfterHavoc]) { + for (uint16 i = 0; i < _scene->_paletteCycles.size(); i++) { + int palIdx = _scene->_paletteCycles[i]._firstColorIndex; + int size = _scene->_paletteCycles[i]._colorCount * 3; + memset(&_vm->_palette->_cyclingPalette[palIdx], 0, size); + memset(&_vm->_palette->_mainPalette[palIdx], 0, size); + } + } + + sceneEntrySound(); +} + +void Scene313::actions() { + if (_action.isAction(VERB_CRAWL_TO, NOUN_FOURTH_CELL)) + _scene->_nextSceneId = 387; + else if (_action.isAction(VERB_CRAWL_TO, NOUN_THIRD_CELL)) + _scene->_nextSceneId = 388; + else if (_action.isAction(VERB_CRAWL_TO, NOUN_SECOND_CELL)) { + if (_globals[kAfterHavoc]) + _scene->_nextSceneId = 399; + else + _scene->_nextSceneId = 389; + } else if (_action.isAction(VERB_CRAWL_TO, NOUN_FIRST_CELL)) + _scene->_nextSceneId = 390; + else if (_action.isAction(VERB_CRAWL_TO, NOUN_SECURITY_STATION)) { + if (_globals[kSexOfRex] == REX_FEMALE) { + _globals[kSexOfRex] = REX_MALE; + _vm->_dialogs->show(31301); + } + _scene->_nextSceneId = 391; + } else if (_action.isAction(VERB_CRAWL_TO, NOUN_EQUIPMENT_ROOM)) { + if (_globals[kSexOfRex] == REX_FEMALE) { + _globals[kSexOfRex] = REX_MALE; + _vm->_dialogs->show(31301); + } + _scene->_nextSceneId = 366; + } else if (!_action.isAction(VERB_CRAWL_DOWN, NOUN_AIR_SHAFT)) + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene316::setup() { + if (_scene->_currentSceneId == 366) + _globals[kSexOfRex] = REX_MALE; + + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene316::handleRexInGrate() { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addTimer(15, 1); + break; + + case 1: + _scene->_sequences.setDone(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 12, 3, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 2, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 2: { + int oldIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 4, 8); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); + + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 12); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 4); + } + break; + + case 3: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 12); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + } + break; + + case 4: { + int oldIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 10, 11); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); + + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 5, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 5); + } + break; + + case 5: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 3); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + + oldIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 12); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); + _scene->_sequences.addTimer(15, 6); + } + break; + + case 6: + _scene->_sequences.setDone(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 13, 14); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, 3); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 7); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 8); + break; + + case 7: + _scene->_sequences.setDone(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 15); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], -1); + break; + + case 8: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addTimer(15, 9); + } + break; + + case 9: + _scene->_sequences.setDone(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.addTimer(48, 10); + break; + + case 10: + _scene->_nextSceneId = 313; + break; + + default: + break; + } +} + +void Scene316::handleRoxInGrate() { + int temp; + int temp1; + + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.addTimer(15, 1); + break; + + case 1: + _scene->_sequences.setDone(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 17, 3, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 2, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 2: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 17, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 12); + + temp = _globals._sequenceIndexes[5]; + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 17, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 4, 8); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], temp); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 4); + break; + + case 3: + temp1 = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 12); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], temp1); + break; + + case 4: + temp = _globals._sequenceIndexes[5]; + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 17, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 10, 11); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], temp); + + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 17, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 5, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 5); + break; + + case 5: + temp = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 3); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], temp); + + temp = _globals._sequenceIndexes[5]; + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 12); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], temp); + _scene->_sequences.addTimer(20, 6); + break; + + case 6: + _scene->_sequences.setDone(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 17, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 13, 15); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 17, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, 3); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 7); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 8); + break; + + case 7: + _scene->_sequences.setDone(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 16); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], -1); + break; + + case 8: + temp = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], temp); + _scene->_sequences.addTimer(20, 9); + break; + + case 9: + _scene->_sequences.setDone(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.addTimer(48, 10); + break; + + case 10: + _scene->_nextSceneId = 313; + break; + + default: + break; + } +} + +void Scene316::enter() { + if (_globals[kSexOfRex] == REX_MALE) { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('g', -1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXCL_8"); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites("*RXCL_2"); + } else { + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('g', 0)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*ROXCL_8"); + } + + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('v', 0)); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 12); + + if (_scene->_priorSceneId == 366) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _game._player._playerPos = Common::Point(78, 87); + _game._player._facing = FACING_SOUTH; + _scene->_sequences.addTimer(48, 70); + } else if (_scene->_priorSceneId == 321) { + _game._player._playerPos = Common::Point(153, 102); + _game._player._facing = FACING_SOUTH; + _game._player._stepEnabled = false; + _game._player._visible = false; + _vm->_sound->command(44); + int spriteIdx = (_globals[kSexOfRex] == REX_MALE) ? 1 : 2; + _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[spriteIdx], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 60); + } else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(291, 126); + + sceneEntrySound(); + _game.loadQuoteSet(0xFD, 0); +} + +void Scene316::step() { + if (_game._trigger == 60) { + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[1]); + _game._player._visible = true; + _game._player._stepEnabled = true; + } + + if (_game._trigger >= 70) { + switch (_game._trigger) { + case 70: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 5); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[6]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + break; + + case 71: { + int synxIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], synxIdx); + } + break; + + case 72: { + int synxIdx = _globals._sequenceIndexes[6]; + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 6, 9); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[6]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[6], synxIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 73); + } + break; + + case 73: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 12); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[6]); + + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 10, -2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[6]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 74); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 75); + break; + + case 74: { + int synxIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 12); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], synxIdx); + } + break; + + case 75: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[6]); + _game._player._stepEnabled = true; + _game._player._visible = true; + break; + + default: + break; + } + } +} + +void Scene316::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST)) { + if (_globals[kAfterHavoc]) + _game._player._walkOffScreenSceneId = 354; + else + _game._player._walkOffScreenSceneId = 304; + } +} + +void Scene316::actions() { + if (_action.isAction(VERB_CLIMB_INTO, NOUN_AIR_VENT)) { + if (_globals[kSexOfRex] == REX_FEMALE) + handleRoxInGrate(); + else + handleRexInGrate(); + } else if (_action.isAction(VERB_WALK_UP, NOUN_RAMP) || _action.isAction(VERB_WALK_ONTO, NOUN_PLATFORM)) { + switch (_game._trigger) { + case 0: + if (_globals[kCityFlooded]) { + _vm->_dialogs->show(31623); + } else { + _vm->_sound->command(45); + _game._player._stepEnabled = false; + _game._player._visible = false; + if (_globals[kSexOfRex] == REX_MALE) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], -1, 7); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + } else { + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + } + } + break; + + case 1: + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 8, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2); + _scene->_kernelMessages.reset(); + if (!_game._visitedScenes.exists(321)) + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(253)); + + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 2: + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 7, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], -2, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2); + _scene->_sequences.addTimer(48, 4); + break; + + case 3: + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -2, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); + _scene->_sequences.addTimer(48, 4); + break; + + case 4: + _scene->_nextSceneId = 321; + break; + } + } else if (_action.isAction(VERB_LOOK, NOUN_PLATFORM)) + _vm->_dialogs->show(31610); + else if (_action.isAction(VERB_LOOK, NOUN_STRANGE_DEVICE)) { + if (_game._visitedScenes.exists(321)) + _vm->_dialogs->show(31612); + else + _vm->_dialogs->show(31611); + } else if (_action.isAction(VERB_LOOK, NOUN_CONTROLS)) + _vm->_dialogs->show(31613); + else if (_action.isAction(VERB_LOOK, NOUN_EQUIPMENT)) + _vm->_dialogs->show(31614); + else if (_action.isAction(VERB_LOOK, NOUN_PANEL)) + _vm->_dialogs->show(31615); + else if (_action.isAction(VERB_LOOK, NOUN_MONITOR)) + _vm->_dialogs->show(31616); + else if (_action.isAction(VERB_LOOK, NOUN_RAMP)) + _vm->_dialogs->show(31617); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT)) + _vm->_dialogs->show(31618); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST)) { + if (!_globals[kAfterHavoc]) { + if (_game._difficulty != DIFFICULTY_EASY) + _vm->_dialogs->show(31620); + else + _vm->_dialogs->show(31619); + } + } else if (_action.isAction(VERB_LOOK, NOUN_FLOOR)) + _vm->_dialogs->show(31621); + else if (_action.isAction(VERB_LOOK, NOUN_SUPPORT)) + _vm->_dialogs->show(31622); + else + return; + + _action._inProgress = false; +} + + +/*------------------------------------------------------------------------*/ + +Scene318::Scene318(MADSEngine *vm) : Scene3xx(vm) { + _dropTimer = 0; + + _lastFrame = -1; + _animMode = -1; + _internCounter = -1; + _counter = -1; + + _dialogFl = false; + _internTalkingFl = false; + _internWalkingFl = false; + _internVisibleFl = false; + _explosionFl = false; + + _lastFrameCounter = 0; + + _subQuote2 = ""; +} + +void Scene318::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + s.syncAsUint32LE(_dropTimer); + + s.syncAsSint32LE(_lastFrame); + s.syncAsSint32LE(_animMode); + s.syncAsSint32LE(_internCounter); + s.syncAsSint32LE(_counter); + + s.syncAsByte(_dialogFl); + s.syncAsByte(_internTalkingFl); + s.syncAsByte(_internWalkingFl); + s.syncAsByte(_internVisibleFl); + s.syncAsByte(_explosionFl); + + s.syncAsUint32LE(_lastFrameCounter); + + s.syncString(_subQuote2); +} + +void Scene318::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene318::handleDialog() { + if (!_game._trigger) { + _game._player._stepEnabled = false; + handleRexDialogs(_action._activeAction._verbId); + } else if (_game._trigger == 2) { + int synxIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], synxIdx); + _vm->_sound->command(3); + _scene->_userInterface.setup(kInputLimitedSentences); + _game._player._stepEnabled = true; + } else { + if (_action._activeAction._verbId < 0x19C) + _dialog1.write(_action._activeAction._verbId, false); + + switch (_action._activeAction._verbId) { + case 0x191: + handleInternDialog(0x19E, 2, 9999999); + _dialog1.write(0x192, true); + break; + + case 0x192: + handleInternDialog(0x1A0, 5, 9999999); + _dialog1.write(0x193, true); + break; + + case 0x193: + handleInternDialog(0x1A5, 4, 9999999); + _dialog1.write(0x194, true); + break; + + case 0x194: + handleInternDialog(0x1A9, 6, 9999999); + _dialog1.write(0x195, true); + _dialog1.write(0x196, true); + _dialog1.write(0x19D, false); + break; + + case 0x195: + handleInternDialog(0x1AF, 7, 9999999); + if (!_dialog1.read(0x196)) + _dialog1.write(0x197, true); + break; + + case 0x196: + handleInternDialog(0x1B6, 5, 9999999); + if (!_dialog1.read(0x195)) + _dialog1.write(0x197, true); + break; + + case 0x197: + handleInternDialog(0x1BB, 5, 9999999); + break; + + case 0x198: + handleInternDialog(0x1C0, 5, 9999999); + _dialog1.write(0x19A, true); + break; + + case 0x199: + handleInternDialog(0x1C5, 3, 9999999); + break; + + case 0x19A: + handleInternDialog(0x1C8, 5, 9999999); + _dialog1.write(0x19B, true); + break; + + case 0x19B: + handleInternDialog(0x1CD, 3, 9999999); + break; + + case 0x19C: + case 0x19D: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121)); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 6, 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + + _dialogFl = false; + handleInternDialog(0x1D0, 1, 120); + if (_dialog1.read(0) || (_action._activeAction._verbId == 0x19D)) { + _explosionFl = true; + _internCounter = 3420; + } + break; + } + + if (_action._activeAction._verbId < 0x19C) { + _dialog1.start(); + _game._player._stepEnabled = true; + } + + } +} + +void Scene318::handleRexDialogs(int quote) { + _scene->_kernelMessages.reset(); + + Common::String curQuote = _game.getQuote(quote); + if (_vm->_font->getWidth(curQuote, _scene->_textSpacing) > 200) { + Common::String subQuote1; + _game.splitQuote(curQuote, subQuote1, _subQuote2); + _scene->_kernelMessages.add(Common::Point(138, 59), 0x1110, 32, 0, 240, subQuote1); + _scene->_kernelMessages.add(Common::Point(138, 73), 0x1110, 32, 1, 180, _subQuote2); + } else + _scene->_kernelMessages.add(Common::Point(138, 73), 0x1110, 32, 1, 120, curQuote); +} + +void Scene318::handleInternDialog(int quoteId, int quoteNum, uint32 timeout) { + int height = quoteNum * 14; + int posY; + if (height < 85) + posY = 87 - height; + else + posY = 2; + + int curQuoteId= quoteId; + + int maxWidth = 0; + for (int i = 0; i < quoteNum; i++) { + maxWidth = MAX(maxWidth, _vm->_font->getWidth(_game.getQuote(curQuoteId), -1)); + curQuoteId++; + } + + int posX = MIN(319 - maxWidth, 178 - (maxWidth >> 1)); + curQuoteId = quoteId; + + _scene->_kernelMessages.reset(); + _internTalkingFl = true; + + for (int i = 0; i < quoteNum; i++) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(180, 63); + _scene->_kernelMessages.add(Common::Point(posX, posY), 0xFDFC, 0, 0, timeout, _game.getQuote(curQuoteId)); + posY += 14; + curQuoteId++; + } +} + +void Scene318::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('k', -1)); + + if (_globals[kAfterHavoc]) { + _scene->loadAnimation(formAnimName('f', -1)); + _scene->_activeAnimation->_resetFlag = true; + } else if (!_globals[kHasSeenProfPyro]) { + _scene->_hotspots.activate(NOUN_PROFESSORS_GURNEY, false); + _scene->_hotspots.activate(NOUN_PROFESSOR, false); + _scene->_hotspots.activate(NOUN_TAPE_PLAYER, false); + } + + if (_game._objects.isInRoom(OBJ_SCALPEL)) { + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 0, 0, 120); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 4); + _scene->_dynamicHotspots.add(NOUN_SCALPEL, VERB_TAKE, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + } + + if (_scene->_priorSceneId == 357) + _game._player._playerPos = Common::Point(15, 110); + else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(214, 152); + + _dialog1.setup(0x47, 0x191, 0x192, 0x193, 0x194, 0x195, 0x196, 0x197, 0x198, 0x199, 0x19A, 0x19B, 0x19C, 0x19D, 0); + + if (!_game._visitedScenes._sceneRevisited) { + _dialog1.set(0x191, 0x198, 0x199, 0x19C, 0); + if (_game._widepipeCtr >= 2) + _dialog1.write(0x19D, true); + } + + if (_scene->_priorSceneId == 307) { + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->loadAnimation(formAnimName('a', -1), 60); + _animMode = 1; + } + + _lastFrame = 0; + _scene->_hotspots.activate(NOUN_INTERN, false); + + if (_scene->_priorSceneId != -2) { + _dialogFl = false; + _internWalkingFl = false; + _counter= 0; + _internCounter= 0; + _internVisibleFl = true; + _explosionFl = false; + } + + _game.loadQuoteSet(0x18C, 0x18D, 0x18E, 0x18F, 0x191, 0x192, 0x193, 0x194, 0x195, 0x196, + 0x197, 0x198, 0x199, 0x19A, 0x19B, 0x19C, 0x19E, 0x19E, 0x1A0, 0x1A1, 0x1A2, 0x1A3, + 0x1A4, 0x1A5, 0x1A6, 0x1A7, 0x1A8, 0x1A9, 0x1AA, 0x1AB, 0x1AC, 0x1AD, 0x1AE, 0x1AF, + 0x1B0, 0x1B1, 0x1B2, 0x1B3, 0x1B4, 0x1B5, 0x1B6, 0x1B7, 0x1B8, 0x1B9, 0x1BA, 0x1BB, + 0x1BC, 0x1BD, 0x1BE, 0x1BF, 0x1C0, 0x1C1, 0x1C2, 0x1C3, 0x1C4, 0x1C5, 0x1C6, 0x1C7, + 0x1C8, 0x1C9, 0x1CA, 0x1CB, 0x1CC, 0x1CD, 0x1CE, 0x1CF, 0x1D0, 0x1D1, 0x1D2, 0x1D3, + 0x190, 0x19D, 0); + + if ((_scene->_priorSceneId== -2) || (((_scene->_priorSceneId == 318) || (_scene->_priorSceneId == -1)) && (!_globals[kAfterHavoc]))) { + if (!_globals[kAfterHavoc]) { + _game._player._visible = false; + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('g', -1)); + _animMode = 2; + + if (_game._visitedScenes.exists(319) || !_internVisibleFl) { + _internVisibleFl = false; + _dialogFl = false; + } else { + _scene->loadAnimation(formAnimName('b', -1), 61); + _scene->_hotspots.activate(NOUN_INTERN, true); + } + + if (_dialogFl) { + _dialog1.start(); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 8); + } else + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + } + } + + if (_scene->_priorSceneId == 319) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _animMode = 4; + if (!_globals[kHasSeenProfPyro]) { + _scene->loadAnimation(formAnimName('d', -1), 64); + _globals[kHasSeenProfPyro] = true; + } else { + _scene->loadAnimation(formAnimName('e', -1), 64); + } + } + + _internTalkingFl = false; + _vm->_palette->setEntry(252, 63, 63, 10); + _vm->_palette->setEntry(253, 45, 45, 05); + + _dropTimer = _vm->_game->_scene._frameStartTime; + sceneEntrySound(); + + if (_dialogFl) + _vm->_sound->command(15); +} + +void Scene318::step() { + if ((_scene->_activeAnimation != nullptr) && (_animMode == 2)) { + if (_lastFrame != _scene->_activeAnimation->getCurrentFrame()) { + _lastFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextFrame = -1; + + switch (_lastFrame) { + case 20: + case 30: + case 40: + case 50: + case 60: + case 70: + case 80: + case 90: + case 100: + case 110: + case 120: + case 130: + case 140: + case 149: + if (_internWalkingFl) { + nextFrame = 149; + } else if (_internTalkingFl) { + nextFrame = 149; + } else if (_lastFrame == 149) { + nextFrame = 4; + } + break; + + case 151: + if (_internWalkingFl) + nextFrame = 183; + break; + + case 167: + case 184: + if (_internWalkingFl) { + nextFrame = 184; + } else if (!_internTalkingFl) { + nextFrame = 0; + } else if (_vm->getRandomNumber(1, 100) <= 50) { + nextFrame = 151; + } else { + nextFrame = 167; + } + + if (nextFrame == 184) { + handleInternDialog(0x1D1, 3, 240); + _scene->_hotspots.activate(NOUN_INTERN, false); + _internVisibleFl = false; + } + break; + } + + if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextFrame); + _lastFrame = nextFrame; + } + } + } + + switch (_game._trigger) { + case 60: + _vm->_sound->command(3); + _animMode = 2; + _scene->_reloadSceneFlag = true; + break; + + case 61: + _counter = 0; + break; + + case 62: + _scene->_nextSceneId = 319; + break; + + case 63: + _internTalkingFl = false; + break; + + case 64: + _vm->_sound->command(3); + _scene->_nextSceneId = 307; + break; + } + + uint32 tmpFrame = _vm->_events->getFrameCounter(); + long diffFrame = tmpFrame - _lastFrameCounter; + _lastFrameCounter = tmpFrame; + + if ((_animMode == 2) && !_internVisibleFl && _game._player._stepEnabled) { + if ((diffFrame >= 0) && (diffFrame <= 4)) + _counter += diffFrame; + else + _counter++; + + int extraCounter = _game._objects.isInInventory(OBJ_SCALPEL) ? 900 : 0; + + if (_counter + extraCounter >= 1800) { + _scene->freeAnimation(); + _game._player._stepEnabled = false; + _scene->loadAnimation(formAnimName('c', -1), 62); + _animMode = 3; + } + } else if ((_animMode == 2) && _explosionFl && _internVisibleFl && !_dialogFl + && !_internWalkingFl && (_game._screenObjects._inputMode != 1)) { + if ((diffFrame >= 0) && (diffFrame <= 4)) + _internCounter += diffFrame; + else + _internCounter++; + + if (_internCounter >= 3600) { + _vm->_sound->command(59); + _vm->_screen._shakeCountdown = 20; + _internWalkingFl = true; + } + } + + if ((_vm->_game->_scene._frameStartTime - _dropTimer) > 600) { + _vm->_sound->command(51); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 14, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _dropTimer = _vm->_game->_scene._frameStartTime; + } +} + +void Scene318::preActions() { + if (_game._player._needToWalk) + _game._player._needToWalk = _game._player._visible; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST)) + _game._player._walkOffScreenSceneId = 357; +} + +void Scene318::actions() { + if (_game._screenObjects._inputMode == 1) { + handleDialog(); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TALKTO, NOUN_INTERN)) { + switch (_game._trigger) { + case 0: { + _dialogFl = true; + _vm->_sound->command(15); + _game._player._stepEnabled = false; + handleRexDialogs(_vm->getRandomNumber(0x18C, 0x18E)); + + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 80); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121)); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 6, 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + + case 1: + _game._player._stepEnabled = true; + handleInternDialog(0x18F, 1, 9999999); + _dialog1.start(); + break; + + case 2: { + int oldIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 8); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx); + } + break; + + default: + break; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_SCALPEL) && (_game._objects.isInRoom(OBJ_SCALPEL) || _game._trigger)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 8, 2, 0, 80); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121)); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 2, 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 5, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + if (_internVisibleFl) + handleInternDialog(0x190, 1, 120); + else { + _game._objects.addToInventory(OBJ_SCALPEL); + _vm->_dialogs->showItem(OBJ_SCALPEL, 0x7C5D); + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + } + break; + + case 2: { + int oldIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx); + _scene->_sequences.addTimer(60, 3); + } + break; + + case 3: + _game._player._stepEnabled = true; + break; + } + _action._inProgress = false; + return; + } + + if (_game._player._visible) { + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH)) { + _scene->_nextSceneId = 407; + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_TAPE_PLAYER)) { + if (_game._objects.isInRoom(OBJ_AUDIO_TAPE)) { + _vm->_dialogs->showItem(OBJ_AUDIO_TAPE, 0x7C5B); + _game._objects.addToInventory(OBJ_AUDIO_TAPE); + } else + _vm->_dialogs->show(31834); + + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_TAPE_PLAYER)) { + if (_game._objects.isInRoom(OBJ_AUDIO_TAPE)) + _vm->_dialogs->show(31833); + else + _vm->_dialogs->show(31834); + + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_WALK_INTO, NOUN_DOCTORS_OFFICE)) { + _vm->_dialogs->show(31831); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_GURNEY)) { + _vm->_dialogs->show(31823); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_INSTRUMENT_TABLE)) { + _vm->_dialogs->show(31825); + _action._inProgress = false; + return; + } + } else { // Not visible + if (_action.isAction(VERB_LOOK, NOUN_GURNEY)) { + _vm->_dialogs->show(31822); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_INSTRUMENT_TABLE)) { + _vm->_dialogs->show(31824); + _action._inProgress = false; + return; + } + } + + if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(31810); + else if (_action.isAction(VERB_LOOK, NOUN_FLOOR)) + _vm->_dialogs->show(31811); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST)) + _vm->_dialogs->show(31812); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH)) + _vm->_dialogs->show(31813); + else if (_action.isAction(VERB_LOOK, NOUN_FAUCET)) + _vm->_dialogs->show(31814); + else if (_action.isAction(VERB_LOOK, NOUN_SINK)) + _vm->_dialogs->show(31815); + else if (_action.isAction(VERB_LOOK, NOUN_CONVEYOR_BELT)) + _vm->_dialogs->show(31816); + else if (_action.isAction(VERB_LOOK, NOUN_LARGE_BLADE)) + _vm->_dialogs->show(31817); + else if (_action.isAction(VERB_LOOK, NOUN_MONITOR)) + _vm->_dialogs->show(31818); + else if (_action.isAction(VERB_LOOK, NOUN_CABINETS)) + _vm->_dialogs->show(31819); + else if (_action.isAction(VERB_LOOK, NOUN_EQUIPMENT)) + _vm->_dialogs->show(31820); + else if (_action.isAction(VERB_LOOK, NOUN_SHELF)) + _vm->_dialogs->show(31821); + else if (_action.isAction(VERB_OPEN, NOUN_CABINETS)) + _vm->_dialogs->show(31829); + else if (_action.isAction(VERB_LOOK, NOUN_INTERN)) + _vm->_dialogs->show(31830); + else if (_action.isAction(VERB_LOOK, NOUN_PROFESSOR)) + _vm->_dialogs->show(31832); + else if (_action.isAction(VERB_LOOK, NOUN_PROFESSORS_GURNEY)) + _vm->_dialogs->show(31836); + else if (_action._lookFlag) { + if (_game._player._visible || _game._objects.isInInventory(OBJ_SCALPEL)) + _vm->_dialogs->show(31828); + else if (_internVisibleFl) + _vm->_dialogs->show(31826); + else + _vm->_dialogs->show(31827); + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene319::Scene319(MADSEngine *vm) : Scene3xx(vm) { + _animMode = -1; + _animFrame = -1; + _nextAction1 = -1; + _nextAction2 = -1; + _slacheMode = -1; + _slacheTopic = -1; + _slachePosY = -1; + + _slacheTalkingFl = false; + _slacheReady = false; + _slacheInitFl = false; + + _subQuote2 = ""; +} + +void Scene319::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + s.syncAsUint32LE(_animMode); + s.syncAsUint32LE(_animFrame); + s.syncAsUint32LE(_nextAction1); + s.syncAsUint32LE(_nextAction2); + s.syncAsUint32LE(_slacheMode); + s.syncAsUint32LE(_slacheTopic); + s.syncAsUint32LE(_slachePosY); + + s.syncAsByte(_slacheTalkingFl); + s.syncAsByte(_slacheReady); + s.syncAsByte(_slacheInitFl); + + s.syncString(_subQuote2); +} + +void Scene319::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene319::handleRexDialogues(int quote) { + _scene->_kernelMessages.reset(); + + Common::String curQuote = _game.getQuote(quote); + if (_vm->_font->getWidth(curQuote, _scene->_textSpacing) > 200) { + Common::String subQuote1; + _game.splitQuote(curQuote, subQuote1, _subQuote2); + _scene->_kernelMessages.add(Common::Point(160, 106), 0x1110, 32, 0, 120, subQuote1); + _scene->_kernelMessages.add(Common::Point(160, 120), 0x1110, 32, 1, 120, _subQuote2); + } else + _scene->_kernelMessages.add(Common::Point(160, 120), 0x1110, 32, 1, 120, curQuote); +} + +void Scene319::handleSlacheDialogs(int quoteId, int counter, uint32 timer) { + int curQuote = quoteId; + int posY = 5 + (_slachePosY * 14); + + for (int count = 0; count < counter; count++, curQuote++) { + _scene->_kernelMessages.add(Common::Point(8, posY), 0xFDFC, 0, 0, timer, _game.getQuote(curQuote)); + posY += 14; + } +} + +void Scene319::enter() { + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('e', 0)); + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('a', 0)); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 3)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('k', -1)); + + if (!_game._objects.isInInventory(OBJ_SCALPEL)) { + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + } + + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 18, 0, 0, 300); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 67, 0, 0, 377); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 173, 0, 0, 233); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 14); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 14); + + _globals._sequenceIndexes[0] = _scene->_sequences.startCycle(_globals._spriteIndexes[0], false, 1); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + + _dialog1.setup(0x43, 0x165, 0x166, 0x167, 0x168, 0x169, 0x16A, 0); + _dialog2.setup(0x44, 0x171, 0x172, 0x173, 0x174, 0x175, 0x176, 0); + _dialog3.setup(0x45, 0x17D, 0x17E, 0x17F, 0x180, 0x181, 0x182, 0x183, 0); + + if (_scene->_priorSceneId != -2) { + _dialog1.set(0x165, 0x166, 0x167, 0x168, 0); + _dialog2.set(0x171, 0x172, 0x173, 0x174, 0); + _dialog3.set(0x17D, 0x17E, 0x17F, 0x180, 0); + } + + _game.loadQuoteSet(0x15F, 0x160, 0x161, 0x162, 0x163, 0x164, 0x16B, 0x16C, 0x16D, + 0x16E, 0x16F, 0x170, 0x177, 0x178, 0x178, 0x17A, 0x17B, 0x17C, 0x165, 0x166, + 0x167, 0x168, 0x169, 0x16A, 0x171, 0x172, 0x173, 0x174, 0x175, 0x176, 0x17D, + 0x17E, 0x17F, 0x180, 0x181, 0x182, 0x183, 0x184, 0x185, 0x186, 0x187, 0x188, + 0x189, 0x18A, 0x18B, 0); + + _vm->_palette->setEntry(252, 63, 30, 2); + _vm->_palette->setEntry(253, 45, 15, 1); + + _slachePosY = 0; + _slacheInitFl = false; + _slacheTalkingFl = false; + _slacheReady = false; + _animFrame = 0; + + _scene->loadAnimation(formAnimName('b', 0)); + + if (_scene->_priorSceneId != -2) { + _animMode = 1; + _nextAction1 = 2; + _nextAction2 = 2; + _slacheMode = 1; + _slacheTopic = 1; + _slacheInitFl = true; + + if (_globals[kRexHasMetSlache]) { + handleSlacheDialogs(VERB_WALK_OUTSIDE, 2, 9999999); + _slachePosY = 3; + } else { + handleSlacheDialogs(0x186, 4, 9999999); + _slachePosY = 5; + } + } + + switch (_slacheTopic) { + case 1: + handleSlacheDialogs(0x15F, 2, 9999999); + _dialog1.start(); + break; + + case 2: + handleSlacheDialogs(0x16B, 2, 9999999); + _dialog2.start(); + break; + + case 3: + handleSlacheDialogs(0x177, 2, 9999999); + _dialog3.start(); + break; + + default: + break; + } + + _slachePosY = 0; + sceneEntrySound(); +} + +void Scene319::step() { + if (_scene->_activeAnimation == nullptr) + return; + + if (_animFrame != _scene->_activeAnimation->getCurrentFrame()) { + _animFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextFrame = -1; + if (_animMode == 1) { + switch (_animFrame) { + case 6: + _slacheTalkingFl = true; + break; + + case 29: + _slacheReady = true; + break; + + case 39: + if (_slacheInitFl) { + _slacheInitFl = false; + if (_nextAction1 == 2) + nextFrame = 0; + } else if (_nextAction1 == 2) + _nextAction1 = 1; + break; + + case 50: + case 60: + case 70: + case 85: + if (_nextAction1 == 2) + nextFrame = 0; + else if (_nextAction1 == 3) { + nextFrame = 85; + _slacheTalkingFl = true; + } else if (_animFrame == 85) { + if (!_game._player._stepEnabled) + _slacheTalkingFl = true; + nextFrame = 40; + } + break; + + case 115: + _slacheReady = true; + break; + + case 129: + if (_nextAction1 == 3) { + nextFrame = 115; + if (!_game._player._stepEnabled) + _slacheTalkingFl = true; + } + break; + + case 145: + nextFrame = 40; + break; + + default: + break; + } + + if ((_animFrame > 40) && (_animFrame < 85) && (nextFrame < 0)) { + switch (_nextAction1) { + case 4: + _animFrame = 0; + _scene->freeAnimation(); + _animMode = 2; + _scene->loadAnimation(formAnimName('b', 3), 70); + break; + + case 5: + _animFrame = 0; + _scene->freeAnimation(); + _animMode = 3; + _scene->loadAnimation(formAnimName('b', 4), 71); + break; + + case 6: + _animFrame = 0; + _scene->freeAnimation(); + _animMode = 4; + _scene->loadAnimation(formAnimName('b', 5), 72); + break; + + default: + break; + } + + if (!_animFrame) { + _scene->_sequences.remove(_globals._sequenceIndexes[0]); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + + for (int i = 0; i <= 1; i++) { + _globals._sequenceIndexes[i] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[i], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[i], 1, 7); + } + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_EXPIRE, 0, 73); + } + } + } + + if (_animMode == 2) { + if (_animFrame == 13) + _vm->_screen._shakeCountdown = 40; + + if (_animFrame == 16) + _vm->_screen._shakeCountdown = 1; + } + + if (_animMode == 3) { + if (_animFrame == 11) + _vm->_screen._shakeCountdown = 60; + + if (_animFrame == 18) + _vm->_screen._shakeCountdown = 1; + } + + if ((_animMode == 4) && (_animFrame == 16)) + _vm->_screen._shakeCountdown = 80; + + if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextFrame); + _animFrame = nextFrame; + } + } + + switch (_game._trigger) { + case 70: + case 71: + _animMode = 1; + _nextAction1 = _nextAction2; + _animFrame = 0; + _scene->freeAnimation(); + _scene->loadAnimation(formAnimName('b', 0)); + if (_nextAction1 == 3) + _scene->_activeAnimation->setCurrentFrame(85); + else if (_nextAction1 == 1) + _scene->_activeAnimation->setCurrentFrame(40); + + _animFrame = _scene->_activeAnimation->getCurrentFrame(); + _slacheTalkingFl = true; + _vm->_screen._shakeCountdown = 1; + + for (int i = 0; i <= 1; i++) { + int oldIdx = _globals._sequenceIndexes[i]; + _scene->_sequences.remove(_globals._sequenceIndexes[i]); + _globals._sequenceIndexes[i] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[i], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[i], 8, 13); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[i], oldIdx); + } + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_EXPIRE, 0, 74); + break; + + case 72: + _vm->_palette->setColorFlags(0xFF, 0, 0); + _vm->_palette->setColorValues(0, 0, 0); + _vm->_palette->fadeOut(_vm->_palette->_mainPalette, nullptr, 18, 228, + 248, 0, 1, 16); + _vm->_screen._shakeCountdown = 1; + _scene->_reloadSceneFlag = true; + break; + + case 73: + for (int i = 0; i <= 1; i++) { + int oldIdx = _globals._sequenceIndexes[i]; + _scene->_sequences.remove(_globals._sequenceIndexes[i]); + _globals._sequenceIndexes[i] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[i], false, 8, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[i], 6, 7); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[i], oldIdx); + } + break; + + case 74: + for (int i = 0; i <= 1; i++) { + int oldIdx = _globals._sequenceIndexes[i]; + _scene->_sequences.remove(_globals._sequenceIndexes[i]); + _globals._sequenceIndexes[i] = _scene->_sequences.startCycle(_globals._spriteIndexes[i], false, 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[i], oldIdx); + } + break; + + default: + break; + } +} + +void Scene319::actions() { + if (_game._trigger == 0) { + _game._player._stepEnabled = false; + handleRexDialogues(_action._activeAction._verbId); + } else { + if ((_action._activeAction._verbId == 0x165) || (_action._activeAction._verbId == 0x166)) { + if (_game._trigger == 1) { + _nextAction1 = 3; + _slacheTalkingFl = false; + _slacheMode = 1; + _slacheTopic = 2; + } + + if (!_slacheTalkingFl) { + _scene->_sequences.addTimer(4, 2); + } else { + handleSlacheDialogs(0x16B, 2, 9999999); + _dialog2.start(); + _game._player._stepEnabled = true; + } + } + + if ((_action._activeAction._verbId == 0x171) || (_action._activeAction._verbId == 0x172)) { + if (_game._trigger == 1) { + _nextAction1 = 2; + _slacheTalkingFl = false; + _slacheMode = 1; + _slacheTopic = 3; + } + + if (!_slacheTalkingFl) { + _scene->_sequences.addTimer(4, 2); + } else { + handleSlacheDialogs(0x177, 2, 9999999); + _dialog3.start(); + _game._player._stepEnabled = true; + } + } + + if ((_action._activeAction._verbId == 0x17D) || (_action._activeAction._verbId == 0x17E)) { + if (_game._trigger == 1) { + _nextAction1 = 3; + _slacheTalkingFl = false; + _slacheReady = false; + _slacheMode = 1; + _slacheTopic = 1; + } + + if (!_slacheTalkingFl) { + _scene->_sequences.addTimer(4, 2); + } else { + if (_game._trigger == 2) + handleSlacheDialogs(0x184, 2, 180); + + if (!_slacheReady) { + _scene->_sequences.addTimer(120, 3); + } else { + _globals[kRexHasMetSlache] = true; + _scene->_nextSceneId = 318; + } + } + } + + if ((_action._activeAction._verbId == 0x168) || (_action._activeAction._verbId == 0x174) || + (_action._activeAction._verbId == 0x180) || (_action._activeAction._verbId == 0x169) || + (_action._activeAction._verbId == 0x175) || (_action._activeAction._verbId == 0x181) || + (_action._activeAction._verbId == 0x16A) || (_action._activeAction._verbId == 0x176) || + (_action._activeAction._verbId == 0x182) || (_action._activeAction._verbId == 0x183) || + (_action._activeAction._verbId == 0x167) || (_action._activeAction._verbId == 0x173) || + (_action._activeAction._verbId == 0x17F)) { + + bool addDialogLine = !((_action._activeAction._verbId == 0x167) || (_action._activeAction._verbId == 0x173) || + (_action._activeAction._verbId == 0x17F) || (_action._activeAction._verbId == 0x16A) || + (_action._activeAction._verbId == 0x176) || (_action._activeAction._verbId == 0x182) || + (_action._activeAction._verbId == 0x183)); + + int addVerbId = _action._activeAction._verbId + 1; + if ((addVerbId == 0x182) && (_game._storyMode != STORYMODE_NAUGHTY)) + addVerbId = 0x183; + + if (_slacheMode == 1) { + if (_game._trigger == 1) { + _nextAction2 = _nextAction1; + _nextAction1 = 4; + } + + if (_nextAction1 != _nextAction2) { + _scene->_sequences.addTimer(4, 2); + } else { + Conversation *curDialog; + int nextDocQuote; + if ((_action._activeAction._verbId == 0x168) || (_action._activeAction._verbId == 0x167)) { + curDialog = &_dialog1; + nextDocQuote = 0x161; + } else if ((_action._activeAction._verbId == 0x174) || (_action._activeAction._verbId == 0x1753)) { + nextDocQuote = 0x16D; + curDialog = &_dialog2; + } else { + nextDocQuote = 0x179; + curDialog = &_dialog3; + } + + handleSlacheDialogs(nextDocQuote, 2, 9999999); + if (addDialogLine) { + curDialog->write(_action._activeAction._verbId, false); + curDialog->write(addVerbId, true); + } + + curDialog->start(); + _game._player._stepEnabled = true; + _slacheMode = 2; + } + } else if (_slacheMode == 2) { + if (_game._trigger == 1) { + _nextAction2 = _nextAction1; + _nextAction1 = 5; + } + + if (_nextAction1 != _nextAction2) { + _scene->_sequences.addTimer(4, 2); + } else { + Conversation *curDialog; + int nextDocQuote; + if ((_action._activeAction._verbId == 0x168) || (_action._activeAction._verbId == 0x169) || (_action._activeAction._verbId == 0x167)) { + curDialog = &_dialog1; + nextDocQuote = 0x163; + } else if ((_action._activeAction._verbId == 0x174) || (_action._activeAction._verbId == 0x175) || (_action._activeAction._verbId == 0x173)) { + nextDocQuote = 0x16F; + curDialog = &_dialog2; + } else { + nextDocQuote = 0x17B; + curDialog = &_dialog3; + } + + handleSlacheDialogs(nextDocQuote, 2, 9999999); + if (addDialogLine) { + curDialog->write(_action._activeAction._verbId, false); + curDialog->write(addVerbId, true); + } + + curDialog->start(); + _game._player._stepEnabled = true; + _slacheMode = 3; + } + } else { + _nextAction2 = _nextAction1; + _nextAction1 = 6; + } + } + } + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene320::Scene320(MADSEngine *vm) : Scene300s(vm) { + _blinkFl = false; + _flippedFl = false; + + _buttonId = -1; + _lastFrame = -1; + _leftItemId = -1; + _posX = -1; + _rightItemId = -1; +} + +void Scene320::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + s.syncAsByte(_blinkFl); + s.syncAsByte(_flippedFl); + + s.syncAsSint32LE(_buttonId); + s.syncAsSint32LE(_lastFrame); + s.syncAsSint32LE(_leftItemId); + s.syncAsSint32LE(_posX); + s.syncAsSint32LE(_rightItemId); +} + +void Scene320::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene320::setRightView(int view) { + if (_rightItemId < 8) _scene->_sequences.remove(_globals._sequenceIndexes[10]); + + int spriteNum; + switch (view) { + case 0: + spriteNum = 16; + break; + + case 1: + spriteNum = 14; + break; + + case 2: + spriteNum = 17; + break; + + case 3: + spriteNum = 15; + break; + + default: + spriteNum = view + 6; + break; + } + + if (view != 8) { + _globals._sequenceIndexes[10] = _scene->_sequences.startCycle(_globals._spriteIndexes[spriteNum], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 0); + } + + _globals[kRightView320] = _rightItemId = view; +} + +void Scene320::setLeftView(int view) { + if (_leftItemId < 10) + _scene->_sequences.remove(_globals._sequenceIndexes[0]); + + if (view != 10) { + _globals._sequenceIndexes[0] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[view], false, 6, 0, 0, 18); + _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 0); + if (!_blinkFl) + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[0], 2, 2); + } + + _leftItemId = view; +} + +void Scene320::handleButtons() { + switch(_action._activeAction._objectNameId) { + case 0x2DD: + _buttonId = 5; + break; + + case 0x2DE: + _buttonId = 4; + break; + + case 0x2E0: + _buttonId = 6; + break; + + case 0x2E1: + _buttonId = 7; + break; + + case 0x2E2: + _buttonId = 8; + break; + + case 0x2E3: + _buttonId = 9; + break; + + case 0x2E4: + _buttonId = 10; + break; + + case 0x2E5: + _buttonId = 11; + break; + + case 0x2E6: + _buttonId = 12; + break; + + case 0x2E7: + _buttonId = 13; + break; + + case 0x2E8: + _buttonId = 0; + break; + + case 0x2E9: + _buttonId = 1; + break; + + case 0x2EA: + _buttonId = 2; + break; + + case 0x2EB: + _buttonId = 3; + break; + + default: + break; + } + + if (_buttonId <= 3) { + _posX = (8 * _buttonId) - 2; + _flippedFl = true; + } else if (_buttonId <= 5) { + _posX = (13 * _buttonId) - 14; + _flippedFl = true; + } else { + _posX = (8 * _buttonId) + 98; + _flippedFl = false; + } +} + +void Scene320::enter() { + _blinkFl = true; + _rightItemId = 8; + _leftItemId = 10; + _lastFrame = 0; + + for (int i = 0; i < 10; i++) + _globals._spriteIndexes[i] = _scene->_sprites.addSprites(formAnimName('M', i)); + + for (int i = 0; i < 8; i++) + _globals._spriteIndexes[10 + i] = _scene->_sprites.addSprites(formAnimName('N', i)); + + _globals._spriteIndexes[18] = _scene->_sprites.addSprites("*REXHAND"); + _game._player._visible = false; + + setRightView(_globals[kRightView320]); + setLeftView(0); + + _vm->_palette->setEntry(252, 63, 30, 20); + _vm->_palette->setEntry(253, 45, 15, 10); + + sceneEntrySound(); +} + +void Scene320::step() { + if (_scene->_activeAnimation != nullptr) { + if (_lastFrame != _scene->_activeAnimation->getCurrentFrame()) { + _lastFrame = _scene->_activeAnimation->getCurrentFrame(); + switch (_lastFrame) { + case 95: + _blinkFl = true; + setLeftView(9); + _vm->_sound->command(41); + break; + + case 139: + _blinkFl = false; + setLeftView(9); + break; + + case 191: + _scene->_kernelMessages.add(Common::Point(1, 1), 0xFDFC, 0, 0, 60, _game.getQuote(0xFE)); + break; + + case 417: + case 457: + _vm->_screen._shakeCountdown = 40; + _vm->_sound->command(59); + break; + + case 430: + _blinkFl = true; + setLeftView(4); + break; + + default: + break; + } + } + } + + if (_game._trigger == 70) { + _globals[kAfterHavoc] = true; + _globals[kTeleporterRoom + 1] = 351; + _scene->_nextSceneId = 361; + } +} + +void Scene320::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(32011); + else if ((_action.isAction(VERB_PRESS) || _action.isAction(VERB_PUSH)) && + (_action.isObject(NOUN_LEFT_1_KEY) || _action.isObject(NOUN_LEFT_2_KEY) || _action.isObject(NOUN_LEFT_3_KEY) || _action.isObject(NOUN_LEFT_4_KEY) || + _action.isObject(NOUN_GREEN_BUTTON) || _action.isObject(NOUN_RED_BUTTON) || _action.isObject(NOUN_RIGHT_1_KEY) || _action.isObject(NOUN_RIGHT_2_KEY) || + _action.isObject(NOUN_RIGHT_3_KEY) || _action.isObject(NOUN_RIGHT_4_KEY) || _action.isObject(NOUN_RIGHT_5_KEY) || _action.isObject(NOUN_RIGHT_6_KEY) || + _action.isObject(NOUN_RIGHT_7_KEY) || _action.isObject(NOUN_RIGHT_8_KEY) + )) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + handleButtons(); + _globals._sequenceIndexes[18] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[18], _flippedFl, 4, 2, 0, 0); + _scene->_sequences.setScale(_globals._sequenceIndexes[18], 60); + _scene->_sequences.setPosition(_globals._sequenceIndexes[18], Common::Point(_posX, 170)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[18], 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[18], SEQUENCE_TRIGGER_LOOP, 0, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[18], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + if (_buttonId >= 6) { + _vm->_sound->command(60); + setRightView(_buttonId - 6); + } + if (_buttonId == 4) { + _vm->_sound->command(38); + if (_leftItemId == 3) + setLeftView(0); + else + setLeftView(3); + } + if (_buttonId == 5) { + _vm->_sound->command(38); + if (_leftItemId == 1) + setLeftView(2); + else + setLeftView(1); + } + if (_buttonId <= 3) { + _vm->_sound->command(60); + setLeftView(_buttonId + 5); + } + break; + + case 2: + _game._player._stepEnabled = true; + if (_buttonId == 5) { + if (_leftItemId == 2) { + _game._player._stepEnabled = false; + setRightView(8); + setLeftView(10); + _scene->_kernelMessages.reset(); + _scene->resetScene(); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('m', 2)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('m', 4)); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('m', 9)); + _blinkFl = false; + setLeftView(2); + _game.loadQuoteSet(0xFE, 0); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->loadAnimation(formAnimName('a', -1), 70); + _vm->_sound->command(17); + } + } + break; + + default: + break; + } + } else if (_action.isAction(VERB_LEAVE, NOUN_SECURITY_STATION)) + _scene->_nextSceneId = 311; + else if (_action.isAction(VERB_LOOK, NOUN_RIGHT_MONITOR)) + _vm->_dialogs->show(32001); + else if (_action.isAction(VERB_LOOK, NOUN_LEFT_MONITOR)) + _vm->_dialogs->show(32002); + else if (_action.isAction(VERB_LOOK, NOUN_DESK)) + _vm->_dialogs->show(32003); + else if (_action.isAction(VERB_LOOK, NOUN_SECURITY_STATION)) + _vm->_dialogs->show(32004); + else if (_action.isAction(VERB_LOOK, NOUN_MUG)) + _vm->_dialogs->show(32005); + else if (_action.isAction(VERB_LOOK, NOUN_DOUGHNUT)) + _vm->_dialogs->show(32006); + else if (_action.isAction(VERB_LOOK, NOUN_MAGAZINE)) + _vm->_dialogs->show(32006); + else if (_action.isAction(VERB_LOOK, NOUN_PAPER_FOOTBALL)) + _vm->_dialogs->show(32008); + else if (_action.isAction(VERB_LOOK, NOUN_NEWSPAPER)) + _vm->_dialogs->show(32009); + else if (_action.isAction(VERB_LOOK, NOUN_CLIPBOARD)) + _vm->_dialogs->show(32010); + else if (_action.isAction(VERB_TAKE, NOUN_MUG)) + _vm->_dialogs->show(32012); + else if (_action.isAction(VERB_TAKE, NOUN_CLIPBOARD)) + _vm->_dialogs->show(32013); + else if (_action.isAction(VERB_TAKE, NOUN_DOUGHNUT) || _action.isAction(VERB_EAT, NOUN_DOUGHNUT)) + _vm->_dialogs->show(32014); + else if (_action.isAction(VERB_TAKE, NOUN_PAPER_FOOTBALL)) + _vm->_dialogs->show(32015); + else if (_action.isAction(VERB_TAKE, NOUN_MAGAZINE)) + _vm->_dialogs->show(32016); + else if (_action.isAction(VERB_TAKE, NOUN_NEWSPAPER)) + _vm->_dialogs->show(32017); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene321::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene321::enter() { + _game._player._visible = false; + _game._player._stepEnabled = false; + + _scene->_userInterface.emptyConversationList(); + _scene->_userInterface.setup(kInputConversation); + + int suffixNum; + if (_globals[kSexOfRex] == REX_FEMALE) { + _globals[kSexOfRex] = REX_MALE; + suffixNum = 1; + } else { + _globals[kSexOfRex] = REX_FEMALE; + suffixNum = _game._visitedScenes._sceneRevisited ? 2 : 0; + } + + _scene->loadAnimation(formAnimName('g', suffixNum), 60); + sceneEntrySound(); +} + +void Scene321::step() { + if (_scene->_activeAnimation != nullptr) { + if ((_scene->_activeAnimation->getCurrentFrame() >= 260) && (_globals[kSexOfRex] == REX_MALE) && (_game._storyMode >= STORYMODE_NICE)) + _scene->_nextSceneId = 316; + } + + if (_game._trigger == 60) + _scene->_nextSceneId = 316; +} + +/*------------------------------------------------------------------------*/ + +void Scene322::setup() { + _game._player._spritesPrefix = ""; + // The original is calling scene3xx_setAAName() + _game._aaName = Resources::formatAAName(4); +} + +void Scene322::enter() { + if (_globals[kSexOfRex] == REX_MALE) + _handSpriteId = _scene->_sprites.addSprites("*REXHAND"); + else + _handSpriteId = _scene->_sprites.addSprites("*ROXHAND"); + + teleporterEnter(); + + // The original is using scene3xx_sceneEntrySound() + if (!_vm->_musicFlag) + _vm->_sound->command(2); + else + _vm->_sound->command(10); +} + +void Scene322::step() { + teleporterStep(); +} + +void Scene322::actions() { + if (_action._lookFlag) { + _vm->_dialogs->show(32214); + _action._inProgress = false; + return; + } + + if (teleporterActions()) { + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_VIEWPORT) || _action.isAction(VERB_PEER_THROUGH, NOUN_VIEWPORT)) + _vm->_dialogs->show(32210); + else if (_action.isAction(VERB_LOOK, NOUN_KEYPAD)) + _vm->_dialogs->show(32211); + else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY)) + _vm->_dialogs->show(32212); + else if (_action.isAction(VERB_LOOK, NOUN_0_KEY) || _action.isAction(VERB_LOOK, NOUN_1_KEY) + || _action.isAction(VERB_LOOK, NOUN_2_KEY) || _action.isAction(VERB_LOOK, NOUN_3_KEY) + || _action.isAction(VERB_LOOK, NOUN_4_KEY) || _action.isAction(VERB_LOOK, NOUN_5_KEY) + || _action.isAction(VERB_LOOK, NOUN_6_KEY) || _action.isAction(VERB_LOOK, NOUN_7_KEY) + || _action.isAction(VERB_LOOK, NOUN_8_KEY) || _action.isAction(VERB_LOOK, NOUN_9_KEY) + || _action.isAction(VERB_LOOK, NOUN_SMILE_KEY) || _action.isAction(VERB_LOOK, NOUN_ENTER_KEY) + || _action.isAction(VERB_LOOK, NOUN_FROWN_KEY)) + _vm->_dialogs->show(32213); + else if (_action.isAction(VERB_LOOK, NOUN_DEVICE)) + _vm->_dialogs->show(32214); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene351::setup() { + if (_scene->_currentSceneId == 391) + _globals[kSexOfRex] = REX_MALE; + + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene351::enter() { + _globals[kAfterHavoc] = -1; + _globals[kTeleporterRoom + 1] = 351; + + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', -1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*ROXRC_7"); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXRD_7"); + + if (_game._objects.isInRoom(OBJ_CREDIT_CHIP)) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 4); + } else + _scene->_hotspots.activate(NOUN_CREDIT_CHIP, false); + + if (_scene->_priorSceneId == 352) + _game._player._playerPos = Common::Point(148, 152); + else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(207, 81); + _game._player._facing = FACING_NORTH; + } + + if (_globals[kTeleporterCommand]) { + _game._player._visible = false; + _game._player._stepEnabled = false; + + char sepChar = 'a'; + if (_globals[kSexOfRex] != REX_MALE) + sepChar = 'b'; + + int suffixNum = -1; + int trigger = 0; + + switch (_globals[kTeleporterCommand]) { + case 1: + suffixNum = 0; + trigger = 60; + _globals[kTeleporterCommand] = true; + break; + + case 2: + suffixNum = 1; + trigger = 61; + break; + + case 3: + case 4: + _game._player._visible = true; + _game._player._stepEnabled = true; + _game._player._turnToFacing = FACING_SOUTH; + suffixNum = -1; + break; + + default: + break; + } + + _globals[kTeleporterCommand] = 0; + + if (suffixNum >= 0) + _scene->loadAnimation(formAnimName(sepChar, suffixNum), trigger); + } + + sceneEntrySound(); +} + +void Scene351::step() { + if (_game._trigger == 60) { + _game._player._stepEnabled = true; + _game._player._visible = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._turnToFacing = FACING_SOUTH; + } + + if (_game._trigger == 61) { + _globals[kTeleporterCommand] = 1; + _scene->_nextSceneId = _globals[kTeleporterDestination]; + _scene->_reloadSceneFlag = true; + } +} + +void Scene351::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(35121); + else if (_action.isAction(VERB_STEP_INTO, NOUN_TELEPORTER)) + _scene->_nextSceneId = 322; + else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH)) + _scene->_nextSceneId = 352; + else if (_action.isAction(VERB_TAKE, NOUN_CREDIT_CHIP)) { + if (_game._trigger || !_game._objects.isInInventory(OBJ_CREDIT_CHIP)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + if (_globals[kSexOfRex] == REX_FEMALE) { + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 5, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 5, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } else { + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 5, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 6, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + + case 1: + _scene->_hotspots.activate(NOUN_CREDIT_CHIP, false); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _game._objects.addToInventory(OBJ_CREDIT_CHIP); + break; + + case 2: + _game._player._visible = true; + _game._player._stepEnabled = true; + _vm->_dialogs->showItem(OBJ_CREDIT_CHIP, 0x32F); + break; + } + } + } else if (_action.isAction(VERB_LOOK, NOUN_VIEW_SCREEN)) + _vm->_dialogs->show(35110); + else if (_action.isAction(VERB_LOOK, NOUN_RIP_IN_FLOOR)) + _vm->_dialogs->show(35111); + else if (_action.isAction(VERB_LOOK, NOUN_FIRE_HYDRANT)) + _vm->_dialogs->show(35112); + else if (_action.isAction(VERB_LOOK, NOUN_GUARD)) { + if (_game._objects[0xF]._roomNumber == 351) + _vm->_dialogs->show(35114); + else + _vm->_dialogs->show(35113); + } else if (_action.isAction(VERB_LOOK, NOUN_EQUIPMENT)) + _vm->_dialogs->show(35115); + else if (_action.isAction(VERB_LOOK, NOUN_DESK)) + _vm->_dialogs->show(35116); + else if (_action.isAction(VERB_LOOK, NOUN_MACHINE)) + _vm->_dialogs->show(35117); + else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER)) + _vm->_dialogs->show(35118); + else if (_action.isAction(VERB_LOOK, NOUN_CONTROL_PANEL)) + _vm->_dialogs->show(35119); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH)) + _vm->_dialogs->show(35120); + else if (_action.isAction(VERB_LOOK, NOUN_POLE)) + _vm->_dialogs->show(35122); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene352::Scene352(MADSEngine *vm) : Scene3xx(vm) { + _vaultOpenFl = false; + _mustPutArmDownFl = false; + _leaveRoomFl = false; + + _tapePlayerHotspotIdx = -1; + _hotspot1Idx = -1; + _hotspot2Idx = -1; + _lampHostpotIdx = -1; + _commonSequenceIdx = -1; + _commonSpriteIndex = -1; +} + +void Scene352::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + s.syncAsByte(_vaultOpenFl); + s.syncAsByte(_mustPutArmDownFl); + s.syncAsByte(_leaveRoomFl); + + s.syncAsSint32LE(_tapePlayerHotspotIdx); + s.syncAsSint32LE(_hotspot1Idx); + s.syncAsSint32LE(_hotspot2Idx); + s.syncAsSint32LE(_lampHostpotIdx); + s.syncAsSint32LE(_commonSequenceIdx); + s.syncAsSint32LE(_commonSpriteIndex); +} + +void Scene352::setup() { + setPlayerSpritesPrefix(); + setAAName(); + + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_YOUR_STUFF); + _scene->addActiveVocab(NOUN_OTHER_STUFF); + _scene->addActiveVocab(NOUN_LAMP); +} + +void Scene352::putArmDown(bool corridorExit, bool doorwayExit) { + switch (_game._trigger) { + case 0: + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 60, _game.getQuote(0xFF)); + _scene->_sequences.addTimer(48, 1); + break; + + case 1: + _game._player._stepEnabled = false; + _game._player._visible = false; + if (_globals[kSexOfRex] == REX_FEMALE) { + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 5, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 5, 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + } else { + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 5, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 6, 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + } + break; + + case 2: { + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 0, 0, 0); + int idx = _scene->_dynamicHotspots.add(NOUN_GUARDS_ARM, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(230, 117), FACING_NORTHWEST); + _scene->changeVariant(0); + } + break; + + case 3: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x100)); + _game._objects.setRoom(OBJ_GUARDS_ARM, _scene->_currentSceneId); + _game._player._visible = true; + if (corridorExit) + _scene->_sequences.addTimer(48, 6); + else if (doorwayExit) + _scene->_sequences.addTimer(48, 4); + else { + _mustPutArmDownFl = false; + _game._player._stepEnabled = true; + } + break; + + case 4: + _game._player.walk(Common::Point(116, 107), FACING_NORTH); + _game._player._stepEnabled = true; + _mustPutArmDownFl = false; + _scene->_sequences.addTimer(180, 5); + _leaveRoomFl = true; + break; + + case 5: + if (_leaveRoomFl) + _scene->_nextSceneId = 351; + + break; + + case 6: + _game._player.walk(Common::Point(171, 152), FACING_SOUTH); + _game._player._stepEnabled = true; + _mustPutArmDownFl = false; + _scene->_sequences.addTimer(180, 7); + _leaveRoomFl = true; + break; + + case 7: + if (_leaveRoomFl) + _scene->_nextSceneId = 353; + + break; + + default: + break; + } +} + +void Scene352::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*RM302x0"); + _globals._spriteIndexes[13] = _scene->_sprites.addSprites("*RM302x2"); + _globals._spriteIndexes[12] = _scene->_sprites.addSprites("*RM302x3"); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('g', -1)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('b', -1)); + + + if (_globals[kSexOfRex] == REX_FEMALE) { + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*ROXRC_7"); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites("*ROXRC_6"); + _globals._spriteIndexes[15] = _scene->_sprites.addSprites("*ROXRC_9"); + _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('a', 3)); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('a', 2)); + } else { + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXRD_7"); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites("*RXRC_6"); + _globals._spriteIndexes[14] = _scene->_sprites.addSprites("*RXMRC_9"); + _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('a', 0)); + } + + _leaveRoomFl = false; + + if (_game._objects.isInRoom(OBJ_TAPE_PLAYER)) { + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 12, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 5); + int idx = _scene->_dynamicHotspots.add(NOUN_TAPE_PLAYER, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _tapePlayerHotspotIdx = _scene->_dynamicHotspots.setPosition(idx, Common::Point(84, 145), FACING_WEST); + } + + _vaultOpenFl = false; + + if (_scene->_priorSceneId != -2) { + _mustPutArmDownFl = false; + if (!_game._visitedScenes._sceneRevisited) + _globals[kHaveYourStuff] = false; + } + + if (_game._objects.isInRoom(OBJ_GUARDS_ARM)) { + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 0, 0, 0); + int idx = _scene->_dynamicHotspots.add(NOUN_GUARDS_ARM, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(230, 117), FACING_NORTHWEST); + } else + _mustPutArmDownFl = true; + + if (_scene->_priorSceneId == 353) + _game._player._playerPos = Common::Point(171, 155); + else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(116, 107); + + sceneEntrySound(); + + _game.loadQuoteSet(0xFF, 0x100, 0x101, 0x102, 0x103, 0); +} + +void Scene352::preActions() { + _leaveRoomFl = false; + + if (_action.isAction(VERB_OPEN, NOUN_VAULT)) + _game._player.walk(Common::Point(266, 111), FACING_NORTHEAST); + + if (_vaultOpenFl && !_action.isObject(NOUN_VAULT) && !_action.isObject(NOUN_LAMP) && !_action.isObject(NOUN_OTHER_STUFF) && !_action.isObject(NOUN_YOUR_STUFF)) { + if (_globals[kHaveYourStuff]) { + _commonSpriteIndex = _globals._spriteIndexes[13]; + _commonSequenceIdx = _globals._sequenceIndexes[13]; + } else { + _commonSpriteIndex = _globals._spriteIndexes[1]; + _commonSequenceIdx = _globals._sequenceIndexes[1]; + } + + switch (_game._trigger) { + case 0: + if (_game._player._needToWalk) { + _game._player._stepEnabled = false; + _scene->_sequences.remove(_commonSequenceIdx); + _vm->_sound->command(20); + _commonSequenceIdx = _scene->_sequences.startReverseCycle(_commonSpriteIndex, false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _scene->_sequences.setDepth(_commonSequenceIdx, 15); + } + break; + + case 1: + if (!_globals[kHaveYourStuff]) + _scene->_dynamicHotspots.remove(_hotspot2Idx); + + _scene->_dynamicHotspots.remove(_hotspot1Idx); + _scene->_dynamicHotspots.remove(_lampHostpotIdx); + _vaultOpenFl = false; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } + + if (_action.isAction(VERB_PUT, NOUN_GUARDS_ARM, NOUN_SCANNER)) { + if (_globals[kSexOfRex] == REX_MALE) + _game._player.walk(Common::Point(269, 111), FACING_NORTHEAST); + else + _game._player.walk(Common::Point(271, 111), FACING_NORTHEAST); + } + + if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY) || _action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH) || _action.isAction(VERB_PUT, NOUN_GUARDS_ARM, NOUN_FLOOR)) { + if (_game._objects.isInInventory(OBJ_GUARDS_ARM)) + _game._player.walk(Common::Point(230, 117), FACING_NORTHWEST); + } +} + +void Scene352::actions() { + if (_action._lookFlag) { + _vm->_dialogs->show(35225); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_OPEN, NOUN_VAULT)) { + if (!_vaultOpenFl) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + if (_globals[kSexOfRex] == REX_FEMALE) + _commonSpriteIndex = _globals._spriteIndexes[9]; + else + _commonSpriteIndex = _globals._spriteIndexes[8]; + + _commonSequenceIdx = _scene->_sequences.addSpriteCycle(_commonSpriteIndex, false, 8, 1, 0, 0); + _scene->_sequences.updateTimeout(_commonSequenceIdx, -1); + _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + _vm->_sound->command(21); + _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 7, 2, 20, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[12], FACING_NORTH); + int oldIdx = _commonSequenceIdx; + _commonSequenceIdx = _scene->_sequences.startCycle(_commonSpriteIndex, false, -2); + _scene->_sequences.updateTimeout(_commonSequenceIdx, oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + + case 2: + _vm->_sound->command(22); + _scene->_sequences.remove(_commonSequenceIdx); + _commonSequenceIdx = _scene->_sequences.startReverseCycle(_commonSpriteIndex, false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_commonSequenceIdx, 1, 3); + _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: + _scene->_sequences.updateTimeout(-1, _commonSequenceIdx); + _game._player._visible = true; + _scene->_sequences.addTimer(60, 4); + break; + + case 4: + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x101)); + _game._player._stepEnabled = true; + break; + } + } + _action._inProgress = false; + return; + } + + if (_game._objects.isInInventory(OBJ_GUARDS_ARM)) { + _mustPutArmDownFl = true; + } + + bool exit_corridor = false; + bool exit_doorway = false; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH)) { + exit_corridor = true; + } + + if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY)) { + exit_doorway = true; + } + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH) || _action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY) || _action.isAction(VERB_PUT, NOUN_GUARDS_ARM, NOUN_FLOOR)) { + if (_mustPutArmDownFl) + putArmDown(exit_corridor, exit_doorway); + else if (exit_corridor) + _scene->_nextSceneId = 353; + else + _scene->_nextSceneId = 351; + + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_GUARDS_ARM)) { + if (_game._trigger || !_game._objects.isInInventory(OBJ_GUARDS_ARM)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + if (_globals[kSexOfRex] == REX_FEMALE) { + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 5, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 5, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } else { + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 5, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 6, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _game._objects.addToInventory(OBJ_GUARDS_ARM); + _scene->changeVariant(1); + break; + + case 2: + _game._player._visible = true; + _game._player._stepEnabled = true; + _vm->_dialogs->showItem(OBJ_GUARDS_ARM, 0x899C); + break; + } + _action._inProgress = false; + return; + } + } + + if (_action.isAction(VERB_PUT, NOUN_GUARDS_ARM, NOUN_SCANNER)) { + if (!_vaultOpenFl) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + if (_globals[kSexOfRex] == REX_FEMALE) + _commonSpriteIndex = _globals._spriteIndexes[11]; + else + _commonSpriteIndex = _globals._spriteIndexes[10]; + + _commonSequenceIdx = _scene->_sequences.addSpriteCycle(_commonSpriteIndex, false, 8, 1, 0, 0); + _scene->_sequences.updateTimeout(_commonSequenceIdx, -1); + _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + _vm->_sound->command(21); + _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 7, 2, 20, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 8); + int oldIdx = _commonSequenceIdx; + _commonSequenceIdx = _scene->_sequences.startCycle(_commonSpriteIndex, false, -2); + _scene->_sequences.updateTimeout(_commonSequenceIdx, oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + + case 2: + _vm->_sound->command(23); + _scene->_sequences.remove(_commonSequenceIdx); + _commonSequenceIdx = _scene->_sequences.startReverseCycle(_commonSpriteIndex, false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_commonSequenceIdx, 1, 4); + _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + + case 3: + _scene->_sequences.updateTimeout(-1, _commonSequenceIdx); + _game._player._visible = true; + if (_globals[kHaveYourStuff]) + _commonSpriteIndex = _globals._spriteIndexes[13]; + else + _commonSpriteIndex = _globals._spriteIndexes[1]; + + _vm->_sound->command(20); + _commonSequenceIdx = _scene->_sequences.addSpriteCycle(_commonSpriteIndex, false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_commonSequenceIdx, 15); + _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 4); + break; + + case 4: + _commonSequenceIdx = _scene->_sequences.addSpriteCycle(_commonSpriteIndex, false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_commonSequenceIdx, -2, -2); + _scene->_sequences.setDepth(_commonSequenceIdx, 15); + _scene->_sequences.addTimer(60, 5); + break; + + case 5: { + _vaultOpenFl = true; + int idx; + if (!_globals[kHaveYourStuff]) { + idx = _scene->_dynamicHotspots.add(NOUN_YOUR_STUFF, VERB_WALKTO, -1, Common::Rect(282, 87, 282 + 13, 87 + 7)); + _hotspot2Idx = _scene->_dynamicHotspots.setPosition(idx, Common::Point(280, 111), FACING_NORTHEAST); + _globals._sequenceIndexes[1] = _commonSequenceIdx; + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x102)); + } else { + _globals._sequenceIndexes[13] = _commonSequenceIdx; + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x103)); + } + + idx = _scene->_dynamicHotspots.add(NOUN_OTHER_STUFF, VERB_WALKTO, -1, Common::Rect(282, 48, 282 + 36, 48 + 27)); + _hotspot1Idx = _scene->_dynamicHotspots.setPosition(idx, Common::Point(287, 115), FACING_NORTHEAST); + idx = _scene->_dynamicHotspots.add(NOUN_LAMP, VERB_WALKTO, -1, Common::Rect(296, 76, 296 + 11, 76 + 17)); + _lampHostpotIdx = _scene->_dynamicHotspots.setPosition(idx, Common::Point(287, 115), FACING_NORTHEAST); + _game._player._stepEnabled = true; + } + break; + } + } + } else if (_action.isAction(VERB_TAKE, NOUN_YOUR_STUFF)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + if (_globals[kSexOfRex] == REX_MALE) { + _globals._sequenceIndexes[14] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[14], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[14], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[14]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[14], SEQUENCE_TRIGGER_SPRITE, 2, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[14], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } else { + _globals._sequenceIndexes[15] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[15], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[15], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[15]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[15], SEQUENCE_TRIGGER_SPRITE, 2, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[15], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + + case 1: + _scene->_dynamicHotspots.remove(_hotspot2Idx); + _globals[kHaveYourStuff] = true; + + for (uint16 i = 0; i < _game._objects.size(); i++) { + if (_game._objects[i]._roomNumber == 50) + _game._objects.addToInventory(i); + } + + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 15); + break; + + case 2: + if (_globals[kSexOfRex] == REX_MALE) + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[14]); + else + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[15]); + + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_TAKE, NOUN_TAPE_PLAYER) && !_game._objects.isInInventory(OBJ_TAPE_PLAYER)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + if (_globals[kSexOfRex] == REX_MALE) { + _globals._sequenceIndexes[6] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[6], true, 6, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[6]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_SPRITE, 6, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } else { + _globals._sequenceIndexes[7] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[7], true, 6, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[7]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_SPRITE, 6, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _scene->_dynamicHotspots.remove(_tapePlayerHotspotIdx); + break; + + case 2: + _game._objects.addToInventory(OBJ_TAPE_PLAYER); + if (_globals[kSexOfRex] == REX_MALE) + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[6]); + else + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[7]); + + _game._player._visible = true; + _game._player._stepEnabled = true; + _vm->_dialogs->showItem(OBJ_TAPE_PLAYER, 0x899B); + break; + + default: + break; + } + } else if (_action.isAction(VERB_LOOK, NOUN_SCANNER)) + _vm->_dialogs->show(35210); + else if (_action.isAction(VERB_LOOK, NOUN_MONITOR)) { + if (_game._storyMode == STORYMODE_NAUGHTY) + _vm->_dialogs->show(35211); + else + _vm->_dialogs->show(35212); + } else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY)) + _vm->_dialogs->show(35213); + else if (_action.isAction(VERB_LOOK, NOUN_STATUE)) + _vm->_dialogs->show(35214); + else if (_action.isAction(VERB_LOOK, NOUN_TAPE_PLAYER) && (_action._savedFields._mainObjectSource == 4)) + _vm->_dialogs->show(35215); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT)) + _vm->_dialogs->show(35216); + else if (_action.isAction(VERB_LOOK, NOUN_GUARDS_ARM) && (_action._savedFields._mainObjectSource == 4)) + _vm->_dialogs->show(35217); + else if (_action.isAction(VERB_LOOK, NOUN_IRONING_BOARD)) + _vm->_dialogs->show(35218); + else if (_action.isAction(VERB_LOOK, NOUN_CLOCK)) + _vm->_dialogs->show(35219); + else if (_action.isAction(VERB_LOOK, NOUN_GAUGE)) + _vm->_dialogs->show(35220); + else if (_action.isAction(VERB_LOOK, NOUN_VAULT)) { + if (!_vaultOpenFl) + _vm->_dialogs->show(35221); + } else if (_action.isAction(VERB_LOOK, NOUN_YOUR_STUFF)) + _vm->_dialogs->show(35222); + else if (_action.isAction(VERB_LOOK, NOUN_OTHER_STUFF)) + _vm->_dialogs->show(35223); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH)) + _vm->_dialogs->show(35224); + else if (_action.isAction(VERB_TAKE, NOUN_OTHER_STUFF)) + _vm->_dialogs->show(35226); + else if (_action.isAction(VERB_LOOK, NOUN_DESK)) + _vm->_dialogs->show(35229); + else if (_action.isAction(VERB_LOOK, NOUN_GUARD)) + _vm->_dialogs->show(35230); + else if (_action.isAction(VERB_LOOK, NOUN_DOORWAY)) + _vm->_dialogs->show(35231); + else if (_action.isAction(VERB_LOOK, NOUN_TABLE)) + _vm->_dialogs->show(35232); + else if (_action.isAction(VERB_LOOK, NOUN_PROJECTOR)) + _vm->_dialogs->show(35233); + else if (_action.isAction(VERB_LOOK, NOUN_SUPPORT)) + _vm->_dialogs->show(35234); + else if (_action.isAction(VERB_LOOK, NOUN_SECURITY_MONITOR)) + _vm->_dialogs->show(35235); + else + return; +} + +/*------------------------------------------------------------------------*/ + +void Scene353::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene353::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(Resources::formatName(303, 'B', 0, EXT_SS, "")); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 0, 5, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + if (_scene->_priorSceneId == 352) + _game._player._playerPos = Common::Point(144, 95); + else + _game._player._playerPos = Common::Point(139, 155); + + sceneEntrySound(); +} + +void Scene353::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(35315); + else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY)) + _scene->_nextSceneId = 352; + else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH)) + _scene->_nextSceneId = 354; + else if (_action.isAction(VERB_LOOK, NOUN_ROCK_CHUNK)) + _vm->_dialogs->show(35310); + else if (_action.isAction(VERB_LOOK, NOUN_PIPES) || _action.isAction(VERB_LOOK, NOUN_PIPE)) + _vm->_dialogs->show(35311); + else if (_action.isAction(VERB_LOOK, NOUN_BROKEN_BEAM)) + _vm->_dialogs->show(35312); + else if (_action.isAction(VERB_LOOK, NOUN_DOORWAY)) + _vm->_dialogs->show(35313); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH)) + _vm->_dialogs->show(35314); + else if (_action.isAction(VERB_LOOK, NOUN_FLOOR)) + _vm->_dialogs->show(35316); + else if (_action.isAction(VERB_LOOK, NOUN_CEILING)) + _vm->_dialogs->show(35317); + else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(35318); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene354::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene354::enter() { + _globals[kAfterHavoc] = true; + _globals[kTeleporterRoom + 1] = 351; + + if (_scene->_priorSceneId == 361) + _game._player._playerPos = Common::Point(231, 110); + else if (_scene->_priorSceneId == 401) { + _game._player._playerPos = Common::Point(106, 152); + _game._player._facing = FACING_NORTH; + } else if (_scene->_priorSceneId == 316) + _game._player._playerPos = Common::Point(71, 107); + else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(167, 57); + + sceneEntrySound(); +} + +void Scene354::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH)) + _game._player._walkOffScreenSceneId = 401; +} + +void Scene354::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(35414); + else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_NORTH)) { + _game._player.startWalking(Common::Point(208, 0), FACING_NORTHEAST); + _game._player._walkOffScreenSceneId = 353; + } else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST)) + _scene->_nextSceneId = 361; + else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST)) + _scene->_nextSceneId = 316; + else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH)) + _scene->_nextSceneId = 401; + else if (_action.isAction(VERB_LOOK, NOUN_CONTROLS)) + _vm->_dialogs->show(35410); + else if (_action.isAction(VERB_LOOK, NOUN_SIGNAL)) + _vm->_dialogs->show(35411); + else if (_action.isAction(VERB_LOOK, NOUN_CATWALK)) + _vm->_dialogs->show(35412); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_DUCT)) + _vm->_dialogs->show(35413); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_NORTH)) + _vm->_dialogs->show(35415); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH)) + _vm->_dialogs->show(35416); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST)) + _vm->_dialogs->show(35417); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST)) + _vm->_dialogs->show(35418); + else if (_action.isAction(VERB_LOOK, NOUN_DEBRIS)) + _vm->_dialogs->show(35419); + else if (_action.isAction(VERB_LOOK, NOUN_GUARD)) + _vm->_dialogs->show(35420); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene357::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene357::enter() { + _globals[kAfterHavoc] = true; + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, "")); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + + if (_scene->_priorSceneId == 318) + _game._player._playerPos = Common::Point(298, 142); + else if (_scene->_priorSceneId == 313) + _game._player._playerPos = Common::Point(127, 101); + else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(15, 148); + + sceneEntrySound(); +} + +void Scene357::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST)) + _game._player._walkOffScreenSceneId = 318; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST)) + _game._player._walkOffScreenSceneId = 358; +} + +void Scene357::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(35715); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT)) + _vm->_dialogs->show(35710); + else if (_action.isAction(VERB_CLIMB_INTO, NOUN_AIR_VENT)) + _vm->_dialogs->show(35711); + else if (_action.isAction(VERB_LOOK, NOUN_BED)) + _vm->_dialogs->show(35712); + else if (_action.isAction(VERB_LOOK, NOUN_SINK)) + _vm->_dialogs->show(35713); + else if (_action.isAction(VERB_LOOK, NOUN_TOILET)) + _vm->_dialogs->show(35714); + else if (_action.isAction(VERB_LOOK, NOUN_CELL_WALL)) + _vm->_dialogs->show(35716); + else if (_action.isAction(VERB_LOOK, NOUN_LIGHT)) + _vm->_dialogs->show(35717); + else if (_action.isAction(VERB_LOOK, NOUN_RIP_IN_FLOOR)) + _vm->_dialogs->show(35718); + else if (_action.isAction(VERB_LOOK, NOUN_DEBRIS)) + _vm->_dialogs->show(35719); + else if (_action.isAction(VERB_TAKE, NOUN_DEBRIS)) + _vm->_dialogs->show(35720); + else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(35721); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST)) + _vm->_dialogs->show(35722); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST)) + _vm->_dialogs->show(35723); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene358::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene358::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, "")); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + + if (_scene->_priorSceneId == 357) + _game._player._playerPos = Common::Point(305, 142); + else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(12, 141); + + sceneEntrySound(); +} + +void Scene358::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST)) + _game._player._walkOffScreenSceneId = 357; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST)) + _game._player._walkOffScreenSceneId = 359; +} + +void Scene358::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(35815); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST)) + _vm->_dialogs->show(35810); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST)) + _vm->_dialogs->show(35811); + else if (_action.isAction(VERB_LOOK, NOUN_BED)) + _vm->_dialogs->show(35812); + else if (_action.isAction(VERB_LOOK, NOUN_SINK)) + _vm->_dialogs->show(35813); + else if (_action.isAction(VERB_LOOK, NOUN_TOILET)) + _vm->_dialogs->show(35814); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR) || _action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(35816); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT)) + _vm->_dialogs->show(35817); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene359::Scene359(MADSEngine *vm) : Scene3xx(vm) { + _cardHotspotId = -1; +} + +void Scene359::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + s.syncAsSint32LE(_cardHotspotId); +} + +void Scene359::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene359::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('b', -1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, "")); + + if (_globals[kSexOfRex] == REX_MALE) + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMBD_2"); + else + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*ROXBD_2"); + + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 15); + + if (_game._objects.isInRoom(OBJ_SECURITY_CARD)) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 0, 0, 0); + _cardHotspotId = _scene->_dynamicHotspots.add(NOUN_SECURITY_CARD, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_cardHotspotId, Common::Point(107, 107), FACING_SOUTH); + } + + if (_scene->_priorSceneId == 358) + _game._player._playerPos = Common::Point(301, 141); + else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(15, 148); + + sceneEntrySound(); +} + +void Scene359::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST)) + _game._player._walkOffScreenSceneId = 358; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST)) + _game._player._walkOffScreenSceneId = 360; +} + +void Scene359::actions() { + if (_action._lookFlag) { + if ((_game._difficulty != DIFFICULTY_HARD) && (_game._objects[OBJ_SECURITY_CARD]._roomNumber == 359)) + _vm->_dialogs->show(35914); + else + _vm->_dialogs->show(35915); + } else if (_action.isAction(VERB_TAKE, NOUN_SECURITY_CARD)) { + if (_game._trigger || !_game._objects.isInInventory(OBJ_SECURITY_CARD)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _vm->_dialogs->show(35920); + if (_globals[kSexOfRex] == REX_MALE) { + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 4, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 6, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } else { + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], true, 7, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(106, 110)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 6, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_dynamicHotspots.remove(_cardHotspotId); + _vm->_sound->command(57); + _game._objects.addToInventory(OBJ_SECURITY_CARD); + _vm->_dialogs->showItem(OBJ_SECURITY_CARD, 0x330); + _scene->changeVariant(1); + break; + + case 2: + if (_globals[kSexOfRex] == REX_MALE) + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + else + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[4]); + + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } + } else if (_action.isAction(VERB_LOOK, NOUN_BLOODY_CELL_WALL)) + _vm->_dialogs->show(35910); + else if (_action.isAction(VERB_LOOK, NOUN_BED)) + _vm->_dialogs->show(35911); + else if (_action.isAction(VERB_LOOK, NOUN_SINK)) + _vm->_dialogs->show(35912); + else if (_action.isAction(VERB_LOOK, NOUN_TOILET)) + _vm->_dialogs->show(35913); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST)) + _vm->_dialogs->show(35916); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST)) + _vm->_dialogs->show(35917); + else if (_action.isAction(VERB_LOOK, NOUN_LIMB)) + _vm->_dialogs->show(35918); + else if (_action.isAction(VERB_TAKE, NOUN_LIMB)) + _vm->_dialogs->show(35919); + else if (_action.isAction(VERB_LOOK, NOUN_SECURITY_CARD) && (_action._mainObjectSource == 4)) + _vm->_dialogs->show(35921); + else if (_action.isAction(VERB_LOOK, NOUN_BLOOD_STAIN)) { + if ((_game._difficulty != DIFFICULTY_HARD) && (_game._objects[OBJ_SECURITY_CARD]._roomNumber == 359)) + _vm->_dialogs->show(35922); + else + _vm->_dialogs->show(35923); + } else if (_action.isAction(VERB_LOOK, NOUN_WALL_BOARD)) + _vm->_dialogs->show(35924); + else if (_action.isAction(VERB_TAKE, NOUN_WALL_BOARD)) + _vm->_dialogs->show(35925); + else if (_action.isAction(VERB_LOOK, NOUN_RIP_IN_FLOOR)) + _vm->_dialogs->show(35926); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR)) + _vm->_dialogs->show(35927); + else if (_action.isAction(VERB_LOOK, NOUN_FLOOR)) { + if ((_game._difficulty != DIFFICULTY_HARD) && (_game._objects[OBJ_SECURITY_CARD]._roomNumber == 359)) + _vm->_dialogs->show(35928); + else + _vm->_dialogs->show(35929); + } else if (_action.isAction(VERB_OPEN, NOUN_AIR_VENT) || _action.isAction(VERB_LOOK, NOUN_AIR_VENT)) + _vm->_dialogs->show(36016); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene360::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene360::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, "")); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + + if (_scene->_priorSceneId == 359) + _game._player._playerPos = Common::Point(304, 143); + else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(13, 141); + + sceneEntrySound(); +} + +void Scene360::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST)) + _game._player._walkOffScreenSceneId = 359; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST)) + _game._player._walkOffScreenSceneId = 361; +} + +void Scene360::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(36015); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST)) + _vm->_dialogs->show(36010); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST)) + _vm->_dialogs->show(36011); + else if (_action.isAction(VERB_LOOK, NOUN_BED)) + _vm->_dialogs->show(36012); + else if (_action.isAction(VERB_LOOK, NOUN_SINK)) + _vm->_dialogs->show(36013); + else if (_action.isAction(VERB_LOOK, NOUN_TOILET)) + _vm->_dialogs->show(36014); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT)) + _vm->_dialogs->show(36016); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR)) + _vm->_dialogs->show(36017); + else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(36018); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene361::setup() { + if (_scene->_currentSceneId == 391) + _globals[kSexOfRex] = REX_MALE; + + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene361::handleRexAction() { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 50, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 3, -2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 15, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, 4); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: { + int seqIdx = _globals._sequenceIndexes[1]; + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 4); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], seqIdx); + } + break; + + case 2: { + int seqIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 4, 10); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + } + break; + + case 3: { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 3); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + int seqIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 11); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(167, 100)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], seqIdx); + _scene->_sequences.addTimer(15, 4); + } + break; + + case 4: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + _scene->_sequences.setDone(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 12, 14); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(167, 100)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 5); + break; + + case 5: { + int seqIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 15); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(167, 100)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], seqIdx); + _scene->_sequences.addTimer(15, 6); + } + break; + + case 6: + _scene->_sequences.setDone(_globals._sequenceIndexes[2]); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _scene->_sequences.addTimer(48, 7); + break; + + case 7: + _scene->_nextSceneId = 313; + break; + + default: + break; + } +} + +void Scene361::handleRoxAction() { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 18, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 2, 4); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 18, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], -1, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: { + int tmpIdx = _globals._sequenceIndexes[1]; + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 4); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], tmpIdx); + } + break; + + case 2: { + int tmpIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 4, 8); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], tmpIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + } + break; + + case 3: { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 3); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + int tmpIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 9, 10); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(167, 100)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], tmpIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 4); + } + break; + + case 4: { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + int tmpIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 11, 15); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(167, 100)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], tmpIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 5); + } + break; + + case 5: { + int tmpIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 16); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(167, 100)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], tmpIdx); + _scene->_sequences.addTimer(48, 6); + } + break; + + case 6: + _scene->_sequences.setDone(_globals._sequenceIndexes[4]); + + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _scene->_sequences.addTimer(48, 7); + break; + + case 7: + _scene->_nextSceneId = 313; + break; + + default: + break; + } +} + +void Scene361::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, "")); + + if (_globals[kSexOfRex] == REX_MALE) { + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXCL_8"); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXCL_2"); + } else + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*ROXCL_8"); + + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + + if (_scene->_priorSceneId == 391) { + _globals[kSexOfRex] = REX_MALE; + _game._player._stepEnabled = false; + _game._player._visible = false; + _game._player._facing = FACING_SOUTH; + _game._player._playerPos = Common::Point(166, 101); + _scene->_sequences.addTimer(120, 70); + } else if (_scene->_priorSceneId == 360) + _game._player._playerPos = Common::Point(302, 145); + else if (_scene->_priorSceneId == 320) { + _game._player._playerPos = Common::Point(129, 113); + _game._player._facing = FACING_SOUTH; + } else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(13, 145); + + _game.loadQuoteSet(0xFB, 0xFC, 0); + + if (_scene->_priorSceneId == 320) + _scene->_kernelMessages.setQuoted(_scene->_kernelMessages.addQuote(0xFB, 0, 0x78), 4, true); + + sceneEntrySound(); +} + +void Scene361::step() { + if (_game._trigger >= 70) { + switch (_game._trigger) { + case 70: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 71); + break; + + case 71: + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 72); + break; + + case 72: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 3); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 73); + break; + + case 73: + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 4, 5); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 74); + break; + + case 74: { + int seqIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], seqIdx); + _scene->_sequences.addTimer(15, 75); + } + break; + + case 75: + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 7); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 76); + break; + + case 76: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 8); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 77); + break; + + case 77: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 9); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 78); + break; + + case 78: + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 10, -2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 79); + break; + + case 79: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]); + _game._player._stepEnabled = true; + _game._player._visible = true; + break; + + default: + break; + } + } +} + +void Scene361::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST)) + _game._player._walkOffScreenSceneId = 360; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST)) + _game._player._walkOffScreenSceneId = 354; +} + +void Scene361::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(36119); + else if (_action.isAction(VERB_SIT_AT, NOUN_DESK)) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.addQuote(0xFC, 120, 0); + } else if (_action.isAction(VERB_CLIMB_INTO, NOUN_AIR_VENT)) { + if (_globals[kSexOfRex] == REX_FEMALE) + handleRoxAction(); + else + handleRexAction(); + } else if (_action.isAction(VERB_LOOK, NOUN_DESK)) + _vm->_dialogs->show(36110); + else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(36111); + else if (_action.isAction(VERB_LOOK, NOUN_LIGHTING_FIXTURE) || _action.isAction(VERB_STARE_AT, NOUN_LIGHTING_FIXTURE)) + _vm->_dialogs->show(36112); + else if (_action.isAction(VERB_LOOK, NOUN_LIGHTS) || _action.isAction(VERB_STARE_AT, NOUN_LIGHTS)) + _vm->_dialogs->show(36113); + else if (_action.isAction(VERB_TAKE, NOUN_LIGHTS)) + _vm->_dialogs->show(36114); + else if (_action.isAction(VERB_LOOK, NOUN_LIGHT_BULB) || _action.isAction(VERB_STARE_AT, NOUN_LIGHT_BULB)) + _vm->_dialogs->show(36115); + else if (_action.isAction(VERB_TAKE, NOUN_LIGHT_BULB)) + _vm->_dialogs->show(36116); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST)) + _vm->_dialogs->show(36117); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST)) + _vm->_dialogs->show(36118); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT)) + _vm->_dialogs->show(36120); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene366::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene366::enter() { + _scene->_userInterface.setup(kInputLimitedSentences); + _game._player._visible = false; + sceneEntrySound(); +} + +void Scene366::actions() { + if (_action.isAction(VERB_RETURN_TO, NOUN_AIR_SHAFT)) + _scene->_nextSceneId = 302; + else if (_action.isAction(VERB_OPEN, NOUN_GRATE)) { + if (_game._visitedScenes.exists(316)) + _vm->_dialogs->show(36612); + else + _vm->_dialogs->show(36613); + _scene->_nextSceneId = 316; + } else if (_action.isAction(VERB_LOOK_THROUGH, NOUN_GRATE)) { + if (_game._visitedScenes.exists(321)) + _vm->_dialogs->show(36611); + else + _vm->_dialogs->show(36610); + } else { + return; + } + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene387::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene387::enter() { + _scene->_userInterface.setup(kInputLimitedSentences); + _game._player._visible = false; + + sceneEntrySound(); +} + +void Scene387::actions() { + if (_action.isAction(VERB_RETURN_TO, NOUN_AIR_SHAFT)) + _scene->_nextSceneId = 313; + else if (_action.isAction(VERB_LOOK_THROUGH, NOUN_GRATE)) + _vm->_dialogs->show(38710); + else if (_action.isAction(VERB_OPEN, NOUN_GRATE)) + _vm->_dialogs->show(38711); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene388::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene388::enter() { + _scene->_userInterface.setup(kInputLimitedSentences); + + if (_globals[kAfterHavoc]) + _scene->_hotspots.activate(NOUN_SAUROPOD, false); + else { + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('b', 0)); + _globals._sequenceIndexes[0] = _scene->_sequences.startCycle(_globals._spriteIndexes[0], false, 1); + } + + _game._player._visible = false; + _vm->_palette->setEntry(252, 63, 30, 20); + _vm->_palette->setEntry(253, 45, 15, 12); + _game.loadQuoteSet(0x154, 0x155, 0x156, 0x157, 0x158, 0); + + sceneEntrySound(); +} + +void Scene388::actions() { + if (_action.isAction(VERB_RETURN_TO, NOUN_AIR_SHAFT)) + _scene->_nextSceneId = 313; + else if (_action.isAction(VERB_TALKTO, NOUN_SAUROPOD)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(160, 136), 0x1110, 32, 1, 120, _game.getQuote(0x154)); + break; + + case 1: + _scene->_kernelMessages.add(Common::Point(82, 38), 0xFDFC, 0, 0, 300, _game.getQuote(0x156)); + _scene->_kernelMessages.add(Common::Point(82, 52), 0xFDFC, 0, 0, 300, _game.getQuote(0x157)); + _scene->_kernelMessages.add(Common::Point(82, 66), 0xFDFC, 0, 2, 300, _game.getQuote(0x158)); + break; + + case 2: + _game._player._stepEnabled = true; + _scene->_kernelMessages.add(Common::Point(160, 136), 0x1110, 32, 0, 120, _game.getQuote(0x155)); + break; + + default: + break; + } + } else if (_action.isAction(VERB_LOOK_THROUGH, NOUN_GRATE)) { + if (_globals[kAfterHavoc]) + _vm->_dialogs->show(38811); + else + _vm->_dialogs->show(38810); + } else if (_action.isAction(VERB_OPEN, NOUN_GRATE)) + _vm->_dialogs->show(38812); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene389::Scene389(MADSEngine *vm) : Scene300s(vm) { + _monsterTime = 0; + _circularQuoteId = -1; +} + +void Scene389::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + s.syncAsUint32LE(_monsterTime); + s.syncAsSint32LE(_circularQuoteId); +} + +void Scene389::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene389::enter() { + _scene->_userInterface.setup(kInputLimitedSentences); + _monsterTime = 0; + _circularQuoteId = 0x159; + + if (_globals[kAfterHavoc]) + _scene->_hotspots.activate(NOUN_MONSTER, false); + else { + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('m', -1)); + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 6, 0, 0, 0); + _scene->_kernelMessages.initRandomMessages(1, + Common::Rect(88, 19, 177, 77), 13, 2, 0xFDFC, 60, + 247, 248, 249, 0); + } + + _vm->_palette->setEntry(252, 63, 37, 26); + _vm->_palette->setEntry(253, 45, 24, 17); + _game._player._visible = false; + _game.loadQuoteSet(0xF7, 0xF8, 0xF9, 0x159, 0x15A, 0x15B, 0); + + sceneEntrySound(); +} + +void Scene389::step() { + _scene->_kernelMessages.randomServer(); + if (_scene->_frameStartTime >= _monsterTime) { + int chanceMinor = _scene->_kernelMessages.checkRandom() * 4 + 1; + _scene->_kernelMessages.generateRandom(20, chanceMinor); + _monsterTime = _scene->_frameStartTime + 2; + } +} + +void Scene389::actions() { + if (_action.isAction(VERB_RETURN_TO, NOUN_AIR_SHAFT)) + _scene->_nextSceneId = 313; + else if (_action.isAction(VERB_TALKTO, NOUN_MONSTER)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_kernelMessages.add(Common::Point(160, 136), 0x1110, 32, 1, 120, _game.getQuote(_circularQuoteId)); + _circularQuoteId++; + if (_circularQuoteId > 0x15B) + _circularQuoteId = 0x159; + + break; + + case 1: + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_LOOK_THROUGH, NOUN_GRATE)) { + if (_globals[kAfterHavoc]) { + if ((_game._difficulty != DIFFICULTY_HARD) && (_game._objects[OBJ_SECURITY_CARD]._roomNumber == 359)) + _vm->_dialogs->show(38911); + else + _vm->_dialogs->show(38912); + } else + _vm->_dialogs->show(38910); + } else if (_action.isAction(VERB_OPEN, NOUN_GRATE)) { + if (_globals[kAfterHavoc]) + _vm->_dialogs->show(38914); + else + _vm->_dialogs->show(38913); + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene390::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene390::enter() { + _scene->_userInterface.setup(kInputLimitedSentences); + _game._player._visible = false; + + sceneEntrySound(); +} + +void Scene390::actions() { + if (_action.isAction(VERB_RETURN_TO, NOUN_AIR_SHAFT)) + _scene->_nextSceneId = 313; + else if (_action.isAction(VERB_LOOK_THROUGH, NOUN_GRATE)) + _vm->_dialogs->show(39010); + else if (_action.isAction(VERB_OPEN, NOUN_GRATE)) + _vm->_dialogs->show(39011); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene391::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene391::enter() { + _scene->_userInterface.setup(kInputLimitedSentences); + _game._player._visible = false; + sceneEntrySound(); +} + +void Scene391::actions() { + if (_action.isAction(VERB_RETURN_TO, NOUN_AIR_SHAFT)) + _scene->_nextSceneId = 313; + else if (_action.isAction(VERB_OPEN, NOUN_GRATE)) { + if (_globals[kKickedIn391Grate]) + _vm->_dialogs->show(39113); + else { + _vm->_dialogs->show(39112); + _globals[kKickedIn391Grate] = true; + } + + if (_globals[kAfterHavoc]) + _scene->_nextSceneId = 361; + else + _scene->_nextSceneId = 311; + } else if (_action.isAction(VERB_LOOK_THROUGH, NOUN_GRATE)) { + if (_globals[kAfterHavoc]) + _vm->_dialogs->show(39111); + else + _vm->_dialogs->show(39110); + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene399::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene399::enter() { + _scene->_userInterface.setup(kInputLimitedSentences); + _game._player._visible = false; + sceneEntrySound(); +} + +void Scene399::actions() { + if (_action.isAction(VERB_RETURN_TO, NOUN_AIR_SHAFT)) + _scene->_nextSceneId = 313; + else if (_action.isAction(VERB_LOOK_THROUGH, NOUN_GRATE)) { + if (_globals[kAfterHavoc]) { + if ((_game._difficulty != DIFFICULTY_HARD) && (_game._objects[OBJ_SECURITY_CARD]._roomNumber == 359)) + _vm->_dialogs->show(38911); + else + _vm->_dialogs->show(38912); + } else + _vm->_dialogs->show(38910); + } else if (_action.isAction(VERB_OPEN, NOUN_GRATE)) { + if (_globals[kAfterHavoc]) + _vm->_dialogs->show(38914); + else + _vm->_dialogs->show(38913); + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +} // End of namespace Nebular +} // End of namespace MADS diff --git a/engines/mads/nebular/nebular_scenes3.h b/engines/mads/nebular/nebular_scenes3.h new file mode 100644 index 0000000000..9efd38e9a4 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes3.h @@ -0,0 +1,548 @@ +/* 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. + * + */ + +#ifndef MADS_NEBULAR_SCENES3_H +#define MADS_NEBULAR_SCENES3_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" + +namespace MADS { + +namespace Nebular { + +typedef struct { + bool _flag; + int _vertical; + int _horizontal; + int _seqId[40]; + uint32 _timer; + + void init() { + _flag = false; + _vertical = _horizontal = -1; + _timer = 0; + for (int i = 0; i < 40; ++i) + _seqId[i] = -1; + } + + void synchronize(Common::Serializer &s) { + s.syncAsByte(_flag); + s.syncAsSint32LE(_vertical); + s.syncAsSint32LE(_horizontal); + for (int i = 0; i < 40; ++i) + s.syncAsSint32LE(_seqId[i]); + s.syncAsUint32LE(_timer); + }; +} ForceField; + +class Scene3xx : public NebularScene { +protected: + /** + * Plays an appropriate sound when entering a scene + */ + void setAAName(); + + /** + * Updates the prefix used for getting player sprites for the scene + */ + void setPlayerSpritesPrefix(); + + void sceneEntrySound(); + + void initForceField(ForceField *force, bool flag); + void handleForceField(ForceField *force, int *sprites); + int computeScale(int low, int high, int id); + +public: + Scene3xx(MADSEngine *vm) : NebularScene(vm) {} + + virtual void actions() {} +}; + +class Scene300s : public Scene3xx { +public: + Scene300s(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void preActions(); +}; + +class Scene301 : public Scene3xx { +public: + Scene301(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); +}; + +class Scene302 : public Scene3xx { +private: + int _oldFrame; + +public: + Scene302(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); +}; + +class Scene303 : public Scene3xx { +public: + Scene303(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); +}; + +class Scene304 : public Scene3xx { +private: + int _explosionSpriteId; + +public: + Scene304(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); +}; + +class Scene307 : public Scene3xx { +private: + ForceField _forceField; + + bool _afterPeeingFl; + bool _duringPeeingFl; + bool _grateOpenedFl; + bool _activePrisonerFl; + + int _animationMode; + int _prisonerMessageId; + int _fieldCollisionCounter; + + uint32 _lastFrameTime; + uint32 _guardTime; + uint32 _prisonerTimer; + + Common::String _subQuote2; + + Conversation _dialog1, _dialog2; + + void handleDialog(); + void handleRexDialog(int quote); + void handlePrisonerDialog(); + void handlePrisonerEncounter(); + void setDialogNode(int node); + void handlePrisonerSpeech(int firstQuoteId, int number, long timeout); + +public: + Scene307(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene308 : public Scene3xx { +private: + ForceField _forceField; + +public: + Scene308(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); +}; + +class Scene309 : public Scene3xx { +private: + ForceField _forceField; + int _characterSpriteIndexes[3]; + int _messagesIndexes[3]; + int _lastFrame; + +public: + Scene309(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); +}; + +class Scene310 : public Scene3xx { +private: + ForceField _forceField; + +public: + Scene310(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); +}; + +class Scene311 : public Scene3xx { +private: + bool _checkGuardFl; + +public: + Scene311(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene313 : public Scene3xx { +public: + Scene313(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene316 : public Scene3xx { +private: + void handleRexInGrate(); + void handleRoxInGrate(); + +public: + Scene316(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene318 : public Scene3xx { +private: + uint32 _dropTimer; + + int _lastFrame; + int _animMode; + int _internCounter; + int _counter; + + bool _dialogFl; + bool _internTalkingFl; + bool _internWalkingFl; + bool _internVisibleFl; + bool _explosionFl; + + uint32 _lastFrameCounter; + + Common::String _subQuote2; + + Conversation _dialog1; + + void handleDialog(); + void handleRexDialogs(int quote); + void handleInternDialog(int quoteId, int quoteNum, uint32 timeout); + +public: + Scene318(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene319 : public Scene3xx { +private: + Conversation _dialog1, _dialog2, _dialog3; + + int _animMode, _animFrame; + int _nextAction1, _nextAction2; + int _slacheMode; + int _slacheTopic; + int _slachePosY; + + bool _slacheTalkingFl; + bool _slacheReady; + bool _slacheInitFl; + + Common::String _subQuote2; + + void handleRexDialogues(int quote); + void handleSlacheDialogs(int quoteId, int counter, uint32 timer); +public: + Scene319(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene320 : public Scene300s { +private: + void setRightView(int view); + void setLeftView(int view); + void handleButtons(); + + bool _blinkFl; + bool _flippedFl; + + int _buttonId; + int _lastFrame; + int _leftItemId; + int _posX; + int _rightItemId; + +public: + Scene320(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene321 : public Scene3xx { +public: + Scene321(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); +}; + +class Scene322 : public SceneTeleporter { +public: + Scene322(MADSEngine *vm) : SceneTeleporter(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene351 : public Scene3xx { +public: + Scene351(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene352 : public Scene3xx { +private: + bool _vaultOpenFl; + bool _mustPutArmDownFl; + bool _leaveRoomFl; + + int _tapePlayerHotspotIdx; + int _hotspot1Idx; + int _hotspot2Idx; + int _lampHostpotIdx; + int _commonSequenceIdx; + int _commonSpriteIndex; + + void putArmDown(bool corridorExit, bool doorwayExit); + +public: + Scene352(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene353 : public Scene3xx { +public: + Scene353(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene354 : public Scene3xx { +public: + Scene354(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene357 : public Scene3xx { +public: + Scene357(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene358 : public Scene3xx { +public: + Scene358(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene359 : public Scene3xx { +private: + int _cardHotspotId; + +public: + Scene359(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene360 : public Scene3xx { +public: + Scene360(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene361 : public Scene3xx { +private: + void handleRexAction(); + void handleRoxAction(); + +public: + Scene361(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene366 : public Scene300s { +public: + Scene366(MADSEngine *vm) : Scene300s(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene387 : public Scene300s { +public: + Scene387(MADSEngine *vm) : Scene300s(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene388 : public Scene300s { +public: + Scene388(MADSEngine *vm) : Scene300s(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene389 : public Scene300s { +private: + uint32 _monsterTime; + + int _circularQuoteId; + +public: + Scene389(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene390 : public Scene300s { +public: + Scene390(MADSEngine *vm) : Scene300s(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene391 : public Scene300s { +public: + Scene391(MADSEngine *vm) : Scene300s(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene399 : public Scene300s { +public: + Scene399(MADSEngine *vm) : Scene300s(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +} // End of namespace Nebular + +} // End of namespace MADS + +#endif /* MADS_NEBULAR_SCENES3_H */ diff --git a/engines/mads/nebular/nebular_scenes4.cpp b/engines/mads/nebular/nebular_scenes4.cpp new file mode 100644 index 0000000000..d114232255 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes4.cpp @@ -0,0 +1,4191 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "mads/mads.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/nebular/nebular_scenes4.h" + +namespace MADS { + +namespace Nebular { + +void Scene4xx::setAAName() { + _game._aaName = Resources::formatAAName(4); +} + +void Scene4xx::setPlayerSpritesPrefix() { + _vm->_sound->command(5); + Common::String oldName = _game._player._spritesPrefix; + + if ((_scene->_nextSceneId == 403) || (_scene->_nextSceneId == 409)) + _game._player._spritesPrefix = ""; + else if (_globals[kSexOfRex] == REX_FEMALE) + _game._player._spritesPrefix = "ROX"; + else + _game._player._spritesPrefix = "RXM"; + + _game._player._scalingVelocity = true; + + if (oldName != _game._player._spritesPrefix) + _game._player._spritesChanged = true; + + _vm->_palette->setEntry(16, 10, 63, 63); + _vm->_palette->setEntry(17, 10, 45, 45); +} + +void Scene4xx::sceneEntrySound() { + if (!_vm->_musicFlag) { + _vm->_sound->command(2); + return; + } + + switch (_scene->_nextSceneId) { + case 401: + _vm->_sound->startQueuedCommands(); + if (_scene->_priorSceneId == 402) + _vm->_sound->command(12, 64); + else + _vm->_sound->command(12, 1); + break; + + case 402: + _vm->_sound->startQueuedCommands(); + _vm->_sound->command(12, 127); + break; + + case 405: + case 407: + case 409: + case 410: + case 413: + _vm->_sound->command(10); + break; + + case 408: + _vm->_sound->command(52); + break; + + default: + break; + } +} + +/*------------------------------------------------------------------------*/ + +Scene401::Scene401(MADSEngine *vm) : Scene4xx(vm), _destPos(0, 0) { + _northFl = false; + _timer = 0; +} + +void Scene401::synchronize(Common::Serializer &s) { + Scene4xx::synchronize(s); + + s.syncAsByte(_northFl); + s.syncAsSint16LE(_destPos.x); + s.syncAsSint16LE(_destPos.y); + s.syncAsUint32LE(_timer); +} + +void Scene401::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene401::enter() { + if (_scene->_priorSceneId != -2) + _northFl = false; + + _timer = 0; + + if (_scene->_priorSceneId == 402) { + _game._player._playerPos = Common::Point(203, 115); + _game._player._facing = FACING_WEST; + } else if (_scene->_priorSceneId == 354) { + _game._player._playerPos = Common::Point(149, 90); + _game._player._facing = FACING_SOUTH; + _northFl = true; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(142, 131); + _game._player._facing = FACING_NORTH; + } + + _game.loadQuoteSet(0x1D4, 0); + sceneEntrySound(); +} + +void Scene401::step() { + if (_game._trigger == 70) { + _scene->_nextSceneId = 354; + _scene->_reloadSceneFlag = true; + } + + if (_game._trigger == 80) { + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._stepEnabled = true; + _game._player._visible = true; + _northFl = false; + _game._player.walk(Common::Point(149, 110), FACING_SOUTH); + } + + if (_scene->_frameStartTime >= _timer) { + int dist = 64 - ((_vm->hypotenuse(_game._player._playerPos.x - 219, _game._player._playerPos.y - 115) * 64) / 120); + + if (dist > 64) + dist = 64; + else if (dist < 1) + dist = 1; + + _vm->_sound->command(12, dist); + _timer = _scene->_frameStartTime + _game._player._ticksAmount; + } + +} + +void Scene401::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_NORTH)) { + _game._player.walk(Common::Point(149, 89), FACING_NORTH); + _northFl = false; + } + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH) && !_northFl) + _game._player._walkOffScreenSceneId = 405; + + if (_action.isAction(VERB_TAKE)) + _game._player._needToWalk = false; + + if (_game._player._needToWalk && _northFl) { + if (_globals[kSexOfRex] == REX_MALE) + _destPos = Common::Point(148, 94); + else + _destPos = Common::Point(149, 99); + + _game._player.walk(_destPos, FACING_SOUTH); + } +} + +void Scene401::actions() { + if ((_game._player._playerPos == _destPos) && _northFl) { + if (_globals[kSexOfRex] == REX_MALE) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _game._player._stepEnabled = false; + _game._player._visible = false; + _vm->_sound->command(21); + _scene->loadAnimation(formAnimName('s', 1), 70); + _globals[kHasBeenScanned] = true; + _vm->_sound->command(22); + int idx = _scene->_kernelMessages.add(Common::Point(153, 46), 0x1110, 32, 0, 60, _game.getQuote(0x1D4)); + _scene->_kernelMessages.setQuoted(idx, 4, true); + } + + if (_globals[kSexOfRex] == REX_FEMALE) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _game._player._stepEnabled = false; + _game._player._visible = false; + _vm->_sound->command(21); + _scene->loadAnimation(formAnimName('s', 2), 80); + _vm->_sound->command(23); + _globals[kHasBeenScanned] = true; + } + } + + if (_action.isAction(VERB_WALK_INTO, NOUN_BAR)) { + if (!_northFl) + _scene->_nextSceneId = 402; + } else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_NORTH)) + _scene->_nextSceneId = 354; + else if (_action.isAction(VERB_LOOK, NOUN_SCANNER)) { + if (_globals[kHasBeenScanned]) + _vm->_dialogs->show(40111); + else + _vm->_dialogs->show(40110); + } else if (_action.isAction(VERB_LOOK, NOUN_BAR)) + _vm->_dialogs->show(40112); + else if (_action.isAction(VERB_LOOK, NOUN_SIGN)) + _vm->_dialogs->show(40113); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH)) + _vm->_dialogs->show(40114); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_NORTH)) + _vm->_dialogs->show(40115); + else if (_action._lookFlag) + _vm->_dialogs->show(40116); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene402::Scene402(MADSEngine *vm) : Scene4xx(vm) { + _lightOn = false; + _blowingSmoke = false; + _leftWomanMoving = false; + _rightWomanMoving = false; + _firstTalkToGirlInChair = false; + _waitingGinnyMove = false; + _ginnyLooking = false; + _bigBeatFl = false; + _roxOnStool = false; + _bartenderSteady = false; + _bartenderHandsHips = false; + _bartenderLooksLeft = false; + _bartenderReady = false; + _bartenderTalking = false; + _bartenderCalled = false; + _conversationFl = false; + _activeTeleporter = false; + _activeArrows = false; + _activeArrow1 = false; + _activeArrow2 = false; + _activeArrow3 = false; + _cutSceneReady = false; + _cutSceneNeeded = false; + _helgaReady = false; + _refuseAlienLiquor = false; + + _drinkTimer = -1; + _beatCounter = -1; + _bartenderMode = -1; + _bartenderDialogNode = -1; + _bartenderCurrentQuestion = -1; + _helgaTalkMode = -1; + _roxMode = -1; + _rexMode = -1; + _talkTimer = -1; +} + +void Scene402::synchronize(Common::Serializer &s) { + Scene4xx::synchronize(s); + + s.syncAsByte(_lightOn); + s.syncAsByte(_blowingSmoke); + s.syncAsByte(_leftWomanMoving); + s.syncAsByte(_rightWomanMoving); + s.syncAsByte(_firstTalkToGirlInChair); + s.syncAsByte(_waitingGinnyMove); + s.syncAsByte(_ginnyLooking); + s.syncAsByte(_bigBeatFl); + s.syncAsByte(_roxOnStool); + s.syncAsByte(_bartenderSteady); + s.syncAsByte(_bartenderHandsHips); + s.syncAsByte(_bartenderLooksLeft); + s.syncAsByte(_bartenderReady); + s.syncAsByte(_bartenderTalking); + s.syncAsByte(_bartenderCalled); + s.syncAsByte(_conversationFl); + s.syncAsByte(_activeTeleporter); + s.syncAsByte(_activeArrows); + s.syncAsByte(_activeArrow1); + s.syncAsByte(_activeArrow2); + s.syncAsByte(_activeArrow3); + s.syncAsByte(_cutSceneReady); + s.syncAsByte(_cutSceneNeeded); + s.syncAsByte(_helgaReady); + s.syncAsByte(_refuseAlienLiquor); + + s.syncAsSint16LE(_drinkTimer); + s.syncAsSint16LE(_beatCounter); + s.syncAsSint16LE(_bartenderMode); + s.syncAsSint16LE(_bartenderDialogNode); + s.syncAsSint16LE(_bartenderCurrentQuestion); + s.syncAsSint16LE(_helgaTalkMode); + s.syncAsSint16LE(_roxMode); + s.syncAsSint16LE(_rexMode); + s.syncAsSint16LE(_talkTimer); +} + +void Scene402::setup() { + setPlayerSpritesPrefix(); + setAAName(); + + _scene->addActiveVocab(NOUN_BARTENDER); + _scene->addActiveVocab(NOUN_ALIEN_LIQUOR); + _scene->addActiveVocab(VERB_DRINK); + _scene->addActiveVocab(NOUN_BINOCULARS); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_CREDIT_CHIP); + _scene->addActiveVocab(VERB_TAKE); + _scene->addActiveVocab(NOUN_REPAIR_LIST); + _scene->addActiveVocab(VERB_LOOK_AT); +} + +void Scene402::setDialogNode(int node) { + if (node > 0) + _bartenderDialogNode = node; + + _game._player._stepEnabled = true; + + switch (node) { + case 0: + _scene->_userInterface.setup(kInputBuildingSentences); + _conversationFl = false; + _bartenderDialogNode = 0; + break; + + case 1: + _dialog1.start(); + _bartenderDialogNode = 1; + break; + + case 2: + _dialog2.start(); + _bartenderDialogNode = 2; + break; + + case 3: + _dialog3.start(); + _bartenderDialogNode = 3; + break; + + case 4: + _dialog4.start(); + _bartenderDialogNode = 4; + break; + + default: + break; + } +} + +void Scene402::handleConversation1() { + switch (_action._activeAction._verbId) { + case 0x214: { + int quoteId = 0; + int quotePosX = 0; + switch (_vm->getRandomNumber(1, 3)) { + case 1: + quoteId = 0x1E4; + _bartenderCurrentQuestion = 4; + quotePosX = 205; + break; + + case 2: + quoteId = 0x1E5; + _bartenderCurrentQuestion = 5; + quotePosX = 203; + break; + + case 3: + quoteId = 0x1E6; + _bartenderCurrentQuestion = 6; + quotePosX = 260; + break; + + default: + break; + } + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(quotePosX, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(quoteId)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 120; + setDialogNode(2); + } + break; + + case 0x215: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(260, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EC)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 120; + _bartenderCurrentQuestion = 1; + setDialogNode(3); + break; + + case 0x237: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(208, 41), 0xFDFC, 0, 0, 100, _game.getQuote(0x1FD)); + setDialogNode(0); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 1120; + break; + + default: + break; + } +} + +void Scene402::handleConversation2() { + switch (_action._activeAction._verbId) { + case 0x216: + _dialog2.write(0x216, false); + _dialog2.write(0x21D, true); + break; + + case 0x219: + _dialog2.write(0x219, false); + _dialog2.write(0x220, true); + break; + + case 0x21A: + _dialog2.write(0x21A, false); + _dialog2.write(0x223, true); + break; + + case 0x21B: + _dialog2.write(0x21B, false); + _dialog2.write(0x224, true); + break; + + case 0x21D: + _dialog2.write(0x21D, false); + _dialog2.write(0x227, true); + break; + + case 0x220: + _dialog2.write(0x220, false); + _dialog2.write(0x22A, true); + break; + + case 0x223: + _dialog2.write(0x223, false); + _dialog2.write(0x22D, true); + break; + + case 0x224: + _dialog2.write(0x224, false); + _dialog2.write(0x230, true); + break; + + case 0x227: + _dialog2.write(0x227, false); + break; + + case 0x22A: + _dialog2.write(0x22A, false); + break; + + case 0x22D: + _dialog2.write(0x22D, false); + break; + + case 0x230: + _dialog2.write(0x230, false); + break; + + case 0x21C: + setDialogNode(0); + break; + + default: + break; + + } + + if (_action._activeAction._verbId != 0x21C) { + switch (_vm->getRandomNumber(1, 3)) { + case 1: + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 180; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(198, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E7)); + _scene->_kernelMessages.add(Common::Point(201, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E8)); + _bartenderCurrentQuestion = 7; + break; + + case 2: + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 180; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(220, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E9)); + _scene->_kernelMessages.add(Common::Point(190, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EA)); + _bartenderCurrentQuestion = 8; + break; + + case 3: + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 150; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(196, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EB)); + _bartenderCurrentQuestion = 9; + break; + + default: + break; + } + _dialog2.start(); + } else { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(208, 41), 0xFDFC, 0, 0, 100, _game.getQuote(0x1FD)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 1120; + } +} + +void Scene402::handleConversation3() { + switch (_action._activeAction._verbId) { + case 0x233: + case 0x234: + case 0x235: + case 0x236: + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 86); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(188, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1ED)); + _scene->_kernelMessages.add(Common::Point(199, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EE)); + setDialogNode(4); + _bartenderCurrentQuestion = 2; + break; + + case 0x237: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(208, 41), 0xFDFC, 0, 0, 100, _game.getQuote(0x1FD)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 1120; + setDialogNode(0); + break; + + default: + break; + } +} + +void Scene402::handleConversation4() { + switch (_action._activeAction._verbId) { + case 0x238: + _scene->_kernelMessages.reset(); + setDialogNode(0); + _game._player._stepEnabled = false; + _scene->_kernelMessages.add(Common::Point(196, 13), 0xFDFC, 0, 0, 180, _game.getQuote(0x1F0)); + _scene->_kernelMessages.add(Common::Point(184, 27), 0xFDFC, 0, 0, 180, _game.getQuote(0x1F1)); + _scene->_kernelMessages.add(Common::Point(200, 41), 0xFDFC, 0, 0, 180, _game.getQuote(0x1F2)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 1100; + _dialog4.write(0x238, false); + _bartenderMode = 22; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(100, 95); + _refuseAlienLiquor = true; + break; + + case 0x239: + _game._player._stepEnabled = false; + _roxMode = 21; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 92); + _scene->_userInterface.setup(kInputBuildingSentences); + _conversationFl = false; + break; + + case 0x23A: + setDialogNode(0); + _game._player._stepEnabled = false; + _scene->_kernelMessages.add(Common::Point(193, 27), 0xFDFC, 0, 0, 150, _game.getQuote(0x1F4)); + _scene->_kernelMessages.add(Common::Point(230, 41), 0xFDFC, 0, 0, 150, _game.getQuote(0x1F5)); + _dialog4.write(0x23A, false); + _globals[kHasSaidTimer] = true; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 1100; + _bartenderMode = 22; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(100, 95); + _refuseAlienLiquor = true; + break; + + case 0x23D: + setDialogNode(0); + _game._player._stepEnabled = false; + _scene->_kernelMessages.add(Common::Point(153, 27), 0xFDFC, 0, 0, 150, _game.getQuote(0x1F6)); + _scene->_kernelMessages.add(Common::Point(230, 41), 0xFDFC, 0, 0, 150, _game.getQuote(0x1F7)); + _dialog4.write(0x23D, false); + _globals[kHasSaidBinocs] = true; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 1100; + _bartenderMode = 22; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(100, 95); + _refuseAlienLiquor = true; + break; + + case 0x23E: + _scene->_kernelMessages.reset(); + setDialogNode(0); + _game._player._stepEnabled = false; + _scene->_kernelMessages.add(Common::Point(205, 41), 0xFDFC, 0, 0, 100, _game.getQuote(0x1F8)); + _bartenderMode = 22; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 1050; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(50, 95); + _refuseAlienLiquor = true; + break; + + default: + break; + } +} + +void Scene402::handleDialogs() { + if (_game._trigger == 0) { + _scene->_kernelMessages.reset(); + _game._player._stepEnabled = false; + Common::String curQuote = _game.getQuote(_action._activeAction._verbId); + if (_vm->_font->getWidth(curQuote, _scene->_textSpacing) > 200) { + Common::String subQuote1, subQuote2; + _game.splitQuote(curQuote, subQuote1, subQuote2); + _scene->_kernelMessages.add(Common::Point(230, 42), 0x1110, 32, 0, 140, subQuote1); + _scene->_kernelMessages.add(Common::Point(230, 56), 0x1110, 32, 0, 140, subQuote2); + _scene->_sequences.addTimer(160, 120); + } else { + _scene->_kernelMessages.add(Common::Point(230, 56), 0x1110, 32, 1, 140, curQuote); + _scene->_sequences.addTimer(160, 120); + } + } else if (_game._trigger == 120) { + _game._player._stepEnabled = true; + switch (_bartenderDialogNode) { + case 1: + handleConversation1(); + break; + + case 2: + handleConversation2(); + break; + + case 3: + handleConversation3(); + break; + + case 4: + handleConversation4(); + break; + + default: + break; + } + } +} + +void Scene402::enter() { + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('n', -1)); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('g', 0)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('g', 1)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('a', 0)); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _globals._spriteIndexes[15] = _scene->_sprites.addSprites(formAnimName('x', 5)); + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('x', 4)); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('b', 0)); + _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('b', 1)); + _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('b', 2)); + _globals._spriteIndexes[12] = _scene->_sprites.addSprites(formAnimName('b', 3)); + _globals._spriteIndexes[13] = _scene->_sprites.addSprites(formAnimName('c', 0)); + _globals._spriteIndexes[14] = _scene->_sprites.addSprites(formAnimName('l', 0)); + _globals._spriteIndexes[16] = _scene->_sprites.addSprites(formAnimName('h', 0)); + _globals._spriteIndexes[17] = _scene->_sprites.addSprites(formAnimName('z', 0)); + _globals._spriteIndexes[18] = _scene->_sprites.addSprites(formAnimName('z', 1)); + _globals._spriteIndexes[19] = _scene->_sprites.addSprites(formAnimName('z', 2)); + _globals._spriteIndexes[20] = _scene->_sprites.addSprites(formAnimName('x', 6)); + _globals._spriteIndexes[21] = _scene->_sprites.addSprites("*ROXRC_9"); + _globals._spriteIndexes[22] = _scene->_sprites.addSprites("*ROXCL_8"); + + if (_scene->_priorSceneId == 401) { + _game._player._playerPos = Common::Point(160, 150); + _game._player._facing = FACING_NORTH; + _roxOnStool = false; + _bartenderDialogNode = 1; + _conversationFl = false; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(160, 150); + _game._player._facing = FACING_NORTH; + _game._objects.addToInventory(OBJ_CREDIT_CHIP); + _game._objects.addToInventory(OBJ_BINOCULARS); + _game._objects.addToInventory(OBJ_TIMER_MODULE); + _roxOnStool = false; + _bartenderDialogNode = 1; + _conversationFl = false; + } + + _game.loadQuoteSet(0x1D7, 0x1D8, 0x1D9, 0x1DA, 0x1DB, 0x1DC, 0x1DD, 0x1DE, 0x1DF, 0x1E2, 0x1E3, 0x1E6, 0x1E5, 0x1E7, + 0x1E8, 0x1E9, 0x1EA, 0x1EF, 0x1F0, 0x1F1, 0x1F2, 0x1F3, 0x1F4, 0x1F5, 0x1F6, 0x1F7, 0x1F8, 0x1F9, 0x1FA, 0x1FB, + 0x1FC, 0x1EB, 0x1EC, 0x1ED, 0x1EE, 0x1E4, 0x1FD, 0x1E0, 0x1E1, 0x1FE, 0x1FF, 0x200, 0x201, 0x202, 0x203, 0x204, + 0x205, 0x206, 0x207, 0x208, 0x209, 0x20A, 0x20B, 0x20C, 0x20F, 0x20D, 0x20E, 0x210, 0x211, 0x212, 0x213, 0x214, + 0x215, 0x237, 0x216, 0x219, 0x21A, 0x21B, 0x21C, 0x21D, 0x220, 0x223, 0x224, 0x227, 0x22A, 0x22D, 0x230, 0x233, + 0x234, 0x235, 0x236, 0x238, 0x239, 0x23A, 0x23D, 0x23E, 0x23F, 0); + + _vm->_palette->setEntry(250, 47, 41, 40); + _vm->_palette->setEntry(251, 50, 63, 55); + _vm->_palette->setEntry(252, 38, 34, 25); + _vm->_palette->setEntry(253, 45, 41, 35); + + _dialog1.setup(0x60, 0x214, 0x215, 0x237, 0); + _dialog2.setup(0x61, 0x216, 0x219, 0x21A, 0x21B, 0x21D, 0x220, 0x223, 0x224, 0x227, 0x22A, 0x22D, 0x230, 0x21C, 0); + _dialog3.setup(0x62, 0x233, 0x234, 0x235, 0x236, 0x237, -1); + _dialog4.setup(0x63, 0x238, 0x239, 0x23A, 0x23D, 0x23E, 0); + + if (!_game._visitedScenes._sceneRevisited) { + _dialog2.set(0x61, 0x216, 0x219, 0x21A, 0x21B, 0x21C, 0); + _dialog4.set(0x63, 0x238, 0x23E, 0); + _dialog1.set(0x60, 0x214, 0x215, 0x237, 0); + } + + if (_game._objects.isInInventory(OBJ_CREDIT_CHIP)) + _dialog4.write(0x239, true); + else + _dialog4.write(0x239, false); + + if (_game._objects.isInInventory(OBJ_BINOCULARS) && !_globals[kHasSaidBinocs]) + _dialog4.write(0x23D, true); + else + _dialog4.write(0x23D, false); + + if (_game._objects.isInInventory(OBJ_TIMER_MODULE) && !_globals[kHasSaidTimer]) + _dialog4.write(0x23A, true); + else + _dialog4.write(0x23A, false); + + if (_dialog2.read(0) <= 1) + _dialog1.write(0x214, false); + + if (_conversationFl) { + switch (_bartenderDialogNode) { + case 0: + _scene->_userInterface.setup(kInputBuildingSentences); + _bartenderDialogNode = 1; + break; + + case 1: + _dialog1.start(); + break; + + case 2: + _dialog2.start(); + break; + + case 3: + _dialog3.start(); + break; + + case 4: + _dialog4.start(); + break; + + default: + break; + } + + switch (_bartenderCurrentQuestion) { + case 1: + _scene->_kernelMessages.add(Common::Point(260, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EC)); + break; + + case 2: + _scene->_kernelMessages.add(Common::Point(188, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1ED)); + _scene->_kernelMessages.add(Common::Point(199, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EE)); + break; + + case 3: + _scene->_kernelMessages.add(Common::Point(177, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EF)); + break; + + case 4: + _scene->_kernelMessages.add(Common::Point(205, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E4)); + break; + + case 5: + _scene->_kernelMessages.add(Common::Point(203, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E5)); + break; + + case 6: + _scene->_kernelMessages.add(Common::Point(260, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E6)); + break; + + case 7: + _scene->_kernelMessages.add(Common::Point(198, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E7)); + _scene->_kernelMessages.add(Common::Point(201, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E8)); + break; + + case 8: + _scene->_kernelMessages.add(Common::Point(220, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E9)); + _scene->_kernelMessages.add(Common::Point(190, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EA)); + break; + + case 9: + _scene->_kernelMessages.add(Common::Point(196, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EB)); + break; + + case 10: + _scene->_kernelMessages.add(Common::Point(198, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E2)); + _scene->_kernelMessages.add(Common::Point(199, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E3)); + break; + + default: + break; + } + } + + _firstTalkToGirlInChair = false; + _lightOn = false; + _blowingSmoke = false; + _leftWomanMoving = false; + _rightWomanMoving = false; + _ginnyLooking = false; + _beatCounter = 0; + _waitingGinnyMove = false; + _bigBeatFl = true; + _bartenderHandsHips = false; + _bartenderSteady = true; + _bartenderLooksLeft = false; + _activeTeleporter = false; + _activeArrows = false; + _activeArrow1 = false; + _activeArrow2 = false; + _activeArrow3 = false; + _cutSceneReady = false; + _cutSceneNeeded = false; + _helgaReady = true; + _bartenderReady = true; + _drinkTimer = 0; + _bartenderTalking = false; + _bartenderCalled = false; + _helgaTalkMode = 0; + _rexMode = 0; + _refuseAlienLiquor = false; + + _scene->loadAnimation(Resources::formatName(402, 'd', 1, EXT_AA, "")); + _scene->_activeAnimation->_resetFlag = true; + + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1); + + _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + + if (!_game._objects.isInInventory(OBJ_REPAIR_LIST)) { + _globals._sequenceIndexes[14] = _scene->_sequences.startCycle(_globals._spriteIndexes[14], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[14], 7); + _scene->_sequences.setPosition(_globals._sequenceIndexes[14], Common::Point(210, 80)); + int idx = _scene->_dynamicHotspots.add(NOUN_REPAIR_LIST, VERB_LOOK_AT, _globals._sequenceIndexes[14], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_NONE); + } + + { + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH); + } + + if (!_game._objects.isInRoom(OBJ_ALIEN_LIQUOR) && !_game._objects.isInInventory(OBJ_CREDIT_CHIP)) { + _globals._sequenceIndexes[15] = _scene->_sequences.startCycle(_globals._spriteIndexes[15], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[15], 8); + _scene->_sequences.setPosition(_globals._sequenceIndexes[15], Common::Point(250, 80)); + int idx = _scene->_dynamicHotspots.add(NOUN_CREDIT_CHIP, VERB_TAKE, _globals._sequenceIndexes[15], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_NONE); + } + + _globals._sequenceIndexes[20] = _scene->_sequences.startCycle(_globals._spriteIndexes[20], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[20], 7); + _scene->_sequences.setPosition(_globals._sequenceIndexes[20], Common::Point(234, 72)); + + if (_globals[kBottleDisplayed]) { + _globals._sequenceIndexes[8] = _scene->_sequences.startCycle(_globals._spriteIndexes[8], false, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 7); + } + + if (_roxOnStool) { + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 5); + _game._player._visible = false; + } + + sceneEntrySound(); +} + +void Scene402::step() { + if (_game._trigger == 104) { + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + _scene->_sequences.remove(_globals._sequenceIndexes[15]); + _game._objects.addToInventory(OBJ_CREDIT_CHIP); + _vm->_dialogs->showItem(OBJ_CREDIT_CHIP, 40242); + _game._player._stepEnabled = true; + } + + if ((_vm->getRandomNumber(1, 1500) == 1) && (!_activeTeleporter) && (_game._player._playerPos.x < 150)) { + _vm->_sound->command(30); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 13, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 14); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 48); + _activeTeleporter = true; + _globals[kSomeoneHasExploded] = true; + } + + if (_game._trigger == 48) + _activeTeleporter = false; + + if (_game._trigger == 100) { + _bartenderReady = false; + if (_bartenderHandsHips) { + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _bartenderHandsHips = false; + } else if (_bartenderLooksLeft) { + _scene->_sequences.remove(_globals._sequenceIndexes[11]); + _bartenderLooksLeft = false; + } else if (_bartenderSteady) { + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _bartenderSteady = false; + } + + if (!_bartenderTalking) { + _globals._sequenceIndexes[10] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[10], false, 7, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 3, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[10], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH); + _bartenderTalking = true; + if (_talkTimer > 1000) + _scene->_sequences.addTimer(_talkTimer - 1000, 101); + else + _scene->_sequences.addTimer(_talkTimer, 101); + } + } + + if ((_game._trigger == 101) && _bartenderTalking) { + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1); + int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + _bartenderSteady = true; + _bartenderTalking = false; + if (_talkTimer < 1000) + _bartenderReady = true; + } + + if (_game._trigger == 28) + _game._player._stepEnabled = true; + + switch (_game._trigger) { + case 92: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[6]); + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 1, 2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 93); + break; + + case 93: { + int seqIdx = _globals._sequenceIndexes[7]; + switch (_roxMode) { + case 20: + _vm->_sound->command(57); + _scene->_sequences.remove(_globals._sequenceIndexes[15]); + _game._objects.addToInventory(OBJ_CREDIT_CHIP); + _vm->_dialogs->showItem(OBJ_CREDIT_CHIP, 40242); + break; + + case 22: + _vm->_sound->command(57); + _scene->_sequences.remove(_globals._sequenceIndexes[8]); + _game._objects.addToInventory(OBJ_ALIEN_LIQUOR); + _globals[kBottleDisplayed] = false; + _vm->_dialogs->showItem(OBJ_ALIEN_LIQUOR, 40241); + break; + + case 21: + _globals._sequenceIndexes[15] = _scene->_sequences.startCycle(_globals._spriteIndexes[15], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[15], 8); + _scene->_sequences.setPosition(_globals._sequenceIndexes[15], Common::Point(250, 80)); + break; + + default: + break; + } + _globals._sequenceIndexes[7] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[7], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 1, 3); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 5); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[7], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 94); + + if (_roxMode == 21) { + if (_game._objects.isInInventory(OBJ_CREDIT_CHIP)) + _game._objects.setRoom (OBJ_CREDIT_CHIP, NOWHERE); + + _bartenderMode = 20; + _scene->_sequences.addTimer(60, 95); + } + } + break; + + case 94: { + int seqIdx = _globals._sequenceIndexes[7]; + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 5); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[6], seqIdx); + if (_roxMode == 22) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(230, 56), 0x1110, 32, 0, 120, _game.getQuote(0x23F)); + _bartenderMode = 21; + _globals[kHasPurchased] = true; + _scene->_sequences.addTimer(140, 95); + } else if (_roxMode == 20) + _game._player._stepEnabled = true; + + } + break; + } + + switch (_game._trigger) { + case 95: + _bartenderReady = false; + _game._player._stepEnabled = false; + if (_bartenderHandsHips || _bartenderTalking) { + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _bartenderHandsHips = false; + _bartenderTalking = false; + } + + if (_bartenderLooksLeft) { + _scene->_sequences.remove(_globals._sequenceIndexes[11]); + _bartenderLooksLeft = false; + } + + if (_bartenderSteady) { + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _bartenderSteady = false; + } + _globals._sequenceIndexes[12] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[12], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[12], 1, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 96); + break; + + case 96: { + int seqIdx = _globals._sequenceIndexes[12]; + _globals._sequenceIndexes[12] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[12], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[12], 6, 7); + _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[12], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 97); + } + break; + + case 97: { + int seqIdx = _globals._sequenceIndexes[12]; + switch (_bartenderMode) { + case 20: + _scene->_sequences.remove(_globals._sequenceIndexes[15]); + break; + + case 21: { + _globals._sequenceIndexes[15] = _scene->_sequences.startCycle(_globals._spriteIndexes[15], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[15], 8); + _scene->_sequences.setPosition(_globals._sequenceIndexes[15], Common::Point(250, 80)); + int idx = _scene->_dynamicHotspots.add(NOUN_CREDIT_CHIP, VERB_TAKE, _globals._sequenceIndexes[15], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_NONE); + } + break; + + case 22: + _scene->_sequences.remove(_globals._sequenceIndexes[8]); + _globals[kBottleDisplayed] = false; + break; + + default: + break; + } + + _globals._sequenceIndexes[12] = _scene->_sequences.startCycle(_globals._spriteIndexes[12], false, 6); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[12], seqIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 8); + _scene->_sequences.addTimer(10, 98); + } + break; + + case 98: + _scene->_sequences.remove(_globals._sequenceIndexes[12]); + _globals._sequenceIndexes[12] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[12], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[12], 1, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 99); + break; + + case 99: { + int seqIdx = _globals._sequenceIndexes[12]; + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1); + _bartenderSteady = true; + int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], seqIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + if (_bartenderMode == 20) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(210, 41), 0xFDFC, 0, 0, 100, _game.getQuote(0x1F3)); + _scene->_sequences.addTimer(5, 100); + _talkTimer = 180; + _roxMode = 22; + _scene->_sequences.addTimer(65, 92); + } else if ((_bartenderMode == 21) || (_bartenderMode == 22)) { + _game._player._stepEnabled = true; + _bartenderReady = true; + } + + } + break; + } + + switch (_game._trigger) { + case 86: + _bartenderReady = false; + _game._player._stepEnabled = false; + if ((_bartenderHandsHips) || (_bartenderTalking)) { + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _bartenderHandsHips = false; + _bartenderTalking = false; + } else if (_bartenderLooksLeft) { + _scene->_sequences.remove(_globals._sequenceIndexes[11]); + _bartenderLooksLeft = false; + } else if (_bartenderSteady) { + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _bartenderSteady = false; + } + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 1, 9); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 87); + break; + + case 87: { + int seqIdx = _globals._sequenceIndexes[9]; + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 9); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], seqIdx); + _scene->_sequences.addTimer(10, 89); + + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 1, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 7); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 88); + } + break; + + case 88: + _globals._sequenceIndexes[8] = _scene->_sequences.startCycle(_globals._spriteIndexes[8], false, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 7); + _globals[kBottleDisplayed] = true; + break; + + case 89: + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + _scene->_sequences.addTimer(10, 90); + break; + + case 90: + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + _scene->_sequences.addTimer(10, 91); + break; + + case 91: { + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1); + int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + _bartenderSteady = true; + _game._player._stepEnabled = true; + _bartenderReady = true; + } + break; + } + + if (!_waitingGinnyMove && !_ginnyLooking) { + _waitingGinnyMove = true; + ++ _beatCounter; + if (_beatCounter >= 20) { + _ginnyLooking = true; + _beatCounter = 0; + _scene->_sequences.addTimer(60, 54); + } else { + _scene->_sequences.addTimer(30, 75); + } + } + + switch (_game._trigger) { + case 75: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _bigBeatFl = !_bigBeatFl; + + if (_bigBeatFl) { + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 5); + _scene->_sequences.addTimer(8, 130); + } else { + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 5); + _scene->_sequences.addTimer(8, 53); + } + + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1); + break; + + case 130: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1); + _scene->_sequences.addTimer(8, 131); + break; + + case 131: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1); + _scene->_sequences.addTimer(8, 53); + break; + + case 53: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1); + _waitingGinnyMove = false; + break; + } + + if ((_game._trigger == 54) && _ginnyLooking) { + ++_beatCounter; + if (_beatCounter >= 10) { + _ginnyLooking = false; + _waitingGinnyMove = false; + _beatCounter = 0; + _bigBeatFl = true; + } else { + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, _vm->getRandomNumber(1, 4)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1); + _scene->_sequences.addTimer(60, 54); + } + } + + if (_bartenderReady) { + if (_vm->getRandomNumber(1, 250) == 1) { + if (_bartenderLooksLeft) { + _scene->_sequences.remove(_globals._sequenceIndexes[11]); + _bartenderLooksLeft = false; + } else if (_bartenderHandsHips) { + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _bartenderHandsHips = false; + } else if (_bartenderSteady) { + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _bartenderSteady = false; + } + + switch (_vm->getRandomNumber(1, 3)) { + case 1: { + _globals._sequenceIndexes[10] = _scene->_sequences.startCycle(_globals._spriteIndexes[10], false, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[10], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH); + _bartenderHandsHips = true; + } + break; + + case 2: { + _globals._sequenceIndexes[11] = _scene->_sequences.startCycle(_globals._spriteIndexes[11], false, 2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[11], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[11], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH); + _bartenderLooksLeft = true; + } + break; + + case 3: { + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH); + _bartenderSteady = true; + } + break; + + default: + break; + } + } + } + + if (_game._trigger == 76) { + int seqIdx = _globals._sequenceIndexes[6]; + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 5); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[6], seqIdx); + if (!_globals[kBeenThruHelgaScene]) { + _game._player._stepEnabled = false; + _cutSceneNeeded = true; + } else { + _game._player._stepEnabled = true; + } + _roxOnStool = true; + } + + switch (_game._trigger) { + case 77: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[6]); + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 10, 12); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 78); + break; + + case 78: { + _vm->_sound->command(57); + int seqIdx = _globals._sequenceIndexes[7]; + _game._objects.addToInventory(OBJ_REPAIR_LIST); + _scene->_sequences.remove(_globals._sequenceIndexes[14]); + _globals._sequenceIndexes[7] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[7], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 10, 12); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 5); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[7], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 79); + } + break; + + case 79: { + int seqIdx = _globals._sequenceIndexes[7]; + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 5); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[6], seqIdx); + _scene->_sequences.addTimer(20, 180); + } + break; + + case 180: + _vm->_dialogs->showItem(OBJ_REPAIR_LIST, 40240); + _game._player._stepEnabled = true; + break; + + default: + break; + } + + if (_cutSceneNeeded && _cutSceneReady) { + _cutSceneNeeded = false; + _scene->_sequences.addTimer(20, 55); + _helgaReady = false; + _bartenderReady = false; + } + + if (_vm->getRandomNumber(1, 25) == 1) { + if (_lightOn) { + _scene->_sequences.remove(_globals._sequenceIndexes[0]); + _lightOn = false; + } else { + _globals._sequenceIndexes[0] = _scene->_sequences.startCycle(_globals._spriteIndexes[0], false, 1); + _lightOn = true; + } + } + + if (!_blowingSmoke && (_vm->getRandomNumber(1, 300) == 1)) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 14); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 14); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 30); + _blowingSmoke = true; + } + + switch (_game._trigger) { + case 30: + _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[1], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 14); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1],SEQUENCE_TRIGGER_EXPIRE, 0, 31); + break; + + case 31: + _blowingSmoke = false; + break; + } + + if (!_leftWomanMoving) { + if (_vm->getRandomNumber(1, 1000) == 1) { + switch (_vm->getRandomNumber(1, 2)) { + case 1: + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 33); + _leftWomanMoving = true; + break; + + case 2: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + _scene->_sequences.addTimer(12, 35); + _leftWomanMoving = true; + break; + + default: + break; + } + } + } + + switch (_game._trigger) { + case 33: { + int seqIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 9); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], seqIdx); + _scene->_sequences.addTimer(_vm->getRandomNumber(60, 250), 34); + } + break; + + case 34: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 38); + break; + + case 35: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 2); + _scene->_sequences.addTimer(_vm->getRandomNumber(60, 300), 36); + break; + + case 36: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + _scene->_sequences.addTimer(12, 37); + break; + + case 37: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _leftWomanMoving = false; + break; + + case 38: + _leftWomanMoving = false; + break; + + default: + break; + } + + if (!_rightWomanMoving) { + if (_vm->getRandomNumber(1, 300) == 1) { + switch (_vm->getRandomNumber(1, 4)) { + case 1: + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 32); + _rightWomanMoving = true; + break; + + case 2: + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 4, 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 32); + _rightWomanMoving = true; + break; + + case 3: + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 4, 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 32); + _rightWomanMoving = true; + break; + + case 4: + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 3, 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 32); + _rightWomanMoving = true; + break; + + default: + break; + } + } + } + + if (_game._trigger == 32) + _rightWomanMoving = false; + + if (_scene->_activeAnimation->getCurrentFrame() == 1) { + switch (_vm->getRandomNumber(1, 50)) { + case 1: + _scene->_activeAnimation->setCurrentFrame(2); + break; + + case 2: + _scene->_activeAnimation->setCurrentFrame(7); + break; + + case 3: + _scene->_activeAnimation->setCurrentFrame(11); + break; + + default: + _scene->_activeAnimation->setCurrentFrame(0); + break; + } + } + + if ((_scene->_activeAnimation->getCurrentFrame() == 4) && (_drinkTimer < 10)) { + ++ _drinkTimer; + _scene->_activeAnimation->setCurrentFrame(3); + } + + if (_drinkTimer == 10) { + _drinkTimer = 0; + _scene->_activeAnimation->setCurrentFrame(4); + _scene->_activeAnimation->_currentFrame = 5; + } + + + switch (_scene->_activeAnimation->getCurrentFrame()) { + case 6: + case 10: + case 14: + _scene->_activeAnimation->setCurrentFrame(0); + break; + + default: + break; + } + + switch (_game._trigger) { + case 39: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(89, 67), 0xFDFC, 32, 0, 120, _game.getQuote(0x1D8)); + _scene->_sequences.addTimer(150, 40); + break; + + case 40: + _scene->_kernelMessages.add(Common::Point(89, 67), 0xFDFC, 32, 0, 120, _game.getQuote(0x1D9)); + _scene->_sequences.addTimer(150, 41); + break; + + case 41: + _scene->_kernelMessages.add(Common::Point(89, 67), 0xFDFC, 32, 0, 120, _game.getQuote(0x1DA)); + _game._player._stepEnabled = true; + break; + + case 42: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(89, 67), 0xFDFC, 32, 0, 120, _game.getQuote(0x1DC)); + _scene->_sequences.addTimer(150, 43); + break; + + case 43: + _scene->_kernelMessages.add(Common::Point(89, 67), 0xFDFC, 32, 0, 120, _game.getQuote(0x1DD)); + _game._player._stepEnabled = true; + break; + + case 44: + _game._player._stepEnabled = true; + break; + + default: + break; + } + + switch (_game._trigger) { + case 55: + if (_bartenderHandsHips) { + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _bartenderHandsHips = false; + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1); + int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH); + _bartenderSteady = true; + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + } else if (_bartenderLooksLeft) { + _scene->_sequences.remove(_globals._sequenceIndexes[11]); + _bartenderLooksLeft = false; + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1); + int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH); + _bartenderSteady = true; + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + } + _game._player._stepEnabled = false; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(180, 47), 0xFBFA, 0, 0, 100, _game.getQuote(0x1FE)); + _scene->_sequences.addTimer(120, 56); + break; + + case 56: + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 2, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 57); + break; + + case 57: { + int seqIdx = _globals._sequenceIndexes[13]; + _scene->_sequences.remove(_globals._sequenceIndexes[20]); + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 6, 9); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 58); + } + break; + + case 58: { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 5, 9); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 59); + } + break; + + case 59: { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 1, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 60); + _globals._sequenceIndexes[20] = _scene->_sequences.startCycle(_globals._spriteIndexes[20], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[20], 8); + _scene->_sequences.setPosition(_globals._sequenceIndexes[20], Common::Point(234, 72)); + } + break; + + case 60: { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 2); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addTimer(10, 61); + } + break; + + case 61: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(181, 33), 0xFBFA, 0, 0, 130, _game.getQuote(0x1FF)); + _scene->_kernelMessages.add(Common::Point(171, 47), 0xFBFA, 0, 0, 130, _game.getQuote(0x200)); + _scene->_sequences.addTimer(150, 63); + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 30, 4, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 10, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 62); + break; + + case 62: { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 2); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + } + break; + + case 63: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(160, 33), 0xFBFA, 0, 0, 130, _game.getQuote(0x201)); + _scene->_kernelMessages.add(Common::Point(165, 47), 0xFBFA, 0, 0, 130, _game.getQuote(0x202)); + _scene->_sequences.addTimer(150, 64); + break; + + case 64: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(210, 27), 0xFDFC, 0, 0, 130, _game.getQuote(0x1E0)); + _scene->_kernelMessages.add(Common::Point(198, 41), 0xFDFC, 0, 0, 130, _game.getQuote(0x1E1)); + _scene->_sequences.addTimer(150, 65); + _scene->_sequences.addTimer(1, 100); + _talkTimer = 1130; + break; + + case 65: + _vm->_sound->command(30); + _globals._sequenceIndexes[16] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[16], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[16], 1, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[16], 9); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[16], SEQUENCE_TRIGGER_EXPIRE, 0, 66); + break; + + case 66: { + int seqIdx = _globals._sequenceIndexes[16]; + _globals._sequenceIndexes[16] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[16], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[16], 7, 37); + _scene->_sequences.setDepth(_globals._sequenceIndexes[16], 9); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[16], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[16], SEQUENCE_TRIGGER_EXPIRE, 0, 68); + + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 12, 13); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 67); + } + break; + + case 67: { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 13); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + } + break; + + case 68: + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 12, 13); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 69); + break; + + case 69: { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 25, 4, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 10, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(179, 33), 0xFBFA, 0, 0, 130, _game.getQuote(0x203)); + _scene->_kernelMessages.add(Common::Point(167, 47), 0xFBFA, 0, 0, 130, _game.getQuote(0x204)); + _scene->_sequences.addTimer(150, 71); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 70); + } + break; + + case 70: + _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 25, 4, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 10, 12); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + break; + + case 71: + _scene->_sequences.addTimer(210, 73); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(168, 33), 0xFBFA, 0, 0, 180, _game.getQuote(0x205)); + _scene->_kernelMessages.add(Common::Point(151, 47), 0xFBFA, 0, 0, 180, _game.getQuote(0x206)); + if (!_game._objects.isInInventory(OBJ_REPAIR_LIST)) + _activeArrows = true; + break; + + case 72: { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 2); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + } + break; + + case 73: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(177, 33), 0xFBFA, 0, 0, 150, _game.getQuote(0x207)); + _scene->_kernelMessages.add(Common::Point(172, 47), 0xFBFA, 0, 0, 150, _game.getQuote(0x208)); + _bartenderSteady = true; + _game._player._stepEnabled = true; + _helgaReady = true; + _bartenderReady = true; + _globals[kBeenThruHelgaScene] = true; + _activeArrows = false; + break; + + default: + break; + } + + if (_helgaReady) { + int rndVal = _vm->getRandomNumber(1, 1000); + if (rndVal < 6) + switch (rndVal) { + case 1: + _cutSceneReady = false; + _helgaReady = false; + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 2, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 82); + break; + + case 2: + _cutSceneReady = false; + _helgaReady = false; + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 15, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 11, 13); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 26); + break; + + case 3: + _cutSceneReady = false; + _helgaReady = false; + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 10, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 26); + break; + + case 4: + _cutSceneReady = false; + _helgaReady = false; + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 15, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 14, 15); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 26); + break; + + case 5: + _cutSceneReady = false; + _helgaReady = false; + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 16, 19); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 80); + break; + + default: + break; + } + } + + if (_game._trigger == 80) { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 19); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addTimer(_vm->getRandomNumber(60, 120), 81); + } + + if (_game._trigger == 81) { + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 16, 19); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 26); + } + + if (_game._trigger == 26) { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 2); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _cutSceneReady = true; + + if (!_cutSceneNeeded) + _helgaReady = true; + } + + if (_game._trigger == 82) { + _scene->_sequences.remove(_globals._sequenceIndexes[20]); + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 6, 9); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 83); + } + + if (_game._trigger == 83) { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 5, 9); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 84); + } + + if (_game._trigger == 84) { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 1, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 85); + + _globals._sequenceIndexes[20] = _scene->_sequences.startCycle(_globals._spriteIndexes[20], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[20], 8); + _scene->_sequences.setPosition(_globals._sequenceIndexes[20], Common::Point(234, 72)); + } + + if (_game._trigger == 85) { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 2); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _cutSceneReady = true; + if (!_cutSceneNeeded) + _helgaReady = true; + } + + if (_game._trigger == 102) { + _scene->_sequences.remove(_globals._sequenceIndexes[6]); + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 14, 18); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 103); + } else if (_game._trigger == 103) { + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _roxOnStool = false; + _game._player._facing = FACING_SOUTH; + _game._player.selectSeries(); + _game._player._visible = true; + _game._player._stepEnabled = true; + _game._player._readyToWalk = true; + } + + if (_activeArrows) { + if (!_activeArrow1) { + _globals._sequenceIndexes[17] = _scene->_sequences.startCycle(_globals._spriteIndexes[17], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[17], 1); + _scene->_sequences.addTimer(_vm->getRandomNumber(10, 15), 49); + _activeArrow1 = true; + } + + if (!_activeArrow2) { + _globals._sequenceIndexes[18] = _scene->_sequences.startCycle(_globals._spriteIndexes[18], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[18], 1); + _scene->_sequences.addTimer(_vm->getRandomNumber(10, 15), 50); + _activeArrow2 = true; + } + + if (!_activeArrow3) { + _globals._sequenceIndexes[19] = _scene->_sequences.startCycle(_globals._spriteIndexes[19], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[19], 1); + _scene->_sequences.addTimer(_vm->getRandomNumber(10, 15), 51); + _activeArrow3 = true; + } + } + + if (_game._trigger == 49) { + _scene->_sequences.remove(_globals._sequenceIndexes[17]); + _scene->_sequences.addTimer(_vm->getRandomNumber(10, 15), 45); + } + + if (_game._trigger == 45) + _activeArrow1 = false; + + if (_game._trigger == 50) { + _scene->_sequences.remove(_globals._sequenceIndexes[18]); + _scene->_sequences.addTimer(_vm->getRandomNumber(10, 15), 46); + } + + if (_game._trigger == 46) + _activeArrow2 = false; + + if (_game._trigger == 51) { + _scene->_sequences.remove(_globals._sequenceIndexes[19]); + _scene->_sequences.addTimer(_vm->getRandomNumber(10, 15), 47); + } + + if (_game._trigger == 47) + _activeArrow3 = false; +} + +void Scene402::preActions() { + if (_action.isAction(VERB_SIT_ON, NOUN_BAR_STOOL) && (_game._player._prepareWalkPos.x != 248)) + _game._player.walk(Common::Point(232, 112), FACING_EAST); + + if (_action.isAction(VERB_WALKTO, NOUN_WOMAN_ON_BALCONY)) + _game._player._needToWalk = _game._player._readyToWalk; + + if (!_roxOnStool && _action.isAction(VERB_TAKE, NOUN_CREDIT_CHIP) && !_game._objects.isInInventory(OBJ_CREDIT_CHIP)) + _game._player.walk(Common::Point(246, 108), FACING_NORTH); + + if (_action.isAction(VERB_TAKE)) + _game._player._needToWalk = false; + + if (_action.isAction(VERB_TAKE, NOUN_CREDIT_CHIP) && !_roxOnStool) + _game._player._needToWalk = true; + + if (_roxOnStool) { + if (_action.isAction(VERB_LOOK) || _action.isObject(NOUN_BAR_STOOL) || _action.isAction(VERB_TALKTO)) + _game._player._needToWalk = false; + + if (_action.isAction(VERB_TAKE, NOUN_REPAIR_LIST) || _action.isAction(VERB_TAKE, NOUN_CREDIT_CHIP)) + _game._player._needToWalk = false; + + if (_action.isAction(VERB_TALKTO, NOUN_WOMAN_IN_CHAIR) || _action.isAction(VERB_TALKTO, NOUN_WOMAN_IN_ALCOVE)) + _game._player._needToWalk = _game._player._readyToWalk; + + if (_game._player._needToWalk) { + _game._player._facing = FACING_SOUTH; + _game._player._readyToWalk = false; + _game._player._stepEnabled = false; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 102); + } + } + + if (_action.isAction(VERB_TAKE, NOUN_REPAIR_LIST) && !_roxOnStool && !_game._objects.isInInventory(OBJ_REPAIR_LIST)) + _game._player.walk(Common::Point(191, 99), FACING_NORTHEAST); + + if (_action.isAction(VERB_TALKTO, NOUN_BARTENDER) && !_roxOnStool) + _game._player.walk(Common::Point(228, 83), FACING_SOUTH); + + if (_action.isAction(VERB_TALKTO, NOUN_REPAIR_WOMAN) && !_roxOnStool) + _game._player.walk(Common::Point(208, 102), FACING_NORTHEAST); +} + +void Scene402::actions() { + if (_action.isAction(VERB_TAKE, NOUN_REPAIR_LIST) && _game._objects.isInRoom(OBJ_REPAIR_LIST) && _roxOnStool) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 77); + _game._player._needToWalk = false; + } else if (_action.isAction(VERB_TAKE, NOUN_REPAIR_LIST) && _game._objects.isInRoom(OBJ_REPAIR_LIST) && !_roxOnStool) { + if (_game._trigger == 0) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[21] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[21], false, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[21], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[21]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[21], SEQUENCE_TRIGGER_SPRITE, 2, 165); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[21], SEQUENCE_TRIGGER_EXPIRE, 0, 166); + } else if (_game._trigger == 165) { + _scene->_sequences.remove(_globals._sequenceIndexes[14]); + _game._objects.addToInventory(OBJ_REPAIR_LIST); + } + } else if (_game._trigger == 166) { + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + _scene->_sequences.addTimer(20, 167); + } else if (_game._trigger == 167) { + _vm->_dialogs->showItem(OBJ_REPAIR_LIST, 40240); + _game._player._stepEnabled = true; + } else if (_game._screenObjects._inputMode == 1) + handleDialogs(); + else if (_action.isAction(VERB_WALK_INTO, NOUN_CORRIDOR_TO_SOUTH)) + _scene->_nextSceneId = 401; + else if (_action.isAction(VERB_WALK_ONTO, NOUN_DANCE_FLOOR)) + ; // just... nothing + else if (_action.isAction(VERB_TALKTO, NOUN_REPAIR_WOMAN)) { + switch (_game._trigger) { + case 0: { + _game._player._stepEnabled = false; + int random = _vm->getRandomNumber(1, 3); + if (_helgaTalkMode == 0) + random = 1; + + int centerFlag; + Common::Point centerPos; + if (_roxOnStool) { + centerFlag = 0; + centerPos = Common::Point(230, 56); + } else { + centerFlag = 2; + centerPos = Common::Point(0, 0); + } + + switch (random) { + case 1: + _scene->_kernelMessages.add(centerPos, 0x1110, 32 | centerFlag, 0, 90, _game.getQuote(0x211)); + _scene->_sequences.addTimer(110, 25); + break; + + case 2: + _scene->_kernelMessages.add(centerPos, 0x1110, 32 | centerFlag, 0, 90, _game.getQuote(0x212)); + _scene->_sequences.addTimer(110, 25); + break; + + case 3: + _scene->_kernelMessages.add(centerPos, 0x1110, 32 | centerFlag, 0, 90, _game.getQuote(0x213)); + _scene->_sequences.addTimer(110, 25); + break; + + default: + break; + } + } + break; + + case 25: + switch (_helgaTalkMode) { + case 0: + _game._player._stepEnabled = false; + _helgaTalkMode = 1; + _scene->_kernelMessages.add(Common::Point(177, 33), 0xFBFA, 0, 0, 130, _game.getQuote(0x209)); + _scene->_kernelMessages.add(Common::Point(182, 47), 0xFBFA, 0, 0, 130, _game.getQuote(0x20A)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(130, 28); + break; + + case 1: + _game._player._stepEnabled = false; + _helgaTalkMode = 2; + _scene->_kernelMessages.add(Common::Point(157, 47), 0xFBFA, 0, 0, 100, _game.getQuote(0x20B)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(100, 28); + break; + + case 2: + _game._player._stepEnabled = false; + _helgaTalkMode = 3; + _scene->_kernelMessages.add(Common::Point(172, 47), 0xFBFA, 0, 0, 100, _game.getQuote(0x20C)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(100, 28); + break; + + case 3: + _game._player._stepEnabled = true; + break; + + default: + break; + } + break; + } + } else if (_action.isAction(VERB_TALKTO, NOUN_WOMAN_IN_CHAIR) && !_firstTalkToGirlInChair) { + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x1D7)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(150, 39); + _game._player._stepEnabled = false; + _firstTalkToGirlInChair = true; + } else if (_action.isAction(VERB_TALKTO, NOUN_WOMAN_IN_CHAIR) && _firstTalkToGirlInChair) { + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x1DB)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(150, 42); + _game._player._stepEnabled = false; + } else if (_action.isAction(VERB_TALKTO, NOUN_WOMAN_IN_ALCOVE) || _action.isAction(VERB_WALKTO, NOUN_WOMAN_IN_ALCOVE)) { + _scene->_kernelMessages.add(Common::Point(102, 48), 0xFBFA, 0, 0, 120, _game.getQuote(0x1DE)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(120, 44); + _game._player._stepEnabled = false; + } else if (_action.isAction(VERB_WALK_ALONG, NOUN_BAR_STOOL) && (_game._player._targetPos.x == 248)){ + _scene->_kernelMessages.add(Common::Point(0, -14), 0x1110, 34, 0, 120, _game.getQuote(0x20D)); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x20E)); + } else if (_action.isAction(VERB_WALK_ALONG, NOUN_BAR_STOOL) && !_roxOnStool && (_game._player._targetPos.x != 248)) { + _game._player._visible = false; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 76); + _game._player._stepEnabled = false; + } else if (_action.isAction(VERB_TAKE, NOUN_CREDIT_CHIP) && !_game._objects.isInInventory(OBJ_CREDIT_CHIP) && _roxOnStool) { + _roxMode = 20; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 92); + } else if (_action.isAction(VERB_TAKE, NOUN_CREDIT_CHIP) && !_game._objects.isInInventory(OBJ_CREDIT_CHIP) && !_roxOnStool) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[22] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[22], false, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[22], 1, 2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[22], Common::Point(_game._player._playerPos.x, _game._player._playerPos.y + 1)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[22], 5); + _scene->_sequences.setScale(_globals._sequenceIndexes[22], 88); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[22], SEQUENCE_TRIGGER_EXPIRE, 0, 104); + } else if (_action.isAction(VERB_TALKTO, NOUN_BARTENDER)) { + switch (_game._trigger) { + case 0: { + int centerFlag; + Common::Point centerPos; + if (_roxOnStool) { + centerFlag = 0; + centerPos = Common::Point(230, 56); + } else { + centerFlag = 2; + centerPos = Common::Point(0, 0); + } + + _game._player._stepEnabled = false; + int quoteId; + if (_bartenderCalled) { + quoteId = 0x210; + } else { + quoteId = 0x20F; + _bartenderCalled = true; + } + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(centerPos, 0x1110, 32 | centerFlag, 0, 90, _game.getQuote(quoteId)); + _scene->_sequences.addTimer(110, 29); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(90, 28); + } + break; + + case 29: + _scene->_kernelMessages.reset(); + if (!_roxOnStool) { + if (_game._objects.isInRoom(OBJ_ALIEN_LIQUOR)) { + _scene->_kernelMessages.add(Common::Point(177, 41), 0xFDFC, 0, 0, 120, _game.getQuote(0x1DF)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 120; + } else if (_rexMode == 0) { + _scene->_kernelMessages.add(Common::Point(175, 13), 0xFDFC, 0, 0, 180, _game.getQuote(0x1F9)); + _scene->_kernelMessages.add(Common::Point(184, 27), 0xFDFC, 0, 0, 180, _game.getQuote(0x1FA)); + _scene->_kernelMessages.add(Common::Point(200, 41), 0xFDFC, 0, 0, 180, _game.getQuote(0x1FB)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 180; + _rexMode = 1; + } else if (_rexMode == 1) { + _scene->_kernelMessages.add(Common::Point(205, 41), 0xFDFC, 0, 0, 120, _game.getQuote(0x1FC)); + _game._player._stepEnabled = true; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 120; + _rexMode = 3; + } else { + _game._player._stepEnabled = true; + } + } else { + if (_game._objects.isInRoom(OBJ_ALIEN_LIQUOR)) { + if (!_refuseAlienLiquor) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(198, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E2)); + _scene->_kernelMessages.add(Common::Point(199, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E3)); + _bartenderCurrentQuestion = 10; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 120; + _conversationFl = true; + _bartenderDialogNode = 1; + if (_dialog2.read(0) <= 1) + _dialog1.write(0x214, false); + + _dialog1.start(); + } else { + _scene->_kernelMessages.add(Common::Point(177, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EF)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 120; + _bartenderCurrentQuestion = 3; + _conversationFl = true; + _bartenderDialogNode = 1; + if (_dialog2.read(0) <= 1) + _dialog1.write(0x214, false); + + _dialog1.start(); + _game._player._stepEnabled = true; + } + } else { + if (_rexMode == 0) { + _scene->_kernelMessages.add(Common::Point(175, 13), 0xFDFC, 0, 0, 180, _game.getQuote(0x1F9)); + _scene->_kernelMessages.add(Common::Point(184, 27), 0xFDFC, 0, 0, 180, _game.getQuote(0x1FA)); + _scene->_kernelMessages.add(Common::Point(200, 41), 0xFDFC, 0, 0, 180, _game.getQuote(0x1FB)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 180; + _rexMode = 1; + } else if (_rexMode == 1) { + _scene->_kernelMessages.add(Common::Point(205, 41), 0xFDFC, 0, 0, 120, _game.getQuote(0x1FC)); + _game._player._stepEnabled = true; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 120; + _rexMode = 3; + } else { + _game._player._stepEnabled = true; + } + } + } + break; + + default: + break; + } + } else if (_action.isAction(VERB_LOOK, NOUN_DANCE_FLOOR)) + _vm->_dialogs->show(40210); + else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER)) { + if (_globals[kSomeoneHasExploded]) + _vm->_dialogs->show(40212); + else + _vm->_dialogs->show(40211); + } else if (_action.isAction(VERB_LOOK, NOUN_BAR)) + _vm->_dialogs->show(40213); + else if (_action.isAction(VERB_LOOK, NOUN_BARTENDER)) + _vm->_dialogs->show(40214); + else if (_action.isAction(VERB_LOOK, NOUN_WOMAN_IN_ALCOVE)) + _vm->_dialogs->show(40215); + else if (_action.isAction(VERB_LOOK, NOUN_WOMAN_ON_BALCONY)) + _vm->_dialogs->show(40216); + else if (_action.isAction(VERB_LOOK, NOUN_WOMAN_IN_CHAIR)) + _vm->_dialogs->show(40217); + else if (_action.isAction(VERB_LOOK, NOUN_REPAIR_WOMAN)) + _vm->_dialogs->show(40218); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH)) + _vm->_dialogs->show(40219); + else if (_action._lookFlag) + _vm->_dialogs->show(40220); + else if (_action.isAction(VERB_LOOK, NOUN_WOMEN)) + _vm->_dialogs->show(40221); + else if (_action.isAction(VERB_PUSH, NOUN_REPAIR_WOMAN) || _action.isAction(VERB_PULL, NOUN_REPAIR_WOMAN)) + _vm->_dialogs->show(40222); + else if (_action.isAction(VERB_TALKTO, NOUN_WOMEN)) + _vm->_dialogs->show(40223); + else if (_action.isAction(VERB_TALKTO, NOUN_WOMAN_ON_BALCONY)) + _vm->_dialogs->show(40224); + else if (_action.isAction(VERB_LOOK, NOUN_RAILING)) + _vm->_dialogs->show(40225); + else if (_action.isAction(VERB_LOOK, NOUN_TABLE)) + _vm->_dialogs->show(40226); + else if (_action.isAction(VERB_TAKE, NOUN_TABLE)) + _vm->_dialogs->show(40227); + else if (_action.isAction(VERB_LOOK, NOUN_SIGN)) + _vm->_dialogs->show(40228); + else if (_action.isAction(VERB_TAKE, NOUN_SIGN)) + _vm->_dialogs->show(40229); + else if (_action.isAction(VERB_LOOK, NOUN_BAR_STOOL)) + _vm->_dialogs->show(40230); + else if (_action.isAction(VERB_TAKE, NOUN_BAR_STOOL)) + _vm->_dialogs->show(40231); + else if (_action.isAction(VERB_LOOK, NOUN_CACTUS)) + _vm->_dialogs->show(40232); + else if (_action.isAction(VERB_TAKE, NOUN_CACTUS)) + _vm->_dialogs->show(40233); + else if (_action.isAction(VERB_LOOK, NOUN_DISCO_BALL)) + _vm->_dialogs->show(40234); + else if (_action.isAction(VERB_LOOK, NOUN_UPPER_DANCE_FLOOR)) + _vm->_dialogs->show(40235); + else if (_action.isAction(VERB_LOOK, NOUN_TREE)) + _vm->_dialogs->show(40236); + else if (_action.isAction(VERB_LOOK, NOUN_PLANT)) + _vm->_dialogs->show(40237); + else if (_action.isAction(VERB_TAKE, NOUN_PLANT)) + _vm->_dialogs->show(40238); + else if (_action.isAction(VERB_LOOK, NOUN_REPAIR_LIST) && _game._objects.isInRoom(OBJ_REPAIR_LIST)) + _vm->_dialogs->show(40239); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene405::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene405::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*ROXCL_8"); + + if (_scene->_priorSceneId == 401) { + _game._player._playerPos = Common::Point(23, 123); + _game._player._facing = FACING_EAST; + } else if (_scene->_priorSceneId == 406) { + _game._player._playerPos = Common::Point(300, 128); + _game._player._facing = FACING_WEST; + } else if (_scene->_priorSceneId == 408) { + _game._player._playerPos = Common::Point(154, 109); + _game._player._facing = FACING_SOUTH; + } else if (_scene->_priorSceneId == 413) { + _game._player._playerPos = Common::Point(284, 109); + _game._player._facing = FACING_SOUTH; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(23, 123); + _game._player._facing = FACING_EAST; + } + + if (_globals[kArmoryDoorOpen]) + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + else + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + + if (_scene->_roomChanged) { + _globals[kArmoryDoorOpen] = false; + _game._objects.addToInventory(OBJ_SECURITY_CARD); + } + + _game.loadQuoteSet(0x24F, 0); + sceneEntrySound(); +} + +void Scene405::step() { + if (_game._trigger == 80) { + _scene->_sequences.addTimer(20, 81); + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + } + + if (_game._trigger == 81) { + _game._player._stepEnabled = true; + _vm->_dialogs->show(40525); + } + + if (_game._trigger == 70) { + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount ; + _game._player._visible = true; + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + _vm->_sound->command(19); + } + + if (_game._trigger == 71) { + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _globals[kArmoryDoorOpen] = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _game._player._stepEnabled = true; + } + + if (_game._trigger == 75) { + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount ; + _game._player._visible = true; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _globals[kArmoryDoorOpen] = true; + _game._player._stepEnabled = true; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle (_globals._spriteIndexes[2], + false, 1); + _vm->_sound->command(19); + } +} + +void Scene405::preActions() { + if (_action.isAction(VERB_TAKE)) + _game._player._needToWalk = false; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST)) + _game._player._walkOffScreenSceneId = 401; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST)) + _game._player._walkOffScreenSceneId = 406; + + if (_action.isAction(VERB_CLOSE, NOUN_WIDE_DOOR) && _globals[kArmoryDoorOpen]) + _game._player.walk(Common::Point(212, 113), FACING_NORTH); +} + +void Scene405::actions() { + if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOOR)) + _scene->_nextSceneId = 413; + else if (_action.isAction(VERB_WALK_THROUGH, NOUN_WIDE_DOOR) && _globals[kArmoryDoorOpen]) + _scene->_nextSceneId = 408; + else if (_action.isAction(VERB_WALK_THROUGH, NOUN_WIDE_DOOR) && !_globals[kArmoryDoorOpen]) + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 60, _game.getQuote(0x24F)); + else if (_action.isAction(VERB_PUT, NOUN_SECURITY_CARD, NOUN_CARD_SLOT) && !_globals[kArmoryDoorOpen]) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 75); + Common::Point msgPos = Common::Point(_game._player._playerPos.x, _game._player._playerPos.y + 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[3], msgPos); + _scene->_sequences.setScale(_globals._sequenceIndexes[3], 87); + } else if ((_action.isAction(VERB_PUT, NOUN_SECURITY_CARD, NOUN_CARD_SLOT) || _action.isAction(VERB_CLOSE, NOUN_WIDE_DOOR)) && _globals[kArmoryDoorOpen]) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 70); + _scene->_sequences.setPosition(_globals._sequenceIndexes[3], _game._player._playerPos); + _scene->_sequences.setScale(_globals._sequenceIndexes[3], 87); + } else if (_action.isAction(VERB_PUT, NOUN_CARD_SLOT)) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 80); + _scene->_sequences.setPosition(_globals._sequenceIndexes[3], _game._player._playerPos); + _scene->_sequences.setScale(_globals._sequenceIndexes[3], 87); + } else if (_action.isAction(VERB_LOOK, NOUN_CANNON_BALLS)) + _vm->_dialogs->show(40510); + else if (_action.isAction(VERB_TAKE, NOUN_CANNON_BALLS)) + _vm->_dialogs->show(40511); + else if (_action.isAction(VERB_LOOK, NOUN_WATER_FOUNTAIN)) + _vm->_dialogs->show(40512); + else if (_action.isAction(VERB_LOOK, NOUN_BACKBOARD) || _action.isAction(VERB_LOOK, NOUN_HOOP)) + _vm->_dialogs->show(40513); + else if (_action.isAction(VERB_LOOK, NOUN_LIGHT)) + _vm->_dialogs->show(40514); + else if (_action.isAction(VERB_LOOK, NOUN_CARD_SLOT)) + _vm->_dialogs->show(40515); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST)) + _vm->_dialogs->show(40516); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST)) + _vm->_dialogs->show(40517); + else if (_action.isAction(VERB_LOOK, NOUN_MONITOR)) + _vm->_dialogs->show(40518); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR) || _action._lookFlag) + _vm->_dialogs->show(40519); + else if (_action.isAction(VERB_LOOK, NOUN_WIDE_DOOR)) { + if (_globals[kArmoryDoorOpen]) + _vm->_dialogs->show(40521); + else + _vm->_dialogs->show(40520); + } else if (_action.isAction(VERB_LOOK, NOUN_DOOR)) + _vm->_dialogs->show(40522); + else if (_action.isAction(VERB_LOOK, NOUN_COACH_LAMP)) + _vm->_dialogs->show(40523); + else if (_action.isAction(VERB_LOOK, NOUN_SUPPORT)) + _vm->_dialogs->show(40524); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene406::Scene406(MADSEngine *vm) : Scene4xx(vm) { + _hitStorageDoor = false; +} + +void Scene406::synchronize(Common::Serializer &s) { + Scene4xx::synchronize(s); + + s.syncAsByte(_hitStorageDoor); +} + +void Scene406::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene406::enter() { + _game._player._visible = true; + if (_scene->_priorSceneId == 405) { + _game._player._playerPos = Common::Point(15, 129); + _game._player._facing = FACING_EAST; + } else if (_scene->_priorSceneId == 407) { + _game._player._playerPos = Common::Point(270, 127); + _game._player._facing = FACING_WEST; + } else if (_scene->_priorSceneId == 410) { + _game._player._playerPos = Common::Point(30, 108); + _game._player._facing = FACING_SOUTH; + } else if (_scene->_priorSceneId == 411) { + _game._player._playerPos = Common::Point(153, 108); + _game._player._facing = FACING_SOUTH; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(15, 129); + _game._player._facing = FACING_EAST; + } + + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*ROXCL_8"); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 1)); + + if (_scene->_roomChanged) { + _globals[kStorageDoorOpen] = false; + _game._objects.addToInventory(OBJ_SECURITY_CARD); + } + + if (!_globals[kStorageDoorOpen]) + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + + if (_scene->_priorSceneId != 411) + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + else { + _game._player._stepEnabled = false; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 3, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 90); + _vm->_sound->command(19); + } + + _game.loadQuoteSet(0x24F, 0); + _hitStorageDoor = false; + sceneEntrySound(); +} + +void Scene406::step() { + if (_game._trigger == 90) { + _game._player._stepEnabled = true; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + } + + if (_game._trigger == 80) + _scene->_nextSceneId = 411; + + if (_game._trigger == 100) { + _vm->_dialogs->show(40622); + _hitStorageDoor = true; + } + + if (_game._trigger == 110) { + _scene->_sequences.addTimer(20, 111); + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + } + + if (_game._trigger == 111) { + _game._player._stepEnabled = true; + _vm->_dialogs->show(40613); + } + + if (_game._trigger == 70) { + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 4, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + _vm->_sound->command(19); + } + + if (_game._trigger == 71) { + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _globals[kStorageDoorOpen] = false; + _game._player._stepEnabled = true; + } + + if (_game._trigger == 75) { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 4, 1, 0, 0); + _globals[kStorageDoorOpen] = true; + _game._player._stepEnabled = true; + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + _vm->_sound->command(19); + } +} + +void Scene406::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST)) + _game._player._walkOffScreenSceneId = 405; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST)) + _game._player._walkOffScreenSceneId = 407; + + if (_action.isAction(VERB_TAKE)) + _game._player._needToWalk = false; + + if (_action.isAction(VERB_LOOK, NOUN_SIGN) || _action.isAction(VERB_LOOK, NOUN_TRASH)) + _game._player._needToWalk = true; +} + +void Scene406::actions() { + if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOOR) && (_game._player._targetPos.x> 100)) { + _game._player._stepEnabled = false; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 3, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 80); + _vm->_sound->command(19); + } else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOOR) && _globals[kStorageDoorOpen] && (_game._player._targetPos.x < 100)) + _scene->_nextSceneId = 410; + else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOOR) && !_globals[kStorageDoorOpen] && (_game._player._targetPos.x < 100)) { + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 60, _game.getQuote(0x24F)); + if (!_hitStorageDoor) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(80, 100); + } + } else if (_action.isAction(VERB_PUT, NOUN_SECURITY_CARD, NOUN_CARD_SLOT) && !_globals[kStorageDoorOpen]) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 75); + Common::Point msgPos = Common::Point(_game._player._playerPos.x, _game._player._playerPos.y + 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], msgPos); + _scene->_sequences.setScale(_globals._sequenceIndexes[2], 87); + } else if (_action.isAction(VERB_PUT, NOUN_SECURITY_CARD, NOUN_CARD_SLOT) && _globals[kStorageDoorOpen]) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 70); + Common::Point msgPos = Common::Point(_game._player._playerPos.x, _game._player._playerPos.y + 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], msgPos); + _scene->_sequences.setScale(_globals._sequenceIndexes[2], 87); + } else if (_action.isAction(VERB_PUT, NOUN_CARD_SLOT)) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 110); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], _game._player._playerPos); + _scene->_sequences.setScale(_globals._sequenceIndexes[2], 87); + } else if (_action.isAction(VERB_LOOK, NOUN_TRASH)) + _vm->_dialogs->show(40610); + else if (_action.isAction(VERB_TAKE, NOUN_TRASH)) + _vm->_dialogs->show(40611); + else if (_action.isAction(VERB_LOOK, NOUN_CARD_SLOT)) + _vm->_dialogs->show(40612); + else if (_action.isAction(VERB_LOOK, NOUN_FIRE_EXTINGUISHER)) + _vm->_dialogs->show(40614); + else if (_action.isAction(VERB_TAKE, NOUN_FIRE_EXTINGUISHER)) + _vm->_dialogs->show(40615); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST)) + _vm->_dialogs->show(40616); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST)) + _vm->_dialogs->show(40617); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR) || _action._lookFlag) + _vm->_dialogs->show(40618); + else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(40619); + else if (_action.isAction(VERB_LOOK, NOUN_DOOR)) { + if (_globals[kStorageDoorOpen]) + _vm->_dialogs->show(40621); + else + _vm->_dialogs->show(40620); + } else if (_action.isAction(VERB_LOOK, NOUN_MONITOR)) + _vm->_dialogs->show(40623); + else if (_action.isAction(VERB_LOOK, NOUN_SIGNPOST)) + _vm->_dialogs->show(40624); + else if (_action.isAction(VERB_TAKE, NOUN_SIGNPOST)) + _vm->_dialogs->show(40625); + else if (_action.isAction(VERB_LOOK, NOUN_BOULDER)) + _vm->_dialogs->show(40626); + else if (_action.isAction(VERB_TAKE, NOUN_BOULDER)) + _vm->_dialogs->show(40627); + else if (_action.isAction(VERB_LOOK, NOUN_SIGN)) + _vm->_dialogs->show(40628); + else if (_action.isAction(VERB_TAKE, NOUN_SIGN)) + _vm->_dialogs->show(40629); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene407::Scene407(MADSEngine *vm) : Scene4xx(vm), _destPos(0, 0) { + _fromNorth = false; +} + +void Scene407::synchronize(Common::Serializer &s) { + Scene4xx::synchronize(s); + + s.syncAsByte(_fromNorth); + s.syncAsSint16LE(_destPos.x); + s.syncAsSint16LE(_destPos.y); +} + +void Scene407::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene407::enter() { + if (_scene->_priorSceneId != -2) + _fromNorth = false; + + if (_scene->_priorSceneId == 318) { + _game._player._playerPos = Common::Point(172, 92); + _game._player._facing = FACING_SOUTH; + _fromNorth = true; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(172, 132); + _game._player._facing = FACING_NORTH; + } + + _game.loadQuoteSet(0x250, 0); + sceneEntrySound(); +} + +void Scene407::step() { + if (_game._trigger == 70) { + _scene->_nextSceneId = 318; + _scene->_reloadSceneFlag = true; + } + + if (_game._trigger == 80) { + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._stepEnabled = true; + _game._player._visible = true; + _fromNorth = false; + _game._player.walk(Common::Point(173, 104), FACING_SOUTH); + } +} + +void Scene407::preActions() { + if (_action.isAction(VERB_TAKE)) + _game._player._needToWalk = false; + + if (_action.isAction(VERB_LOOK, NOUN_DOOR)) + _game._player._needToWalk = true; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_NORTH)) { + _game._player.walk(Common::Point(172, 91), FACING_NORTH); + _fromNorth = false; + } + + if (_game._player._needToWalk && _fromNorth) { + if (_globals[kSexOfRex] == REX_MALE) + _destPos = Common::Point(171, 95); + else + _destPos = Common::Point(173, 96); + + _game._player.walk(_destPos, FACING_SOUTH); + } +} + +void Scene407::actions() { + if ((_game._player._playerPos == _destPos) && _fromNorth) { + if (_globals[kSexOfRex] == REX_MALE) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _game._player._stepEnabled = false; + _game._player._visible = false; + _vm->_sound->command(21); + _scene->loadAnimation(formAnimName('s', 1), 70); + _globals[kHasBeenScanned] = true; + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 60, _game.getQuote(60)); + _vm->_sound->command(22); + } + + if (_globals[kSexOfRex] == REX_FEMALE) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _game._player._stepEnabled = false; + _game._player._visible = false; + _vm->_sound->command(21); + _scene->loadAnimation(formAnimName('s', 2), 80); + _vm->_sound->command(23); + _globals[kHasBeenScanned] = true; + } + } + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH) && !_fromNorth) + _scene->_nextSceneId = 406; + else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_NORTH)) + _scene->_nextSceneId = 318; + else if (_action.isAction(VERB_LOOK, NOUN_SCANNER)) { + if (_globals[kHasBeenScanned]) + _vm->_dialogs->show(40711); + else + _vm->_dialogs->show(40710); + } else if (_action.isAction(VERB_LOOK, NOUN_DOOR)) + _vm->_dialogs->show(40712); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH)) + _vm->_dialogs->show(40713); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_NORTH)) + _vm->_dialogs->show(40714); + else if (_action._lookFlag) + _vm->_dialogs->show(40715); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene408::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_TARGET_MODULE); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene408::enter() { + _game._player._playerPos = Common::Point(137, 150); + _game._player._facing = FACING_NORTH; + + _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*ROXRC_7"); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('m', -1)); + + if (_game._objects.isInRoom(OBJ_TARGET_MODULE)) { + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3); + int idx = _scene->_dynamicHotspots.add(NOUN_TARGET_MODULE, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(283, 128), FACING_NORTHEAST); + } + sceneEntrySound(); +} + +void Scene408::preActions() { + if ((_action.isAction(VERB_TAKE) && !_action.isObject(NOUN_TARGET_MODULE)) || _action.isAction(VERB_PULL, NOUN_PIN) || _action.isAction(VERB_OPEN, NOUN_CARTON)) + _game._player._needToWalk = false; + + if ((_action.isAction(VERB_LOOK, NOUN_TARGET_MODULE) && _game._objects.isInRoom(OBJ_TARGET_MODULE)) || _action.isAction(VERB_LOOK, NOUN_CHEST)) + _game._player._needToWalk = true; +} + +void Scene408::actions() { + if (_action.isAction(VERB_WALK_INTO, NOUN_CORRIDOR_TO_SOUTH)) { + _scene->_nextSceneId = 405; + _vm->_sound->command(58); + } else if (_action.isAction(VERB_TAKE, NOUN_TARGET_MODULE) && (_game._objects.isInRoom(OBJ_TARGET_MODULE) || _game._trigger)) { + switch (_game._trigger) { + case 0: + _vm->_sound->command(57); + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], true, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[1]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_SPRITE, 2, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _game._objects.addToInventory(OBJ_TARGET_MODULE); + _vm->_dialogs->showItem(OBJ_TARGET_MODULE, 40847); + break; + + case 2: + _game._player._priorTimer = _game._player._ticksAmount + _scene->_frameStartTime; + _game._player._visible = true; + _scene->_sequences.addTimer(20, 3); + break; + + case 3: + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_LOOK, NOUN_ARMORED_VEHICLE)) + _vm->_dialogs->show(40810); + else if (_action.isAction(VERB_TAKE, NOUN_ARMORED_VEHICLE) || _action.isAction(VERB_TAKE, NOUN_ANVIL) || _action.isAction(VERB_TAKE, NOUN_TWO_TON_WEIGHT)) + _vm->_dialogs->show(40811); + else if (_action.isAction(VERB_LOOK, NOUN_MISSILE)) + _vm->_dialogs->show(40812); + else if (_action.isAction(VERB_TAKE, NOUN_MISSILE)) + _vm->_dialogs->show(40813); + else if (_action.isAction(VERB_LOOK, NOUN_GRENADE)) + _vm->_dialogs->show(40814); + else if (_action.isAction(VERB_TAKE, NOUN_GRENADE)) + _vm->_dialogs->show(40815); + else if (_action.isAction(VERB_TAKE, NOUN_PIN) || _action.isAction(VERB_PULL, NOUN_PIN)) + _vm->_dialogs->show(40816); + else if (_action.isAction(VERB_LOOK, NOUN_BLIMP)) + _vm->_dialogs->show(40817); + else if (_action.isAction(VERB_TAKE, NOUN_BLIMP)) + _vm->_dialogs->show(40818); + else if (_action.isAction(VERB_LOOK, NOUN_AMMUNITION)) + _vm->_dialogs->show(40819); + else if (_action.isAction(VERB_TAKE, NOUN_AMMUNITION)) + _vm->_dialogs->show(40820); + else if (_action.isAction(VERB_LOOK, NOUN_CATAPULT)) + _vm->_dialogs->show(40821); + else if (_action.isAction(VERB_TAKE, NOUN_CATAPULT)) + _vm->_dialogs->show(40822); + else if (_action.isAction(VERB_LOOK, NOUN_CHEST)) { + if (_game._objects.isInRoom(OBJ_TARGET_MODULE)) + _vm->_dialogs->show(40823); + else + _vm->_dialogs->show(40824); + } else if (_action.isAction(VERB_TAKE, NOUN_CHEST)) + _vm->_dialogs->show(40825); + else if (_action.isAction(VERB_LOOK, NOUN_SUIT_OF_ARMOR)) + _vm->_dialogs->show(40826); + else if (_action.isAction(VERB_TAKE, NOUN_SUIT_OF_ARMOR)) + _vm->_dialogs->show(40827); + else if (_action.isAction(VERB_LOOK, NOUN_ESCAPE_HATCH)) + _vm->_dialogs->show(40828); + else if (_action.isAction(VERB_OPEN, NOUN_ESCAPE_HATCH) || _action.isAction(VERB_PULL, NOUN_ESCAPE_HATCH)) + _vm->_dialogs->show(40829); + else if (_action.isAction(VERB_LOOK, NOUN_BARRELS)) + _vm->_dialogs->show(40830); + else if (_action.isAction(VERB_TAKE, NOUN_BARRELS)) + _vm->_dialogs->show(40831); + else if (_action.isAction(VERB_LOOK, NOUN_INFLATABLE_RAFT)) + _vm->_dialogs->show(40832); + else if (_action.isAction(VERB_TAKE, NOUN_INFLATABLE_RAFT)) + _vm->_dialogs->show(40833); + else if (_action.isAction(VERB_LOOK, NOUN_TOMATO)) + _vm->_dialogs->show(40834); + else if (_action.isAction(VERB_TAKE, NOUN_TOMATO)) + _vm->_dialogs->show(40835); + else if (_action.isAction(VERB_LOOK, NOUN_ANVIL)) + _vm->_dialogs->show(40836); + else if (_action.isAction(VERB_LOOK, NOUN_TWO_TON_WEIGHT)) + _vm->_dialogs->show(40837); + else if (_action.isAction(VERB_LOOK, NOUN_POWDER_CONTAINER)) + _vm->_dialogs->show(40838); + else if (_action.isAction(VERB_LOOK, NOUN_POWDER_PUFF)) + _vm->_dialogs->show(40839); + else if (_action.isAction(VERB_TAKE, NOUN_POWDER_PUFF)) + _vm->_dialogs->show(40840); + else if (_action.isAction(VERB_LOOK, NOUN_CARTON)) + _vm->_dialogs->show(40841); + else if (_action.isAction(VERB_TAKE, NOUN_CARTON)) + _vm->_dialogs->show(40842); + else if (_action.isAction(VERB_OPEN, NOUN_CARTON)) + _vm->_dialogs->show(40843); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH)) + _vm->_dialogs->show(40844); + else if (_action._lookFlag) + _vm->_dialogs->show(40845); + else if (_action.isAction(VERB_LOOK, NOUN_TARGET_MODULE) && _game._objects.isInRoom(OBJ_TARGET_MODULE)) + _vm->_dialogs->show(40846); + else if (_action.isAction(VERB_LOOK, NOUN_LOADING_RAMP)) + _vm->_dialogs->show(40848); + else if (_action.isAction(VERB_OPEN, NOUN_CHEST)) + _vm->_dialogs->show(40849); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene409::setup() { + _game._player._spritesPrefix = ""; + + // The original is calling Scene4xx::setAAName() + _game._aaName = Resources::formatAAName(4); +} + +void Scene409::enter() { + _handSpriteId = _scene->_sprites.addSprites("*ROXHAND"); + teleporterEnter(); + + // The original is calling Scene4xx::sceneEntrySound() + if (!_vm->_musicFlag) + _vm->_sound->command(2); + else + _vm->_sound->command(10); +} + +void Scene409::step() { + teleporterStep(); +} + +void Scene409::actions() { + if (teleporterActions()) { + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_VIEWPORT)) + _vm->_dialogs->show(40910); + else if (_action.isAction(VERB_PEER_THROUGH, NOUN_VIEWPORT)) + _vm->_dialogs->show(40910); + else if (_action.isAction(VERB_LOOK, NOUN_KEYPAD)) + _vm->_dialogs->show(40911); + else if (_action.isAction(VERB_INSPECT, NOUN_KEYPAD)) + _vm->_dialogs->show(40911); + else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY)) + _vm->_dialogs->show(40912); + else if (_action.isAction(VERB_LOOK, NOUN_1_KEY) || _action.isAction(VERB_LOOK, NOUN_2_KEY) + || _action.isAction(VERB_LOOK, NOUN_3_KEY) || _action.isAction(VERB_LOOK, NOUN_4_KEY) + || _action.isAction(VERB_LOOK, NOUN_5_KEY) || _action.isAction(VERB_LOOK, NOUN_6_KEY) + || _action.isAction(VERB_LOOK, NOUN_7_KEY) || _action.isAction(VERB_LOOK, NOUN_8_KEY) + || _action.isAction(VERB_LOOK, NOUN_9_KEY) || _action.isAction(VERB_LOOK, NOUN_0_KEY) + || _action.isAction(VERB_LOOK, NOUN_SMILE_KEY) || _action.isAction(VERB_LOOK, NOUN_FROWN_KEY)) + _vm->_dialogs->show(40913); + else if (_action.isAction(VERB_LOOK, NOUN_DEVICE)) + _vm->_dialogs->show(40914); + else if (_action._lookFlag) + _vm->_dialogs->show(40914); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene410::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene410::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('y', -1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*ROXRC_7"); + + if (_game._objects.isInRoom(OBJ_CHARGE_CASES)) + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + else + _scene->_hotspots.activate(NOUN_CHARGE_CASES, false); + + if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(155, 150); + _game._player._facing = FACING_NORTH; + } + + sceneEntrySound(); + + _scene->loadAnimation(Resources::formatName(410, 'r', -1, EXT_AA, "")); + _scene->_activeAnimation->_resetFlag = true; +} + +void Scene410::step() { + if (_scene->_activeAnimation->getCurrentFrame() == 1) { + if (_vm->getRandomNumber(1, 30) == 1) + _scene->_activeAnimation->setCurrentFrame(2); + else + _scene->_activeAnimation->setCurrentFrame(0); + } + + if (_scene->_activeAnimation->getCurrentFrame() == 9) { + if (_vm->getRandomNumber(1, 30) == 1) + _scene->_activeAnimation->setCurrentFrame(10); + else + _scene->_activeAnimation->setCurrentFrame(8); + } + + if (_scene->_activeAnimation->getCurrentFrame() == 5) { + if (_vm->getRandomNumber(1, 30) == 1) + _scene->_activeAnimation->setCurrentFrame(6); + else + _scene->_activeAnimation->setCurrentFrame(4); + } + + if (_scene->_activeAnimation->getCurrentFrame() == 3) { + if (_vm->getRandomNumber(1, 2) == 1) + _scene->_activeAnimation->setCurrentFrame(4); + else // == 2 + _scene->_activeAnimation->setCurrentFrame(8); + } +} + +void Scene410::preActions() { + if (_action.isAction(VERB_TAKE) && !_action.isObject(NOUN_CHARGE_CASES)) + _game._player._needToWalk = false; + + if (_action.isAction(VERB_LOOK, NOUN_CHARGE_CASES) && _game._objects.isInRoom(OBJ_CHARGE_CASES)) + _game._player._needToWalk = true; + + if (_action.isAction(VERB_OPEN, NOUN_SACKS) || _action.isAction(VERB_OPEN, NOUN_SACK)) + _game._player._needToWalk = false; + + if (_action.isAction(VERB_LOOK, NOUN_CAN)) + _game._player._needToWalk = true; +} + +void Scene410::actions() { + if (_action.isAction(VERB_WALK_INTO, NOUN_CORRIDOR_TO_SOUTH)) + _scene->_nextSceneId = 406; + else if (_action.isAction(VERB_TAKE, NOUN_CHARGE_CASES) && (_game._objects.isInRoom(OBJ_CHARGE_CASES) || _game._trigger)) { + switch (_game._trigger) { + case 0: + _vm->_sound->command(57); + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 3, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_hotspots.activate(NOUN_CHARGE_CASES, false); + _game._objects.addToInventory(OBJ_CHARGE_CASES); + _vm->_dialogs->showItem(OBJ_CHARGE_CASES, 41032); + break; + + case 2: + _game._player._priorTimer = _game._player._ticksAmount + _scene->_frameStartTime; + _game._player._visible = true; + _scene->_sequences.addTimer(20, 3); + break; + + case 3: + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_LOOK, NOUN_BARREL)) + _vm->_dialogs->show(41010); + else if (_action.isAction(VERB_TAKE, NOUN_BARREL)) + _vm->_dialogs->show(41011); + else if (_action.isAction(VERB_OPEN, NOUN_BARREL)) + _vm->_dialogs->show(41012); + else if (_action.isAction(VERB_LOOK, NOUN_RUG)) + _vm->_dialogs->show(41013); + else if (_action.isAction(VERB_TAKE, NOUN_RUG)) + _vm->_dialogs->show(41014); + else if (_action.isAction(VERB_LOOK, NOUN_CARTON) || _action.isAction(VERB_OPEN, NOUN_CARTON)) { + if (_game._objects.isInRoom(OBJ_CHARGE_CASES)) + _vm->_dialogs->show(41015); + else + _vm->_dialogs->show(41016); + } else if (_action.isAction(VERB_LOOK, NOUN_FLOUR)) + _vm->_dialogs->show(41017); + else if (_action.isAction(VERB_TAKE, NOUN_FLOUR)) + _vm->_dialogs->show(41018); + else if (_action.isAction(VERB_LOOK, NOUN_SACKS)) + _vm->_dialogs->show(41019); + else if (_action.isAction(VERB_LOOK, NOUN_SACK)) + _vm->_dialogs->show(41019); + else if (_action.isAction(VERB_OPEN, NOUN_SACKS)) + _vm->_dialogs->show(41020); + else if (_action.isAction(VERB_OPEN, NOUN_SACK)) + _vm->_dialogs->show(41020); + else if (_action.isAction(VERB_LOOK, NOUN_BUCKET_OF_TAR)) + _vm->_dialogs->show(41021); + else if (_action.isAction(VERB_TAKE, NOUN_BUCKET_OF_TAR)) + _vm->_dialogs->show(41022); + else if (_action.isAction(VERB_LOOK, NOUN_CAN)) + _vm->_dialogs->show(41023); + else if (_action.isAction(VERB_TAKE, NOUN_CAN)) + _vm->_dialogs->show(41024); + else if (_action.isAction(VERB_LOOK, NOUN_CHARGE_CASES) && _game._objects.isInRoom(OBJ_CHARGE_CASES)) + _vm->_dialogs->show(41025); + else if (_action.isAction(VERB_LOOK, NOUN_FENCE)) + _vm->_dialogs->show(41027); + else if (_action.isAction(VERB_LOOK, NOUN_SHELVES)) + _vm->_dialogs->show(41028); + else if (_action.isAction(VERB_LOOK, NOUN_RAT)) + _vm->_dialogs->show(41029); + else if (_action.isAction(VERB_TAKE, NOUN_RAT)) + _vm->_dialogs->show(41030); + else if (_action.isAction(VERB_THROW, NOUN_RAT)) + _vm->_dialogs->show(41031); + else if (_action._lookFlag) + _vm->_dialogs->show(41033); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene411::Scene411(MADSEngine *vm) : Scene4xx(vm) { + _curAnimationFrame = -1; + _newIngredient = -1; + _newQuantity = -1; + _resetFrame = -1; + _badThreshold = -1; + + _killRox = false; + _makeMushroomCloud = false; +} + +void Scene411::synchronize(Common::Serializer &s) { + Scene4xx::synchronize(s); + + s.syncAsSint32LE(_curAnimationFrame); + s.syncAsSint32LE(_newIngredient); + s.syncAsSint32LE(_newQuantity); + s.syncAsSint32LE(_resetFrame); + s.syncAsSint32LE(_badThreshold); + + s.syncAsByte(_killRox); + s.syncAsByte(_makeMushroomCloud); +} + +bool Scene411::addIngredient() { + bool retVal = false; + + switch (_newIngredient) { + case OBJ_LECITHIN: + if (_globals[kIngredientList + _globals[kNextIngredient]] == 1) + retVal = true; + + _badThreshold = 1; + break; + + case OBJ_ALIEN_LIQUOR: + if (_globals[kIngredientList + _globals[kNextIngredient]] == 0) + retVal = true; + + _badThreshold = 0; + break; + + case OBJ_FORMALDEHYDE: + if (_globals[kIngredientList + _globals[kNextIngredient]] == 3) + retVal = true; + + _badThreshold = 3; + break; + + case OBJ_PETROX: + if (_globals[kIngredientList + _globals[kNextIngredient]] == 2) + retVal = true; + + _badThreshold = 2; + break; + + default: + break; + } + + if (!retVal && (_globals[kNextIngredient] == 0)) + _globals[kBadFirstIngredient] = _badThreshold; + + if (_globals[kNextIngredient] == 0) + retVal = true; + + return(retVal); +} + +bool Scene411::addQuantity() { + bool retVal = false; + + if (_globals[kIngredientQuantity + _globals[kNextIngredient]] == _newQuantity) + retVal = true; + + if (!retVal && (_globals[kNextIngredient] == 0)) + _globals[kBadFirstIngredient] = _badThreshold; + + if (_globals[kNextIngredient] == 0) + retVal = true; + + return(retVal); +} + +int Scene411::computeQuoteAndQuantity() { + int quoteId; + int quantity; + + switch (_action._activeAction._verbId) { + case 0x252: + quoteId = 0x26F; + quantity = 0; + break; + + case 0x253: + quoteId = 0x271; + quantity = 0; + break; + + case 0x254: + quoteId = 0x270; + quantity = 0; + break; + + case 0x255: + quoteId = 0x272; + quantity = 0; + break; + + case 0x256: + quoteId = 0x267; + quantity = 2; + break; + + case 0x257: + quoteId = 0x269; + quantity = 2; + break; + + case 0x258: + quoteId = 0x268; + quantity = 2; + break; + + case 0x259: + quoteId = 0x26A; + quantity = 2; + break; + + case 0x25A: + quoteId = 0x26B; + quantity = 3; + break; + + case 0x25B: + quoteId = 0x26D; + quantity = 3; + break; + + case 0x25C: + quoteId = 0x26C; + quantity = 3; + break; + + case 0x25D: + quoteId = 0x26E; + quantity = 3; + break; + + case 0x25E: + quoteId = 0x263; + quantity = 1; + break; + + case 0x25F: + quoteId = 0x265; + quantity = 1; + break; + + case 0x260: + quoteId = 0x264; + quantity = 1; + break; + + case 0x261: + quoteId = 0x266; + quantity = 1; + break; + + default: + quoteId = 0; + quantity = 0; + break; + } + + _scene->_kernelMessages.add(Common::Point(202, 82), 0x1110, 32, 0, 120, _game.getQuote(quoteId)); + return quantity; +} + +void Scene411::handleKettleAction() { + switch (_globals[kNextIngredient]) { + case 1: + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], + false, 15, 0, 0, 0); + break; + + case 2: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], + false, 6, 0, 0, 0); + break; + + case 3: + _makeMushroomCloud = true; + break; + + default: + break; + } +} + +void Scene411::handleDialog() { + if ((_action._activeAction._verbId != 0x262) && (_game._trigger == 0)) { + if (_game._objects.isInInventory(_newIngredient)) { + switch (_newIngredient) { + case OBJ_FORMALDEHYDE: + _resetFrame = 17; + break; + + case OBJ_PETROX: + _resetFrame = 55; + break; + + case OBJ_LECITHIN: + _resetFrame = 36; + break; + + default: + _resetFrame = 112; + break; + } + + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->_activeAnimation->setCurrentFrame(_resetFrame); + } + _scene->_kernelMessages.reset(); + _newQuantity = computeQuoteAndQuantity (); + + if ((_globals[kNextIngredient] == 1) && (_globals[kBadFirstIngredient] > -1)) + _killRox = true; + else if (addIngredient() && addQuantity()) { + handleKettleAction(); + _globals[kNextIngredient]++; + } else + _killRox = true; + + _scene->_userInterface.setup(kInputBuildingSentences); + } else if (_action._activeAction._verbId == 0x262) + _scene->_userInterface.setup(kInputBuildingSentences); +} + +void Scene411::giveToRex(int object) { + switch (object) { + case 0: + _game._objects.addToInventory(OBJ_ALIEN_LIQUOR); + break; + + case 1: + _game._objects.addToInventory(OBJ_LECITHIN); + break; + + case 2: + _game._objects.addToInventory(OBJ_PETROX); + break; + + case 3: + _game._objects.addToInventory(OBJ_FORMALDEHYDE); + break; + + default: + break; + } +} + +void Scene411::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_ALIEN_LIQUOR); + _scene->addActiveVocab(NOUN_FORMALDEHYDE); + _scene->addActiveVocab(NOUN_PETROX); + _scene->addActiveVocab(NOUN_LECITHIN); +} + +void Scene411::enter() { + if (_scene->_priorSceneId == 411) { + if ((_globals[kNextIngredient] == 1) && (_globals[kBadFirstIngredient] > -1)) + giveToRex(_globals[kBadFirstIngredient]); + else if (_globals[kNextIngredient] > 0) { + for (int i = 0; i < _globals[kNextIngredient]; i ++) + giveToRex(_globals[kIngredientList + i]); + } + _globals[kNextIngredient] = 0; + _globals[kBadFirstIngredient] = -1; + } + + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('c', 0)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('f', 0)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('f', 1)); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('f', 2)); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('c', 1)); + _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('a', 6)); + _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _globals._spriteIndexes[8] = _scene->_sprites.addSprites("*ROXRC_9"); + + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 0, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 50, 0, 0, 0); + + _game.loadQuoteSet(0x252, 0x25E, 0x25A, 0x256, 0x253, 0x25F, 0x25B, 0x257, 0x254, 0x260, 0x25C, 0x258, 0x255, + 0x261, 0x25D, 0x259, 0x262, 0x267, 0x263, 0x26B, 0x26F, 0x268, 0x264, 0x26C, 0x270, 0x26A, 0x266, 0x26E, + 0x272, 0x269, 0x265, 0x26D, 0x271, 0); + + _dialog1.setup(0x5B, 0x252, 0x25E, 0x25A, 0x256, 0x262, -1); + _dialog2.setup(0x5C, 0x253, 0x25F, 0x25B, 0x257, 0x262, -1); + _dialog3.setup(0x5D, 0x254, 0x260, 0x25C, 0x258, 0x262, -1); + _dialog4.setup(0x5E, 0x255, 0x261, 0x25D, 0x259, 0x262, -1); + + if (_globals[kNextIngredient] >= 4 && _game._objects[OBJ_CHARGE_CASES].getQuality(3)) { + _scene->_hotspots.activate(NOUN_EXPLOSIVES, false); + _scene->_hotspots.activate(NOUN_KETTLE, true); + } else { + _scene->_hotspots.activate(NOUN_KETTLE, false); + _scene->_hotspots.activate(NOUN_EXPLOSIVES, true); + } + + if (_globals[kNextIngredient] >= 4 && _game._objects[OBJ_CHARGE_CASES].getQuality(3)) { + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], true, 6); + } else if (!_game._objects[OBJ_CHARGE_CASES].getQuality(3)) { + switch (_globals[kNextIngredient]) { + case 1: + _vm->_sound->command(53); + break; + + case 2: + _vm->_sound->command(53); + _vm->_sound->command(54); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 15, 0, 0, 0); + break; + + case 3: + _vm->_sound->command(53); + _vm->_sound->command(54); + _vm->_sound->command(55); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 0, 0, 0); + break; + + case 4: + _vm->_sound->command(53); + _vm->_sound->command(54); + _vm->_sound->command(55); + _vm->_sound->command(56); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 0, 0, 0); + break; + + default: + _vm->_sound->command(10); + break; + } + } + + if (_globals[kNextIngredient] >= 4 && _game._objects[OBJ_CHARGE_CASES].getQuality(3)) { + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], true, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + } + + if (_game._objects.isInRoom(OBJ_FORMALDEHYDE)) { + _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 1); + int idx = _scene->_dynamicHotspots.add(NOUN_FORMALDEHYDE, VERB_WALKTO, _globals._sequenceIndexes[7], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(206, 145), FACING_SOUTHEAST); + } + + if (_game._objects.isInRoom(OBJ_PETROX)) { + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_PETROX, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(186, 112), FACING_NORTHEAST); + } + + if (_game._objects.isInRoom(OBJ_LECITHIN)) { + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_LECITHIN, VERB_WALKTO, _globals._sequenceIndexes[6], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(220, 121), FACING_NORTHEAST); + } + + if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(60, 146); + _game._player._facing = FACING_NORTHEAST; + } + + sceneEntrySound(); + + if (_scene->_roomChanged) { + _game._objects.addToInventory(OBJ_ALIEN_LIQUOR); + _game._objects.addToInventory(OBJ_CHARGE_CASES); + _game._objects.addToInventory(OBJ_TAPE_PLAYER); + _game._objects.addToInventory(OBJ_AUDIO_TAPE); + } + + _scene->loadAnimation(formAnimName('a', -1)); + _scene->_activeAnimation->setCurrentFrame(128); + + _makeMushroomCloud = false; + _killRox = false; +} + +void Scene411::step() { + if (_scene->_activeAnimation != nullptr) { + if (_curAnimationFrame != _scene->_activeAnimation->getCurrentFrame()) { + _curAnimationFrame = _scene->_activeAnimation->getCurrentFrame(); + _resetFrame = -1; + + switch (_curAnimationFrame) { + case 16: + _game._player._stepEnabled = true; + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + _resetFrame = 128; + break; + + case 35: + case 54: + case 71: + case 127: + if (_killRox) { + _resetFrame = 72; + } else { + _resetFrame = 0; + _game._objects.removeFromInventory(_newIngredient, NOWHERE); + switch (_globals[kNextIngredient]) { + case 1: + _vm->_sound->command(53); + break; + + case 2: + _vm->_sound->command(54); + break; + + case 3: + _vm->_sound->command(55); + break; + + case 4: + _vm->_sound->command(56); + break; + + default: + break; + } + } + break; + + case 22: + case 41: + case 59: + case 115: + if (_makeMushroomCloud) { + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 5, 1, 0, 0); + _makeMushroomCloud = false; + _scene->_hotspots.activate(NOUN_EXPLOSIVES, false); + _scene->_hotspots.activate(NOUN_KETTLE, true); + } + break; + + case 111: + _resetFrame = 111; + _scene->_reloadSceneFlag = true; + break; + + case 129: + _resetFrame = 128; + break; + + default: + break; + } + + if ((_resetFrame >= 0) && (_resetFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(_resetFrame); + _curAnimationFrame = _resetFrame; + } + } + } + + if (_scene->_activeAnimation->getCurrentFrame() == 86) + _vm->_sound->command(59); +} + +void Scene411::preActions() { + if (_action.isAction(VERB_LOOK, NOUN_PETROX) && (_game._objects.isInRoom(OBJ_PETROX))) + _game._player._needToWalk = true; + + if (_action.isAction(VERB_LOOK, NOUN_LECITHIN) && (_game._objects.isInRoom(OBJ_LECITHIN))) + _game._player._needToWalk = true; + + if (_action.isAction(VERB_LOOK, NOUN_FORMALDEHYDE) && (_game._objects.isInRoom(OBJ_FORMALDEHYDE))) + _game._player._needToWalk = true; + + if (_action.isAction(VERB_LOOK, NOUN_EXPLOSIVES) || _action.isAction(VERB_LOOK, NOUN_KETTLE) || _action.isAction(VERB_LOOK, NOUN_MISHAP) || + _action.isAction(VERB_LOOK, NOUN_ALCOVE) || _action.isAction(VERB_LOOK, NOUN_SINK) || _action.isAction(VERB_PUT, NOUN_SINK) || + _action.isAction(VERB_LOOK, NOUN_EXPERIMENT) || _action.isAction(VERB_LOOK, NOUN_DRAWING_BOARD)) + _game._player._needToWalk = true; + + if (_action.isAction(VERB_PULL, NOUN_KNIFE_SWITCH) || _action.isAction(VERB_PUSH, NOUN_KNIFE_SWITCH)) + _game._player._needToWalk = false; +} + +void Scene411::actions() { + if (_game._screenObjects._inputMode != 1) { + handleDialog(); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_WALK_INTO, NOUN_CORRIDOR_TO_SOUTH)) { + _scene->_nextSceneId = 406; + _vm->_sound->command(10); + _action._inProgress = false; + return; + } + + if ((_globals[kNextIngredient] >= 4) && (_action.isAction(VERB_TAKE, NOUN_EXPLOSIVES) || _action.isAction(VERB_PUT, NOUN_CHARGE_CASES, NOUN_EXPLOSIVES)) + && !_game._objects[OBJ_CHARGE_CASES].getQuality(3) + && _game._objects.isInInventory(OBJ_CHARGE_CASES)) { + switch (_game._trigger) { + case 0: + _vm->_sound->command(10); + _vm->_sound->command(57); + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[10] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[10], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 1, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[10], SEQUENCE_TRIGGER_EXPIRE, 0, 110); + break; + + case 110: { + int idx = _globals._sequenceIndexes[10]; + _globals._sequenceIndexes[10] = _scene->_sequences.startCycle(_globals._spriteIndexes[10], false, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 3); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[10], idx); + _scene->_sequences.addTimer(180, 111); + } + break; + + case 111: + _scene->_hotspots.activate(NOUN_KETTLE, true); + _scene->_hotspots.activate(NOUN_EXPLOSIVES, false); + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], true, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + + _globals._sequenceIndexes[10] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[10], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 1, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[10], SEQUENCE_TRIGGER_EXPIRE, 0, 112); + // No break on purpose + case 112: + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._visible = true; + _game._player._stepEnabled = true; + _game._objects[OBJ_CHARGE_CASES].setQuality(3, 1); + _vm->_dialogs->showItem(OBJ_CHARGE_CASES, 41142); + break; + } + _action._inProgress = false; + return; + } else if (!_game._objects.isInInventory(OBJ_CHARGE_CASES) && _action.isAction(VERB_TAKE, NOUN_EXPLOSIVES)) { + _vm->_dialogs->show(41143); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_PETROX) && (_game._objects.isInRoom(OBJ_PETROX) || _game._trigger)) { + switch (_game._trigger) { + case 0: + _vm->_sound->command(57); + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[8] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[8], false, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[8]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_SPRITE, 2, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _game._objects.addToInventory(OBJ_PETROX); + _vm->_dialogs->showItem(OBJ_PETROX, 41120); + break; + + case 2: + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + _scene->_sequences.addTimer(20, 3); + break; + + case 3: + _game._player._stepEnabled = true; + break; + + default: + break; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_LECITHIN) && (_game._objects.isInRoom(OBJ_LECITHIN) || _game._trigger)) { + switch (_game._trigger) { + case 0: + _vm->_sound->command(57); + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[8] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[8], false, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[8]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_SPRITE, 2, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[6]); + _game._objects.addToInventory(OBJ_LECITHIN); + _vm->_dialogs->showItem(OBJ_LECITHIN, 41124); + break; + + case 2: + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + _scene->_sequences.addTimer(20, 3); + break; + + case 3: + _game._player._stepEnabled = true; + break; + + default: + break; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_FORMALDEHYDE) && _game._objects.isInRoom(OBJ_FORMALDEHYDE) && (_game._trigger == 0)) { + _vm->_sound->command(57); + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[11] = _scene->_sequences.startCycle(_globals._spriteIndexes[11], false, 2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[11], 1); + _scene->_sequences.addTimer(20, 100); + _scene->_sequences.remove(_globals._sequenceIndexes[7]); + _game._objects.addToInventory(OBJ_FORMALDEHYDE); + _action._inProgress = false; + return; + } + + if (_game._trigger == 100) { + _scene->_sequences.remove(_globals._sequenceIndexes[11]); + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._visible = true; + _game._player._stepEnabled = true; + _scene->_sequences.addTimer(20, 10); + } + + if (_game._trigger == 10) + _vm->_dialogs->showItem(OBJ_FORMALDEHYDE, 41124); + + if (_action.isAction(VERB_PUT, NOUN_KETTLE)) { + if (_action.isObject(NOUN_PETROX) || _action.isObject(NOUN_FORMALDEHYDE) || _action.isObject(NOUN_LECITHIN) || _action.isObject(NOUN_ALIEN_LIQUOR)) { + _newIngredient = _game._objects.getIdFromDesc(_action._activeAction._objectNameId); + switch (_newIngredient) { + case OBJ_ALIEN_LIQUOR: + _dialog1.start(); + break; + + case OBJ_FORMALDEHYDE: + _dialog3.start(); + break; + + case OBJ_PETROX: + _dialog4.start(); + break; + + case OBJ_LECITHIN: + _dialog2.start(); + break; + + default: + break; + } + } + } + + + if (_action.isAction(VERB_LOOK, NOUN_MONITOR)) + _vm->_dialogs->show(41110); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_PURIFIER)) + _vm->_dialogs->show(41111); + else if (_action.isAction(VERB_LOOK, NOUN_LAB_EQUIPMENT)) + _vm->_dialogs->show(41112); + else if (_action.isAction(VERB_LOOK, NOUN_KNIFE_SWITCH)) + _vm->_dialogs->show(41113); + else if (_action.isAction(VERB_PUSH, NOUN_KNIFE_SWITCH) || _action.isAction(VERB_PULL, NOUN_KNIFE_SWITCH)) + _vm->_dialogs->show(41114); + else if (_action.isAction(VERB_LOOK, NOUN_TOXIC_WASTE)) + _vm->_dialogs->show(41115); + else if (_action.isAction(VERB_TAKE, NOUN_TOXIC_WASTE)) + _vm->_dialogs->show(41116); + else if (_action.isAction(VERB_LOOK, NOUN_DRAWING_BOARD)) + _vm->_dialogs->show(41117); + else if (_action.isAction(VERB_LOOK, NOUN_EXPERIMENT)) + _vm->_dialogs->show(41118); + else if (_action.isAction(VERB_LOOK, NOUN_PETROX) && _game._objects.isInRoom(OBJ_PETROX)) + _vm->_dialogs->show(41119); + else if (_action.isAction(VERB_LOOK, NOUN_ALCOVE)) + _vm->_dialogs->show(41121); + else if ((_action.isAction(VERB_LOOK, NOUN_FORMALDEHYDE)) && (_game._objects.isInRoom(OBJ_FORMALDEHYDE))) + _vm->_dialogs->show(41122); + else if ((_action.isAction(VERB_LOOK, NOUN_LECITHIN)) && (_game._objects.isInRoom(OBJ_LECITHIN))) + _vm->_dialogs->show(41123); + else if (_action.isAction(VERB_LOOK, NOUN_KETTLE)) { + if (_globals[kNextIngredient] > 0 && !_game._objects[OBJ_CHARGE_CASES].getQuality(3)) { + _vm->_dialogs->show(41126); + } else if (_globals[kNextIngredient] == 0 || _game._objects[OBJ_CHARGE_CASES].getQuality(3)) { + _vm->_dialogs->show(41125); + } + } else if (_action.isAction(VERB_LOOK, NOUN_EXPLOSIVES) && _game._objects[OBJ_CHARGE_CASES].getQuality(3) == 0) { + _vm->_dialogs->show(41127); + } else if (_action.isAction(VERB_TAKE, NOUN_KETTLE)) + _vm->_dialogs->show(41128); + else if (_action.isAction(VERB_LOOK, NOUN_CONTROL_PANEL)) + _vm->_dialogs->show(41129); + else if (_action.isAction(VERB_LOOK, NOUN_MISHAP)) + _vm->_dialogs->show(41130); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH)) + _vm->_dialogs->show(41131); + else if (_action._lookFlag) + _vm->_dialogs->show(41132); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_HORN)) + _vm->_dialogs->show(41133); + else if (_action.isAction(VERB_LOOK, NOUN_DEBRIS)) + _vm->_dialogs->show(41134); + else if (_action.isAction(VERB_LOOK, NOUN_HEATER)) + _vm->_dialogs->show(41135); + else if (_action.isAction(VERB_LOOK, NOUN_PIPE)) + _vm->_dialogs->show(41136); + else if (_action.isAction(VERB_LOOK, NOUN_SINK)) + _vm->_dialogs->show(41137); + else if (_action.isAction(VERB_PUT, NOUN_SINK)) + _vm->_dialogs->show(41138); + else if (_action.isAction(VERB_TAKE, NOUN_EXPERIMENT)) + _vm->_dialogs->show(41139); + else if (_action.isAction(VERB_LOOK, NOUN_ELECTRODES)) + _vm->_dialogs->show(41140); + else if (_action.isAction(VERB_TAKE, NOUN_ELECTRODES)) + _vm->_dialogs->show(41141); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene413::Scene413(MADSEngine *vm) : Scene4xx(vm) { + _rexDeath = -1; + _canMove = -1; +} + +void Scene413::synchronize(Common::Serializer &s) { + Scene4xx::synchronize(s); + + s.syncAsSint32LE(_rexDeath); + s.syncAsSint32LE(_canMove); +} + +void Scene413::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene413::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 2)); + _rexDeath = false; + + if (_scene->_priorSceneId == 405) { + _game._player._playerPos = Common::Point(142, 146); + _game._player._facing = FACING_NORTH; + _game._player._visible = true; + } else if (_scene->_priorSceneId != -2) { + if (_globals[kSexOfRex] == REX_MALE) { + _scene->loadAnimation(Resources::formatName(413, 'd', 1, EXT_AA, ""), 78); + _vm->_sound->command(30); + _game._player._visible = false; + _game._player._stepEnabled = false; + _rexDeath = true; + } else if (!_globals[kTeleporterCommand]) { + _game._player._playerPos = Common::Point(136, 117); + _game._player.walk(Common::Point(141, 130), FACING_SOUTH); + _game._player._facing = FACING_SOUTH; + _game._player._visible = true; + } + } + + if ((_globals[kTeleporterCommand]) && (!_rexDeath)) { + switch (_globals[kTeleporterCommand]) { + case 1: + _vm->_sound->command(30); + _game._player._visible = false; + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 19); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 76); + break; + + case 2: + _game._player._visible = false; + _vm->_sound->command(30); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 20); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 77); + break; + + case 3: + case 4: + _game._player._playerPos = Common::Point(136, 117); + _game._player._facing = FACING_SOUTH; + _game._player.walk(Common::Point(141, 130), FACING_SOUTH); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + _globals[kTeleporterCommand] = 0; + } + + _canMove = true; + sceneEntrySound(); +} + +void Scene413::step() { + if (_scene->_activeAnimation && _scene->_activeAnimation->getCurrentFrame() == 38) + _scene->_activeAnimation->setCurrentFrame(37); + + if (_scene->_activeAnimation && _scene->_activeAnimation->getCurrentFrame() == 21 && _canMove) { + _vm->_sound->command(27); + _canMove = false; + } + + if (_game._trigger == 76) { + _game._player._playerPos = Common::Point(136, 117); + _game._player.walk(Common::Point(141, 130), FACING_SOUTH); + _game._player._facing = FACING_SOUTH; + _game._player.selectSeries(); + _game._player._visible = true; + _game._player._stepEnabled = true; + } + + if (_game._trigger == 77) { + _globals[kTeleporterCommand] = TELEPORTER_BEAM_IN; + _scene->_nextSceneId = _globals[kTeleporterDestination]; + _scene->_reloadSceneFlag = true; + } + + if (_game._trigger == 78) { + _scene->_reloadSceneFlag = true; + _scene->_nextSceneId = _scene->_priorSceneId; + _globals[kTeleporterCommand] = TELEPORTER_NONE; + } +} + +void Scene413::preActions() { + if (_action.isAction(VERB_TAKE) || _action.isAction(VERB_PUT, NOUN_CONVEYOR_BELT)) + _game._player._needToWalk = false; + + if (_action.isAction(VERB_LOOK, NOUN_WOODEN_STATUE) || _action.isAction(VERB_LOOK, NOUN_DISPLAY) + || _action.isAction(VERB_LOOK, NOUN_PICTURE) || _action.isAction(VERB_LOOK, NOUN_PLANT)) { + _game._player._needToWalk = true; + } +} + +void Scene413::actions() { + if (_action.isAction(VERB_WALK_INSIDE, NOUN_TELEPORTER)) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_nextSceneId = 409; + } else if (_action.isAction(VERB_WALK_INSIDE, NOUN_CORRIDOR_TO_SOUTH)) + _scene->_nextSceneId = 405; + else if (_action.isAction(VERB_LOOK, NOUN_WOODEN_STATUE)) + _vm->_dialogs->show(41310); + else if (_action.isAction(VERB_TAKE, NOUN_WOODEN_STATUE)) + _vm->_dialogs->show(41311); + else if (_action.isAction(VERB_LOOK, NOUN_CONVEYOR_BELT)) + _vm->_dialogs->show(41312); + else if (_action.isAction(VERB_PUT, NOUN_CONVEYOR_BELT)) + _vm->_dialogs->show(41313); + else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER)) + _vm->_dialogs->show(41314); + else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY)) + _vm->_dialogs->show(41315); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH)) + _vm->_dialogs->show(41316); + else if (_action.isAction(VERB_LOOK, NOUN_PICTURE)) + _vm->_dialogs->show(41317); + else if (_action.isAction(VERB_LOOK, NOUN_PLANT)) + _vm->_dialogs->show(41318); + else if (_action.isAction(VERB_TAKE, NOUN_PLANT)) + _vm->_dialogs->show(41319); + else if (_action._lookFlag) + _vm->_dialogs->show(41320); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +} // End of namespace Nebular +} // End of namespace MADS diff --git a/engines/mads/nebular/nebular_scenes4.h b/engines/mads/nebular/nebular_scenes4.h new file mode 100644 index 0000000000..fbd5ce81f0 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes4.h @@ -0,0 +1,258 @@ +/* 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. + * + */ + +#ifndef MADS_NEBULAR_SCENES4_H +#define MADS_NEBULAR_SCENES4_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" + +namespace MADS { + +namespace Nebular { + +class Scene4xx : public NebularScene { +protected: + /** + * Plays an appropriate sound when entering a scene + */ + void setAAName(); + + /** + * Updates the prefix used for getting player sprites for the scene + */ + void setPlayerSpritesPrefix(); + + void sceneEntrySound(); + +public: + Scene4xx(MADSEngine *vm) : NebularScene(vm) {} +}; + +class Scene401 : public Scene4xx { +private: + bool _northFl; + Common::Point _destPos; + uint32 _timer; + +public: + Scene401(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene402 : public Scene4xx { +private: + bool _lightOn; + bool _blowingSmoke; + bool _leftWomanMoving; + bool _rightWomanMoving; + bool _firstTalkToGirlInChair; + bool _waitingGinnyMove; + bool _ginnyLooking; + bool _bigBeatFl; + bool _roxOnStool; + bool _bartenderSteady; + bool _bartenderHandsHips; + bool _bartenderLooksLeft; + bool _bartenderReady; + bool _bartenderTalking; + bool _bartenderCalled; + bool _conversationFl; + bool _activeTeleporter; + bool _activeArrows; + bool _activeArrow1; + bool _activeArrow2; + bool _activeArrow3; + bool _cutSceneReady; + bool _cutSceneNeeded; + bool _helgaReady; + bool _refuseAlienLiquor; + + int _drinkTimer; + int _beatCounter; + int _bartenderMode; + int _bartenderDialogNode; + int _bartenderCurrentQuestion; + int _helgaTalkMode; + int _roxMode; + int _rexMode; + int _talkTimer; + + Conversation _dialog1; + Conversation _dialog2; + Conversation _dialog3; + Conversation _dialog4; + + void setDialogNode(int node); + void handleConversation1(); + void handleConversation2(); + void handleConversation3(); + void handleConversation4(); + void handleDialogs(); + +public: + Scene402(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene405 : public Scene4xx { +public: + Scene405(MADSEngine *vm) : Scene4xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene406 : public Scene4xx { +private: + bool _hitStorageDoor; + +public: + Scene406(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene407 : public Scene4xx { +private: + bool _fromNorth; + Common::Point _destPos; + +public: + Scene407(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene408 : public Scene4xx { +public: + Scene408(MADSEngine *vm) : Scene4xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene409 : public SceneTeleporter { +public: + Scene409(MADSEngine *vm) : SceneTeleporter(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene410 : public Scene4xx { +public: + Scene410(MADSEngine *vm) : Scene4xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene411 : public Scene4xx { +private: + int _curAnimationFrame; + int _newIngredient; + int _newQuantity; + int _resetFrame; + int _badThreshold; + + bool _killRox; + bool _makeMushroomCloud; + + Conversation _dialog1; + Conversation _dialog2; + Conversation _dialog3; + Conversation _dialog4; + + void giveToRex(int object); + void handleDialog(); + void handleKettleAction(); + + int computeQuoteAndQuantity(); + + bool addQuantity(); + bool addIngredient(); + +public: + Scene411(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene413 : public Scene4xx { +private: + int _rexDeath; + int _canMove; + +public: + Scene413(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; +} // End of namespace Nebular +} // End of namespace MADS + +#endif /* MADS_NEBULAR_SCENES4_H */ diff --git a/engines/mads/nebular/nebular_scenes5.cpp b/engines/mads/nebular/nebular_scenes5.cpp new file mode 100644 index 0000000000..fd5e244872 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes5.cpp @@ -0,0 +1,2872 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "mads/mads.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/nebular/nebular_scenes5.h" + +namespace MADS { + +namespace Nebular { + +void Scene5xx::setAAName() { + _game._aaName = Resources::formatAAName(5); +} + +void Scene5xx::setPlayerSpritesPrefix() { + _vm->_sound->command(5); + + Common::String oldName = _game._player._spritesPrefix; + + if ((_scene->_nextSceneId == 502) || (_scene->_nextSceneId == 504) || (_scene->_nextSceneId == 505) || (_scene->_nextSceneId == 515)) + _game._player._spritesPrefix = ""; + else if (_globals[kSexOfRex] == REX_MALE) + _game._player._spritesPrefix = "RXM"; + else if ((_scene->_nextSceneId == 501) || (_scene->_nextSceneId == 503) || (_scene->_nextSceneId == 551)) + _game._player._spritesPrefix = "ROX"; + + _game._player._scalingVelocity = true; + + if ((_scene->_nextSceneId == 512) || (_scene->_nextSceneId == 507)) + _game._player._scalingVelocity = false; + + if (oldName != _game._player._spritesPrefix) + _game._player._spritesChanged = true; + + _vm->_palette->setEntry(16, 10, 63, 63); + _vm->_palette->setEntry(17, 10, 45, 45); +} + +void Scene5xx::sceneEntrySound() { + if (!_vm->_musicFlag) { + _vm->_sound->command(2); + return; + } + + switch (_scene->_nextSceneId) { + case 501: + case 502: + case 504: + case 505: + case 506: + case 507: + case 508: + case 511: + case 512: + case 513: + case 515: + case 551: + if (_scene->_priorSceneId == 503) + _vm->_sound->command(38); + else + _vm->_sound->command(29); + break; + case 503: + _vm->_sound->command(41); + break; + default: + break; + } +} + +/*------------------------------------------------------------------------*/ + +Scene501::Scene501(MADSEngine *vm) : Scene5xx(vm) { + _mainSequenceId = -1; + _mainSpriteId = -1; + _doorHotspotid = -1; + + _rexPunched = false; +} + +void Scene501::synchronize(Common::Serializer &s) { + Scene5xx::synchronize(s); + + s.syncAsSint16LE(_mainSequenceId); + s.syncAsSint16LE(_mainSpriteId); + s.syncAsSint16LE(_doorHotspotid); + s.syncAsByte(_rexPunched); +} + +void Scene501::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_DOOR); + _scene->addActiveVocab(VERB_WALK_THROUGH); +} + +void Scene501::handleSlotActions() { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + int numTicks, frameIndex; + if (_globals[kSexOfRex] == REX_MALE) { + _mainSpriteId = _globals._spriteIndexes[4]; + numTicks = 8; + frameIndex = 3; + } else { + _mainSpriteId = _globals._spriteIndexes[5]; + numTicks = 10; + frameIndex = 2; + } + + _mainSequenceId = _scene->_sequences.startReverseCycle(_mainSpriteId, false, numTicks, 1, 0, 0); + _scene->_sequences.setAnimRange(_mainSequenceId, 1, frameIndex); + _scene->_sequences.setMsgLayout(_mainSequenceId); + _vm->_sound->command(10); + _scene->_sequences.addSubEntry(_mainSequenceId, SEQUENCE_TRIGGER_SPRITE, frameIndex, 1); + _scene->_sequences.addSubEntry(_mainSequenceId, SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 12, 6, 0, 0); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _mainSequenceId); + _game._player._visible = true; + _scene->_sequences.addTimer(15, 3); + break; + + case 3: + _game._player.walk(Common::Point(282, 110), FACING_NORTH); + _scene->_sequences.addTimer(60, 4); + break; + + default: + break; + } +} + +void Scene501::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('c', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 0)); + + if (_globals[kSexOfRex] == REX_MALE) { + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXMRC_9"); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites("*RXCD_7"); + } else { + _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*ROXRC_9"); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites("*ROXCD_7"); + } + + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + int idx = _scene->_dynamicHotspots.add(NOUN_DOOR, VERB_WALK_THROUGH, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _doorHotspotid = _scene->_dynamicHotspots.setPosition(idx,Common::Point(282, 110), FACING_NORTH); + _scene->_dynamicHotspots.setCursor(_doorHotspotid, CURSOR_GO_UP); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _rexPunched = true; + + if (_scene->_priorSceneId == 504) { + _game._player._stepEnabled = false; + _game._player._playerPos = Common::Point(74, 121); + _game._player._facing = FACING_NORTHWEST; + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + if (_globals[kSexOfRex] == REX_MALE) + _scene->loadAnimation(formAnimName('G', 2), 70); + else + _scene->loadAnimation(formAnimName('R', 2), 70); + } else if (_scene->_priorSceneId == 503) { + _game._player._playerPos = Common::Point(317, 102); + _game._player._facing = FACING_SOUTHWEST; + _scene->_sequences.addTimer(15, 80); + } else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(299, 131); + + if (_scene->_roomChanged) { + _game._objects.addToInventory(OBJ_FAKE_ID); + _game._objects.addToInventory(OBJ_SECURITY_CARD); + _game._objects.addToInventory(OBJ_ID_CARD); + } + + sceneEntrySound(); + _game.loadQuoteSet(0x275, 0x276, 0x277, 0); + + if (!_game._visitedScenes._sceneRevisited) + _scene->_sequences.addTimer(2, 90); +} + +void Scene501::step() { + if (_game._trigger == 90) + _vm->_dialogs->show(50127); + + if (_game._trigger >= 80) { + switch (_game._trigger) { + case 80: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 12, 6, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + _vm->_sound->command(11); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 81); + break; + + case 81: + _scene->_dynamicHotspots.remove(_doorHotspotid); + _game._player.walk(Common::Point(276, 110), FACING_SOUTHWEST); + _scene->_sequences.addTimer(120, 82); + break; + + case 82: + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + _vm->_sound->command(12); + _doorHotspotid = _scene->_dynamicHotspots.add(NOUN_DOOR, VERB_WALK_THROUGH, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_globals._sequenceIndexes[3], Common::Point(282, 110), FACING_NORTH); + _scene->_dynamicHotspots.setCursor(_doorHotspotid, CURSOR_GO_UP); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 83); + break; + + case 83: + _game._player._stepEnabled = true; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + break; + + default: + break; + } + } + + if (_game._trigger >= 70 && _game._trigger <= 73) { + switch (_game._trigger) { + case 70: + _game._player._visible = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _scene->_sequences.addTimer(15, 71); + break; + + case 71: + _game._player.walk(Common::Point(92, 130), FACING_SOUTH); + _scene->_sequences.addTimer(30, 72); + break; + + case 72: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 73); + break; + + case 73: + _game._player._stepEnabled = true; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + break; + + default: + break; + } + } +} + +void Scene501::preActions() { + if (_action.isAction(VERB_WALK_DOWN) && (_action.isObject(NOUN_STREET_TO_EAST) || _action.isObject(NOUN_SIDEWALK_TO_EAST))) + _game._player._walkOffScreenSceneId = 551; +} + +void Scene501::actions() { + if (_action.isAction(VERB_GET_INTO, NOUN_CAR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], syncIdx); + _scene->_sequences.addTimer(15, 2); + } + break; + + case 2: + _game._player._visible = false; + if (_globals[kSexOfRex] == REX_MALE) + _mainSpriteId = _globals._spriteIndexes[6]; + else + _mainSpriteId = _globals._spriteIndexes[7]; + + _mainSequenceId = _scene->_sequences.addSpriteCycle(_mainSpriteId, false, 8, 1, 0, 0); + _scene->_sequences.setMsgLayout(_mainSequenceId); + _scene->_sequences.addSubEntry(_mainSequenceId, SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: { + int syncIdx = _mainSequenceId; + _mainSequenceId = _scene->_sequences.startCycle(_mainSpriteId, false, -2); + _scene->_sequences.setMsgLayout(_mainSequenceId); + _scene->_sequences.updateTimeout(_mainSequenceId, syncIdx); + _scene->_sequences.addTimer(30, 4); + } + break; + + case 4: + _scene->_nextSceneId = 504; + break; + + default: + break; + } + } else if (_action.isAction(VERB_PUT, NOUN_SECURITY_CARD, NOUN_CARD_SLOT)) + _vm->_dialogs->show(50113); + else if (_action.isAction(VERB_PUT, NOUN_FAKE_ID, NOUN_CARD_SLOT)) { + switch (_game._trigger) { + case 0: + case 1: + case 2: + case 3: + handleSlotActions(); + break; + + case 4: + if (_globals[kSexOfRex] == REX_MALE) { + _game._player._visible = false; + _vm->_sound->command(13); + _scene->loadAnimation(formAnimName('G', 1), 5); + } else { + _rexPunched = false; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 6, 120, _game.getQuote(0x277)); + } + break; + + case 5: + _game._player._visible = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _scene->_sequences.addTimer(30, 6); + break; + + case 6: + if (_globals[kSexOfRex] == REX_MALE) { + if (_rexPunched) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x275)); + _rexPunched = false; + } else { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x276)); + } + } + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_PUT, NOUN_ID_CARD, NOUN_CARD_SLOT)) { + switch (_game._trigger) { + case 0: + case 1: + case 2: + case 3: + handleSlotActions(); + break; + + case 4: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _scene->_dynamicHotspots.remove(_doorHotspotid); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + _vm->_sound->command(11); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 6); + break; + + case 6: + _game._player.walk(Common::Point(317, 102), FACING_NORTHEAST); + _scene->_sequences.addTimer(120, 7); + break; + + case 7: { + _vm->_sound->command(12); + int syncIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _vm->_sound->command(12); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 8); + } + break; + + case 8: { + int syncIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _scene->_nextSceneId = 503; + } + break; + + default: + break; + } + } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_STREET)) + _vm->_dialogs->show(50121); + else if (_action.isAction(VERB_LOOK, NOUN_DOOR)) + _vm->_dialogs->show(50110); + else if (_action.isAction(VERB_LOOK, NOUN_CARD_SLOT)) + _vm->_dialogs->show(50112); + else if (_action.isAction(VERB_LOOK, NOUN_SIGN)) + _vm->_dialogs->show(50114); + else if (_action.isAction(VERB_TAKE, NOUN_SIGN)) + _vm->_dialogs->show(50115); + else if (_action.isAction(VERB_LOOK, NOUN_SIDEWALK_TO_EAST)) + _vm->_dialogs->show(50118); + else if (_action.isAction(VERB_LOOK, NOUN_SIDEWALK_TO_WEST) || _action.isAction(VERB_LOOK, NOUN_STREET_TO_WEST) + || _action.isAction(VERB_WALK_DOWN, NOUN_SIDEWALK_TO_WEST) || _action.isAction(VERB_WALK_DOWN, NOUN_STREET_TO_WEST)) + _vm->_dialogs->show(50119); + else if (_action.isAction(VERB_LOOK, NOUN_BUILDING)) + _vm->_dialogs->show(50120); + else if (_action.isAction(VERB_OPEN, NOUN_DOOR)) + _vm->_dialogs->show(50122); + else if (_action.isAction(VERB_LOOK, NOUN_FIRE_HYDRANT)) + _vm->_dialogs->show(50123); + else if (_action.isAction(VERB_OPEN, NOUN_FIRE_HYDRANT)) + _vm->_dialogs->show(50124); + else if (_action.isAction(VERB_LOOK, NOUN_EQUIPMENT_OVERHEAD)) + _vm->_dialogs->show(50125); + else if (_action.isAction(VERB_LOOK, NOUN_PIPES) || _action.isAction(VERB_LOOK, NOUN_PIPE)) + _vm->_dialogs->show(50126); + else if (_action.isAction(VERB_LOOK, NOUN_CAR)) { + if (!_game._visitedScenes.exists(504)) + _vm->_dialogs->show(50116); + else + _vm->_dialogs->show(50117); + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene502::setup() { + _game._player._spritesPrefix = ""; + // The original is using Scene5xx_setAAName() + _game._aaName = Resources::formatAAName(5); +} + +void Scene502::enter() { + if (_globals[kSexOfRex] == REX_MALE) + _handSpriteId = _scene->_sprites.addSprites("*REXHAND"); + else + _handSpriteId = _scene->_sprites.addSprites("*ROXHAND"); + + teleporterEnter(); + + // The original uses scene5xx_sceneEntrySound + if (!_vm->_musicFlag) + _vm->_sound->command(2); + else if (_scene->_priorSceneId == 503) + _vm->_sound->command(38); + else + _vm->_sound->command(29); +} + +void Scene502::step() { + teleporterStep(); +} + +void Scene502::actions() { + if (teleporterActions()) { + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_VIEWPORT) || _action.isAction(VERB_PEER_THROUGH, NOUN_VIEWPORT)) + _vm->_dialogs->show(50210); + else if (_action.isAction(VERB_LOOK, NOUN_KEYPAD)) + _vm->_dialogs->show(50211); + else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY)) + _vm->_dialogs->show(50212); + else if (_action.isAction(VERB_LOOK, NOUN_0_KEY) || _action.isAction(VERB_LOOK, NOUN_1_KEY) + || _action.isAction(VERB_LOOK, NOUN_2_KEY) || _action.isAction(VERB_LOOK, NOUN_3_KEY) + || _action.isAction(VERB_LOOK, NOUN_4_KEY) || _action.isAction(VERB_LOOK, NOUN_5_KEY) + || _action.isAction(VERB_LOOK, NOUN_6_KEY) || _action.isAction(VERB_LOOK, NOUN_7_KEY) + || _action.isAction(VERB_LOOK, NOUN_8_KEY) || _action.isAction(VERB_LOOK, NOUN_9_KEY) + || _action.isAction(VERB_LOOK, NOUN_SMILE_KEY) || _action.isAction(VERB_LOOK, NOUN_ENTER_KEY) + || _action.isAction(VERB_LOOK, NOUN_FROWN_KEY)) + _vm->_dialogs->show(50213); + else if (_action.isAction(VERB_LOOK, NOUN_DEVICE) || _action._lookFlag) + _vm->_dialogs->show(50214); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene503::Scene503(MADSEngine *vm) : Scene5xx(vm) { + _detonatorHotspotId = -1; +} + +void Scene503::synchronize(Common::Serializer &s) { + Scene5xx::synchronize(s); + + s.syncAsSint16LE(_detonatorHotspotId); +} + +void Scene503::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_DETONATORS); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene503::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', -1)); + + if (_globals[kSexOfRex] == REX_MALE) + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMBD_2"); + else + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*ROXBD_2"); + + if (_game._objects[OBJ_DETONATORS]._roomNumber == _scene->_currentSceneId) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 0, 0, 0); + _detonatorHotspotId = _scene->_dynamicHotspots.add(NOUN_DETONATORS, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_detonatorHotspotId, Common::Point(254, 135), FACING_SOUTH); + } + + if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(191, 152); + _game._player._facing = FACING_NORTHWEST; + } + + sceneEntrySound(); +} + +void Scene503::actions() { + if (_action.isAction(VERB_WALK, NOUN_OUTSIDE)) + _scene->_nextSceneId = 501; + else if (_action.isAction(VERB_TAKE, NOUN_DETONATORS)) { + if ( _game._trigger || !_game._objects.isInInventory(OBJ_DETONATORS)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + if (_globals[kSexOfRex] == REX_MALE) { + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 3, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } else { + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], true, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 4); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 4, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + + case 1: + _vm->_sound->command(9); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_dynamicHotspots.remove(_detonatorHotspotId); + _game._objects.addToInventory(OBJ_DETONATORS); + _vm->_dialogs->showItem(OBJ_DETONATORS, 50326); + break; + + case 2: + if (_globals[kSexOfRex] == REX_MALE) + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + else + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]); + + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } + } else if (_action._lookFlag) + _vm->_dialogs->show(50328); + else if (_action.isAction(VERB_LOOK, NOUN_MONITORING_EQUIPMENT)) + _vm->_dialogs->show(50310); + else if (_action.isAction(VERB_LOOK, NOUN_PHOTON_RIFLES)) + _vm->_dialogs->show(50311); + else if (_action.isAction(VERB_TAKE, NOUN_PHOTON_RIFLES) || _action.isAction(VERB_TAKE, NOUN_NUCLEAR_SLINGSHOT)) + _vm->_dialogs->show(50312); + else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY_CASE)) + _vm->_dialogs->show(50313); + else if (_action.isAction(VERB_LOOK, NOUN_NUCLEAR_SLINGSHOT)) + _vm->_dialogs->show(50314); + else if (_action.isAction(VERB_LOOK, NOUN_WATER_COOLER)) + _vm->_dialogs->show(50315); + else if (_action.isAction(VERB_LOOK, NOUN_STORAGE_BOX)) + _vm->_dialogs->show(50316); + else if (_action.isAction(VERB_OPEN, NOUN_STORAGE_BOX)) + _vm->_dialogs->show(50317); + else if (_action.isAction(VERB_LOOK, NOUN_WARNING_LABEL)) + _vm->_dialogs->show(50318); + else if (_action.isAction(VERB_LOOK, NOUN_DESK)) + _vm->_dialogs->show(50319); + else if (_action.isAction(VERB_LOOK, NOUN_MONITOR)) + _vm->_dialogs->show(50320); + else if (_action.isAction(VERB_LOOK, NOUN_FILE_CABINETS)) + _vm->_dialogs->show(50322); + else if (_action.isAction(VERB_LOOK, NOUN_BOX)) { + if (_game._objects.isInRoom(OBJ_DETONATORS)) + _vm->_dialogs->show(50323); + else + _vm->_dialogs->show(50324); + } else if (_action.isAction(VERB_LOOK, NOUN_DETONATORS) && (_action._savedFields._mainObjectSource == 4)) + _vm->_dialogs->show(50325); + else if (_action.isAction(VERB_LOOK, NOUN_WINDOWS)) + _vm->_dialogs->show(50327); + else if (_action.isAction(VERB_OPEN, NOUN_DISPLAY_CASE)) + _vm->_dialogs->show(50329); + else if (_action.isAction(VERB_THROW, NOUN_DISPLAY_CASE) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) + _vm->_dialogs->show(50330); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene504::Scene504(MADSEngine *vm) : Scene5xx(vm) { + _carAnimationMode = -1; + _carFrame = -1; +} + +void Scene504::synchronize(Common::Serializer &s) { + Scene5xx::synchronize(s); + + s.syncAsSint16LE(_carAnimationMode); + s.syncAsSint16LE(_carFrame); +} + +void Scene504::setup() { + _game._player._spritesPrefix = ""; + setAAName(); +} + +void Scene504::enter() { + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 2)); + + for (int i = 0; i < 4; i++) + _globals._spriteIndexes[5 + i] = _scene->_sprites.addSprites(formAnimName('m', i)); + + if (_globals[kSexOfRex] == REX_MALE) + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 0)); + else { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _scene->changeVariant(1); + } + + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 0, 0, 0); + _carFrame = -1; + + if ((_scene->_priorSceneId == 505) && (_globals[kHoverCarDestination] != _globals[kHoverCarLocation])){ + _carAnimationMode = 1; + _scene->loadAnimation(formAnimName('A', -1)); + _vm->_sound->command(14); + _scene->_sequences.addTimer(1, 70); + _game._player._stepEnabled = false; + } else { + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 3)); + _carAnimationMode = 1; + _scene->loadAnimation(formAnimName('A', -1)); + if ((_scene->_priorSceneId != -2) && (_scene->_priorSceneId != 505)) + _globals[kHoverCarLocation] = _scene->_priorSceneId; + + _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, 1); + } + + if (_globals[kTimebombTimer] > 10500) + _globals[kTimebombTimer] = 10500; + + sceneEntrySound(); +} + +void Scene504::step() { + if ((_carAnimationMode == 1) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) { + _carFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextFrame; + + if (_carFrame == 1) + nextFrame = 0; + else + nextFrame = -1; + + if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextFrame); + _carFrame = nextFrame; + } + } + } + + + if (_game._trigger >= 70) { + switch (_game._trigger) { + case 70: + if (_globals[kHoverCarDestination] != -1) { + _game._player._stepEnabled = false; + _scene->freeAnimation(); + _carAnimationMode = 2; + if (((_globals[kHoverCarLocation] >= 500 && _globals[kHoverCarLocation] <= 599) && + (_globals[kHoverCarDestination] >= 500 && _globals[kHoverCarDestination] <= 599)) || + ((_globals[kHoverCarLocation] >= 600 && _globals[kHoverCarLocation] <= 699) && + (_globals[kHoverCarDestination] >= 600 && _globals[kHoverCarDestination] <= 699))) { + _scene->loadAnimation(formAnimName('A', -1), 71); + } else if (_globals[kHoverCarLocation] > _globals[kHoverCarDestination]) + _scene->loadAnimation(formAnimName('C', -1), 71); + else + _scene->loadAnimation(formAnimName('B', -1), 71); + } + break; + + case 71: + _vm->_sound->command(15); + _scene->_nextSceneId = _globals[kHoverCarDestination]; + break; + + default: + break; + } + } + + if ((_globals[kTimebombTimer] >= 10800) && (_globals[kTimebombStatus] == TIMEBOMB_ACTIVATED) && (_game._difficulty != 3)) { + _globals[kTimebombStatus] = TIMEBOMB_DEAD; + _globals[kTimebombTimer] = 0; + _globals[kCheckDaemonTimebomb] = false; + _scene->_nextSceneId = 620; + } +} + +void Scene504::preActions() { + _game._player._needToWalk = false; +} + +void Scene504::actions() { + if (_action.isAction(VERB_EXIT_FROM, NOUN_CAR)) { + _vm->_sound->command(15); + _scene->_nextSceneId = _globals[kHoverCarLocation]; + } else if (_action.isAction(VERB_ACTIVATE, NOUN_CAR_CONTROLS)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _vm->_sound->command(39); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 13); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _scene->_sequences.remove(_globals._sequenceIndexes[7]); + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 18, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 14); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 13); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 6); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + } + break; + + case 2: + _scene->_sequences.addTimer(10, 3); + break; + + case 3: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + if (_globals[kSexOfRex] == REX_MALE) { + _vm->_sound->command(34); + _scene->_sequences.addTimer(60, 4); + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 14); + } else { + _vm->_sound->command(40); + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 18, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 14); + _scene->_sequences.addTimer(120, 5); + } + break; + + case 4: + _game._player._stepEnabled = true; + _globals[kHoverCarDestination] = _globals[kHoverCarLocation]; + _scene->_nextSceneId = 505; + break; + + case 5: + _game._player._stepEnabled = true; + _scene->_sequences.remove(_globals._sequenceIndexes[8]); + _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, 1); + _vm->_dialogs->show(50421); + break; + + default: + break; + } + } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_INTERIOR_OF_CAR)) + _vm->_dialogs->show(50412); + else if (_action.isAction(VERB_LOOK, NOUN_GLOVE_COMPARTMENT)) + _vm->_dialogs->show(50410); + else if (_action.isAction(VERB_LOOK, NOUN_CAR_CONTROLS) || _action.isAction(VERB_LOOK, NOUN_DASHBOARD)) + _vm->_dialogs->show(50411); + else if (_action.isAction(VERB_LOOK, NOUN_SCENT_PACKET)) + _vm->_dialogs->show(50413); + else if (_action.isAction(VERB_LOOK, NOUN_SODA_CANS)) + _vm->_dialogs->show(50414); + else if (_action.isAction(VERB_LOOK, NOUN_KITTY)) + _vm->_dialogs->show(50415); + else if (_action.isAction(VERB_LOOK, NOUN_WINDSHIELD) || _action.isAction(VERB_LOOK_THROUGH, NOUN_WINDSHIELD)) + _vm->_dialogs->show(50416); + else if (_action.isAction(VERB_LOOK, NOUN_REARVIEW_MIRROR)) + _vm->_dialogs->show(50417); + else if (_action.isAction(VERB_TAKE, NOUN_REARVIEW_MIRROR)) + _vm->_dialogs->show(50418); + else if (_action.isAction(VERB_LOOK, NOUN_MOLDY_SOCK)) + _vm->_dialogs->show(50419); + else if (_action.isAction(VERB_TAKE, NOUN_MOLDY_SOCK)) + _vm->_dialogs->show(50420); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene505::Scene505(MADSEngine *vm) : Scene5xx(vm) { + _frame = -1; + _nextButtonId = -1; + _homeSelectedId = -1; + _selectedId = -1; + _activeCars = -1; + + for (int i = 0; i < 9; i++) + _carLocations[i] = -1; +} + +void Scene505::synchronize(Common::Serializer &s) { + Scene5xx::synchronize(s); + + s.syncAsSint16LE(_frame); + s.syncAsSint16LE(_nextButtonId); + s.syncAsSint16LE(_homeSelectedId); + s.syncAsSint16LE(_selectedId); + s.syncAsSint16LE(_activeCars); + + for (int i = 0; i < 9; i++) + s.syncAsSint16LE(_carLocations[i]); +} + +void Scene505::setup() { + _game._player._spritesPrefix = ""; + setAAName(); +} + +void Scene505::enter() { + for (int i = 0; i < 9; i++) + _globals._spriteIndexes[i] = _scene->_sprites.addSprites(formAnimName('a', i + 1)); + + _globals._spriteIndexes[13] = _scene->_sprites.addSprites(formAnimName('b', 1)); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('g', 1)); + _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('g', 0)); + _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('t', -1)); + _globals._spriteIndexes[12] = _scene->_sprites.addSprites(formAnimName('e', -1)); + + if (_scene->_priorSceneId != -2) + _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 6, 1, 0, 0); + + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 6, 1, 120, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 60); + _scene->_sequences.addTimer(30, 62); + + _carLocations[0] = 501; + _carLocations[1] = 506; + _carLocations[2] = 511; + _carLocations[3] = 513; + _carLocations[4] = 601; + _carLocations[5] = 604; + _carLocations[6] = 607; + _carLocations[7] = 609; + _carLocations[8] = 612; + + _activeCars = false; + + for (int i = 0; i < 9; i++) { + if (_globals[kHoverCarLocation] == _carLocations[i]) { + _homeSelectedId = i; + if (_scene->_priorSceneId != -2) + _selectedId = i; + } + } + + _game._player._visible = false; + _game._player._stepEnabled = false; + _frame = -1; + _scene->loadAnimation(formAnimName('a', -1)); + _scene->_activeAnimation->setCurrentFrame(86); + + sceneEntrySound(); + _vm->_sound->command(16); +} + +void Scene505::step() { + if (_frame != _scene->_activeAnimation->getCurrentFrame()) { + _frame = _scene->_activeAnimation->getCurrentFrame(); + int resetFrame = -1; + + switch (_frame) { + case 4: + case 24: + case 33: + case 53: + case 62: + case 82: + if (_nextButtonId == 0x38A) + resetFrame = 4; + else if (_nextButtonId == 0x38B) + resetFrame = 33; + else if (_nextButtonId == 0x2DE) + resetFrame = 62; + + break; + + case 15: + case 44: + case 73: { + int this_button; + int old_select; + _vm->_sound->command(17); + old_select = _selectedId; + if (_frame == 15) { + this_button = 0x38A; + _selectedId = (_selectedId + 1) % 9; + } else if (_frame == 44) { + this_button = 0x38B; + _selectedId--; + if (_selectedId < 0) + _selectedId = 8; + } else { + this_button = 0x2DE; + if ((_globals[kTimebombStatus] == TIMEBOMB_ACTIVATED) && (_carLocations[_selectedId] == 501)) + _vm->_dialogs->show(431); + else if (_selectedId != _homeSelectedId) { + _nextButtonId = 0; + _activeCars = true; + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_sequences.remove(_globals._sequenceIndexes[0]); + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 63); + _vm->_sound->command(18); + } + } + + if (_nextButtonId == this_button) + _nextButtonId = 0; + + if (old_select != _selectedId) { + _scene->_sequences.remove(_globals._sequenceIndexes[11]); + _globals._sequenceIndexes[11] = _scene->_sequences.startCycle(_globals._spriteIndexes[11], false, _selectedId + 1); + if (old_select != _homeSelectedId) + _scene->_sequences.remove(_globals._sequenceIndexes[0]); + + if (_selectedId != _homeSelectedId) { + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0 + _selectedId], false, 24, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 1); + } + } + break; + } + + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + if (_nextButtonId == 0x38A) + resetFrame = 29 - _frame; + + break; + + case 26: + case 55: + case 84: + if (_nextButtonId != 0) + resetFrame = 3; + + break; + + case 27: + case 56: + case 85: + if (_nextButtonId != 0) + resetFrame = 2; + + break; + + case 29: + case 58: + case 87: + if (_activeCars) + _globals[kHoverCarDestination] = _carLocations[_selectedId]; + + if (_nextButtonId == 0x38A) + resetFrame = 0; + else if (_nextButtonId == 0x38B) + resetFrame = 29; + else if (_nextButtonId == 0x2DE) + resetFrame = 58; + else + resetFrame = 86; + break; + + case 47: + case 48: + case 49: + case 50: + case 51: + case 52: + if (_nextButtonId == 0x38B) + resetFrame = 87 - _frame; + + break; + + case 76: + case 77: + case 78: + case 79: + case 80: + case 81: + if (_nextButtonId == 0x2DE) + resetFrame = 145 - _frame; + + break; + + default: + break; + } + + if ((resetFrame >= 0) && (resetFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(resetFrame); + _frame = resetFrame; + } + } + + switch (_game._trigger) { + case 60: { + _game._player._stepEnabled = true; + int syncIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], syncIdx); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[_homeSelectedId], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _globals._sequenceIndexes[11] = _scene->_sequences.startCycle(_globals._spriteIndexes[11], false, _selectedId + 1); + + if (_selectedId != _homeSelectedId) { + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0 + _selectedId], false, 24, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 1); + } + break; + } + + case 61: + _globals._sequenceIndexes[10] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[10], false, 8, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[10], _globals._sequenceIndexes[9]); + break; + + case 62: + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 8, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 61); + break; + + case 63: + _globals[kHoverCarDestination] = _carLocations[_selectedId]; + _scene->_nextSceneId = 504; + break; + + default: + break; + } +} + +void Scene505::actions() { + if (_action.isAction(VERB_PRESS)) + _nextButtonId = _action._activeAction._objectNameId; + else if (_action.isAction(VERB_RETURN_TO, NOUN_INSIDE_OF_CAR)) + _scene->_nextSceneId = 504; + else if (_action.isAction(VERB_LOOK, NOUN_VIEW_SCREEN)) + _vm->_dialogs->show(50510); + else if (_action.isAction(VERB_LOOK, NOUN_CONTROL_PANEL)) + _vm->_dialogs->show(50511); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene506::Scene506(MADSEngine *vm) : Scene5xx(vm), _doorPos(0, 0) { + _heroFacing = FACING_DUMMY; + + _doorDepth = -1; + _doorSpriteIdx = -1; + _doorSequenceIdx = -1; + _doorWord = -1; + + _labDoorFl = false; + _firstDoorFl = false; + _actionFl = false; +} + +void Scene506::synchronize(Common::Serializer &s) { + Scene5xx::synchronize(s); + + s.syncAsSint16LE(_doorPos.x); + s.syncAsSint16LE(_doorPos.y); + + s.syncAsByte(_heroFacing); + + s.syncAsSint16LE(_doorDepth); + s.syncAsSint16LE(_doorSpriteIdx); + s.syncAsSint16LE(_doorSequenceIdx); + s.syncAsSint16LE(_doorWord); + + s.syncAsByte(_labDoorFl); + s.syncAsByte(_firstDoorFl); + s.syncAsByte(_actionFl); +} + +void Scene506::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(VERB_WALK_INTO); + _scene->addActiveVocab(NOUN_SOFTWARE_STORE); + _scene->addActiveVocab(NOUN_LABORATORY); +} + +void Scene506::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('q', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('q', 1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('c', -1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXCD_3"); + + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + int idx = _scene->_dynamicHotspots.add(NOUN_LABORATORY, VERB_WALK_INTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + int hotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(65, 125), FACING_NORTHWEST); + _scene->_dynamicHotspots.setCursor(hotspotId, CURSOR_GO_LEFT); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + idx = _scene->_dynamicHotspots.add(NOUN_SOFTWARE_STORE, VERB_WALK_INTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + hotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(112, 102), FACING_NORTHWEST); + _scene->_dynamicHotspots.setCursor(hotspotId, CURSOR_GO_LEFT); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 13); + + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 5); + _firstDoorFl = true; + _actionFl = false; + + if (_scene->_priorSceneId == 508) { + _game._player._playerPos = Common::Point(16, 111); + _game._player._facing = FACING_SOUTHEAST; + _scene->_sequences.addTimer(15, 80); + _game._player._stepEnabled = false; + } else if (_scene->_priorSceneId == 507) { + _game._player._playerPos = Common::Point(80, 102); + _game._player._facing = FACING_SOUTHEAST; + _scene->_sequences.addTimer(60, 80); + _game._player._stepEnabled = false; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(138, 116); + _game._player._facing = FACING_NORTHEAST; + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 5); + _scene->loadAnimation(formAnimName('R', 1), 70); + } + sceneEntrySound(); +} + +void Scene506::step() { + if (_game._trigger >= 80) { + if (_firstDoorFl) { + _heroFacing = FACING_SOUTHEAST; + if (_scene->_priorSceneId == 507) { + _doorPos = Common::Point(112, 102); + _doorWord = 0x336; + } else { + _doorPos = Common::Point(65, 125); + _doorWord = 0x37D; + } + } + handleDoorSequences(); + } + + if (_game._trigger >= 70) { + switch (_game._trigger) { + case 70: + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + _scene->_sequences.addTimer(6, 71); + break; + + case 71: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + break; + + case 72: + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 5); + _game._player._stepEnabled = true; + break; + + default: + break; + } + } +} + +void Scene506::handleDoorSequences() { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + + if (_firstDoorFl) { + if (_action.isAction(VERB_WALK_INTO, NOUN_SOFTWARE_STORE) || ((_scene->_priorSceneId == 507) && !_actionFl)) { + _doorDepth = 13; + _doorSpriteIdx = _globals._spriteIndexes[2]; + _doorSequenceIdx = _globals._sequenceIndexes[2]; + _labDoorFl = false; + } else { + _doorDepth = 10; + _doorSpriteIdx = _globals._spriteIndexes[1]; + _doorSequenceIdx = _globals._sequenceIndexes[1]; + _labDoorFl = true; + } + _firstDoorFl = false; + } + + switch (_game._trigger) { + case 0: + case 80: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_doorSequenceIdx); + _doorSequenceIdx = _scene->_sequences.addSpriteCycle(_doorSpriteIdx, false, 7, 1, 0, 0); + _scene->_sequences.setDepth(_doorSequenceIdx, _doorDepth); + _scene->changeVariant(1); + _scene->_sequences.addSubEntry(_doorSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 81); + break; + + + case 81: + _doorSequenceIdx = _scene->_sequences.startCycle(_doorSpriteIdx, false, -2); + _scene->_sequences.setDepth(_doorSequenceIdx, _doorDepth); + _game._player._walkAnywhere = true; + _game._player.walk(_doorPos, _heroFacing); + _scene->_sequences.addTimer(120, 82); + break; + + case 82: + _scene->_sequences.remove(_doorSequenceIdx); + _doorSequenceIdx = _scene->_sequences.startReverseCycle(_doorSpriteIdx, false, 7, 1, 0, 0); + _scene->_sequences.setDepth(_doorSequenceIdx, _doorDepth); + if (_actionFl) + _scene->_sequences.addSubEntry(_doorSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 84); + else + _scene->_sequences.addSubEntry(_doorSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 83); + + break; + + case 83: { + _doorSequenceIdx = _scene->_sequences.startCycle(_doorSpriteIdx, false, 1); + int idx = _scene->_dynamicHotspots.add(_doorWord, VERB_WALK_INTO, _doorSequenceIdx, Common::Rect(0, 0, 0, 0)); + int hotspotId = _scene->_dynamicHotspots.setPosition(idx, _doorPos, FACING_NORTHWEST); + _scene->_dynamicHotspots.setCursor(hotspotId, CURSOR_GO_LEFT); + _scene->_sequences.setDepth(_doorSequenceIdx, _doorDepth); + _firstDoorFl = true; + if (_labDoorFl) { + _globals._spriteIndexes[1] = _doorSpriteIdx; + _globals._sequenceIndexes[1] = _doorSequenceIdx; + } else { + _globals._spriteIndexes[2] = _doorSpriteIdx; + _globals._sequenceIndexes[2] = _doorSequenceIdx; + } + _game._player._stepEnabled = true; + + } + break; + + case 84: + _actionFl = false; + _game._player._stepEnabled = true; + if (_labDoorFl) + _scene->_nextSceneId = 508; + else + _scene->_nextSceneId = 507; + + break; + + default: + break; + } +} + +void Scene506::actions() { + if (_action.isAction(VERB_WALK_INTO, NOUN_LABORATORY)) { + if (_firstDoorFl) { + _heroFacing = FACING_NORTHWEST; + _doorPos = Common::Point(16, 111); + } + _actionFl = true; + handleDoorSequences(); + } else if (_action.isAction(VERB_WALK_INTO, NOUN_SOFTWARE_STORE)) { + if (_firstDoorFl) { + _heroFacing = FACING_NORTHWEST; + _doorPos = Common::Point(80, 102); + } + _actionFl = true; + handleDoorSequences(); + } else if (_action.isAction(VERB_GET_INTO, NOUN_CAR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _scene->_sequences.addTimer(6, 2); + } + break; + + case 2: + _game._player._visible = false; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: { + int syncIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx); + _scene->_nextSceneId = 504; + } + break; + + default: + break; + } + } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_STREET)) + _vm->_dialogs->show(50618); + else if (_action.isAction(VERB_LOOK, NOUN_RESTAURANT)) + _vm->_dialogs->show(50610); + else if (_action.isAction(VERB_LOOK, NOUN_MOTEL)) + _vm->_dialogs->show(50611); + else if (_action.isAction(VERB_LOOK, NOUN_CYCLE_SHOP)) + _vm->_dialogs->show(50612); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_BIKE)) + _vm->_dialogs->show(50613); + else if (_action.isAction(VERB_TAKE, NOUN_AIR_BIKE)) + _vm->_dialogs->show(50614); + else if (_action.isAction(VERB_LOOK, NOUN_SOFTWARE_STORE)) + _vm->_dialogs->show(50615); + else if (_action.isAction(VERB_LOOK, NOUN_LABORATORY)) + _vm->_dialogs->show(50616); + else if (_action.isAction(VERB_LOOK, NOUN_STREET_TO_WEST) || _action.isAction(VERB_WALK_DOWN, NOUN_STREET_TO_WEST)) + _vm->_dialogs->show(50617); + else if (_action.isAction(VERB_LOOK, NOUN_SOFTWARE_STORE_SIGN)) + _vm->_dialogs->show(50619); + else if (_action.isAction(VERB_LOOK, NOUN_CAR)) + _vm->_dialogs->show(50620); + else if (_action.isAction(VERB_LOOK, NOUN_SKY)) + _vm->_dialogs->show(50621); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene507::Scene507(MADSEngine *vm) : Scene5xx(vm) { + _penlightHotspotId = -1; +} + +void Scene507::synchronize(Common::Serializer &s) { + Scene5xx::synchronize(s); + + s.syncAsSint16LE(_penlightHotspotId); +} + +void Scene507::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_PENLIGHT); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene507::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('p', -1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMRD_3"); + + if ((_game._difficulty != DIFFICULTY_EASY) && (_game._objects[OBJ_PENLIGHT]._roomNumber == _scene->_currentSceneId)) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 0, 0, 0); + _penlightHotspotId = _scene->_dynamicHotspots.add(NOUN_PENLIGHT, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_penlightHotspotId, Common::Point(233, 152), FACING_SOUTHEAST); + } + + if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(121, 147); + _game._player._facing = FACING_NORTH; + } + + sceneEntrySound(); +} +void Scene507::actions() { + if (_action.isAction(VERB_WALK_THROUGH, NOUN_ENTRANCE)) + _scene->_nextSceneId = 506; + else if (_action.isAction(VERB_TAKE, NOUN_PENLIGHT)) { + if (_game._trigger || !_game._objects.isInInventory(OBJ_PENLIGHT)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 5); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 5, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_dynamicHotspots.remove(_penlightHotspotId); + _vm->_sound->command(27); + _game._objects.addToInventory(OBJ_PENLIGHT); + _vm->_dialogs->showItem(OBJ_PENLIGHT, 50730); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } + } else if (_action._lookFlag) + _vm->_dialogs->show(50722); + else if (_action.isAction(VERB_LOOK, NOUN_SWIRLING_LIGHT)) + _vm->_dialogs->show(50710); + else if (_action.isAction(VERB_TAKE, NOUN_SWIRLING_LIGHT)) + _vm->_dialogs->show(50711); + else if (_action.isAction(VERB_LOOK, NOUN_OLD_SOFTWARE)) + _vm->_dialogs->show(50712); + else if (_action.isAction(VERB_TAKE, NOUN_OLD_SOFTWARE)) + _vm->_dialogs->show(50713); + else if (_action.isAction(VERB_LOOK, NOUN_ADVERTISEMENT)) + _vm->_dialogs->show(50714); + else if (_action.isAction(VERB_LOOK, NOUN_ADVERTISING_POSTER)) + _vm->_dialogs->show(50715); + else if (_action.isAction(VERB_LOOK, NOUN_SIGN)) { + if (_scene->_customDest.x < 100) + _vm->_dialogs->show(50726); + else + _vm->_dialogs->show(50716); + } else if (_action.isAction(VERB_LOOK, NOUN_HOTTEST_SOFTWARE)) + _vm->_dialogs->show(50717); + else if (_action.isAction(VERB_LOOK, NOUN_SOFTWARE_SHELF)) + _vm->_dialogs->show(50718); + else if (_action.isAction(VERB_LOOK, NOUN_SENSOR)) + _vm->_dialogs->show(50719); + else if (_action.isAction(VERB_LOOK, NOUN_CASH_REGISTER)) + _vm->_dialogs->show(50720); + else if (_action.isAction(VERB_LOOK, NOUN_PAD_OF_PAPER)) + _vm->_dialogs->show(50721); + else if (_action.isAction(VERB_OPEN, NOUN_CASH_REGISTER)) + _vm->_dialogs->show(50723); + else if (_action.isAction(VERB_LOOK, NOUN_BARGAIN_VAT)) + _vm->_dialogs->show(50724); + else if (_action.isAction(VERB_LOOK, NOUN_WINDOW)) + _vm->_dialogs->show(50725); + else if (_action.isAction(VERB_LOOK, NOUN_COUNTER)) { + if (_game._objects.isInRoom(OBJ_PENLIGHT)) + _vm->_dialogs->show(50728); + else + _vm->_dialogs->show(50727); + } else if (_action.isAction(VERB_LOOK, NOUN_PENLIGHT) && !_game._objects.isInInventory(OBJ_PENLIGHT)) { + if (_game._objects.isInRoom(OBJ_PENLIGHT)) + _vm->_dialogs->show(50729); + } else if (_action.isAction(VERB_LOOK, NOUN_EMERGENCY_LIGHT)) + _vm->_dialogs->show(50731); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene508::Scene508(MADSEngine *vm) : Scene5xx(vm) { + _chosenObject = -1; +} + +void Scene508::synchronize(Common::Serializer &s) { + Scene5xx::synchronize(s); + + s.syncAsSint16LE(_chosenObject); +} + +void Scene508::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_SPINACH_PATCH_DOLL); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_LASER_BEAM); +} + +void Scene508::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('m', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('h', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('l', 2)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('t', 0)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites("*RXMRC_9"); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('l', 3)); + + if (!_game._visitedScenes._sceneRevisited) { + _globals[kLaserOn] = false; + _chosenObject = 0; + } + + if (!_globals[kLaserOn]) { + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8); + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, -2); + int idx = _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(57, 116), FACING_NORTHEAST); + _scene->_hotspots.activate(NOUN_HOLE, false); + _scene->_hotspots.activate(NOUN_LASER_BEAM, false); + } else { + _scene->changeVariant(1); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 11); + int idx = _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(57, 116), FACING_NORTHEAST); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 15, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 6, 8); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 6); + if (_globals[kLaserHoleIsThere]) { + _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, -2); + _scene->_hotspots.activate(NOUN_HOLE, true); + _scene->_hotspots.activate(NOUN_LASER_BEAM, true); + } + _vm->_sound->command(21); + } + _vm->_sound->command(20); + + if (_scene->_priorSceneId == 515) { + _game._player._playerPos = Common::Point(57, 116); + _game._player._facing = FACING_NORTHEAST; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(289, 139); + _game._player._facing = FACING_WEST; + } + + sceneEntrySound(); + _game.loadQuoteSet(0x273, 0); + + if (_scene->_roomChanged) { + _game._objects.addToInventory(OBJ_COMPACT_CASE); + _game._objects.addToInventory(OBJ_REARVIEW_MIRROR); + } +} + +void Scene508::preActions() { + if (_action.isAction(VERB_WALK, NOUN_OUTSIDE)) + _game._player._walkOffScreenSceneId = 506; +} + +void Scene508::handlePedestral() { + if (!_globals[kLaserOn]) + _vm->_dialogs->show(50835); + + if (_globals[kLaserHoleIsThere]) + _vm->_dialogs->show(50836); + + if (_globals[kLaserOn] && !_globals[kLaserHoleIsThere]) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[6] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[6], false, 9, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 4); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[6]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_SPRITE, 4, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 1: + if (_chosenObject == 2) + _game._objects.removeFromInventory(OBJ_COMPACT_CASE, 1); + else + _game._objects.removeFromInventory(OBJ_REARVIEW_MIRROR, 1); + + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 2: + _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, -2); + _scene->_hotspots.activate(NOUN_HOLE, true); + _scene->_hotspots.activate(NOUN_LASER_BEAM, true); + break; + + case 3: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[6]); + _game._player._visible = true; + _scene->_sequences.addTimer(120, 4); + break; + + case 4: + _vm->_dialogs->show(50834); + _globals[kLaserHoleIsThere] = true; + _scene->_nextSceneId = 515; + break; + + default: + break; + } + } +} + +void Scene508::actions() { + if (_action.isAction(VERB_PULL, NOUN_LEVER)) { + if (!_globals[kLaserOn]) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 2, 120, _game.getQuote(0x273)); + break; + + case 2: + _game._player._visible = false; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 10, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 7); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], -1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: + _vm->_sound->command(19); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 15, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 6); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 4); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8); + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[1]); + _game._player._visible = true; + _scene->_sequences.addTimer(15, 5); + break; + + case 4: + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 15, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 6, 8); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 6); + break; + + case 5: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _scene->loadAnimation(formAnimName('B', 1), 6); + break; + + case 6: { + _vm->_sound->command(22); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 11); + int idx = _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(57, 116), FACING_NORTHEAST); + _scene->_kernelMessages.reset(); + _scene->changeVariant(1); + _scene->_sequences.addTimer(30, 7); + } + break; + + case 7: + _globals[kLaserOn] = true; + _vm->_dialogs->show(50833); + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else { + _vm->_dialogs->show(50837); + } + } else if (_action.isAction(VERB_REFLECT, NOUN_REARVIEW_MIRROR, NOUN_LASER_BEAM) || _action.isAction(VERB_PUT, NOUN_REARVIEW_MIRROR, NOUN_PEDESTAL) || _action.isAction(VERB_PUT, NOUN_REARVIEW_MIRROR, NOUN_LASER_BEAM)) { + _chosenObject = 1; + handlePedestral(); + } else if (_action.isAction(VERB_PUT, NOUN_COMPACT_CASE, NOUN_PEDESTAL) || _action.isAction(VERB_PUT, NOUN_COMPACT_CASE, NOUN_LASER_BEAM) || _action.isAction(VERB_REFLECT, NOUN_COMPACT_CASE, NOUN_LASER_BEAM)) { + _chosenObject = 2; + handlePedestral(); + } else if (_action._lookFlag) + _vm->_dialogs->show(50822); + else if (_action.isAction(VERB_LOOK, NOUN_TARGET_AREA)) + _vm->_dialogs->show(50810); + else if (_action.isAction(VERB_LOOK, NOUN_SPINACH_PATCH_DOLL)) + _vm->_dialogs->show(50811); + else if (_action.isAction(VERB_TAKE, NOUN_SPINACH_PATCH_DOLL)) + _vm->_dialogs->show(50812); + else if (_action.isAction(VERB_LOOK, NOUN_SAND_BAGS)) + _vm->_dialogs->show(50816); + else if (_action.isAction(VERB_TAKE, NOUN_SAND_BAGS)) + _vm->_dialogs->show(50817); + else if (_action.isAction(VERB_LOOK, NOUN_CONTROL_STATION)) + _vm->_dialogs->show(50818); + else if (_action.isAction(VERB_LOOK, NOUN_MONITOR)) { + if (_globals[kLaserOn]) + _vm->_dialogs->show(50820); + else + _vm->_dialogs->show(50819); + } else if (_action.isAction(VERB_LOOK, NOUN_LASER_CANNON)) { + if (_globals[kLaserOn]) + _vm->_dialogs->show(50822); + else + _vm->_dialogs->show(50821); + } else if (_action.isAction(VERB_TAKE, NOUN_LASER_CANNON)) + _vm->_dialogs->show(50823); + else if (_action.isAction(VERB_LOOK, NOUN_LEVER)) { + if (_globals[kLaserOn]) + _vm->_dialogs->show(50825); + else + _vm->_dialogs->show(50824); + } else if (_action.isAction(VERB_PUSH, NOUN_LEVER)) + _vm->_dialogs->show(50826); + else if (_action.isAction(VERB_LOOK, NOUN_LASER_BEAM)) { + if (_globals[kLaserHoleIsThere]) + _vm->_dialogs->show(50828); + else + _vm->_dialogs->show(50827); + } else if (_action.isAction(VERB_TAKE, NOUN_LASER_BEAM)) + _vm->_dialogs->show(50829); + else if (_action.isAction(VERB_LOOK, NOUN_CEILING)) { + if (_globals[kLaserHoleIsThere]) + _vm->_dialogs->show(50831); + else + _vm->_dialogs->show(50830); + } else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(50832); + else if (_action.isAction(VERB_LOOK, NOUN_PEDESTAL)) { + if (!_globals[kLaserOn]) + _vm->_dialogs->show(50813); + else if (!_globals[kLaserHoleIsThere]) + _vm->_dialogs->show(50814); + else + _vm->_dialogs->show(50815); + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene511::Scene511(MADSEngine *vm) : Scene5xx(vm) { + _handingLine = false; + _lineMoving = false; + + _lineAnimationMode = -1; + _lineFrame = -1; + _lineAnimationPosition = -1; +} + +void Scene511::synchronize(Common::Serializer &s) { + Scene5xx::synchronize(s); + + s.syncAsByte(_handingLine); + s.syncAsByte(_lineMoving); + + s.syncAsSint16LE(_lineAnimationMode); + s.syncAsSint16LE(_lineFrame); + s.syncAsSint16LE(_lineAnimationPosition); +} + +void Scene511::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_BOAT); + _scene->addActiveVocab(NOUN_FISHING_LINE); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene511::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXCD_6"); + + if (_scene->_priorSceneId != -2) + _handingLine = false; + + if (_globals[kBoatRaised]) { + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('b', 0)); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3); + _scene->_hotspots.activate(NOUN_BOAT, false); + int idx = _scene->_dynamicHotspots.add(NOUN_BOAT, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(75, 124), FACING_NORTH); + _scene->_hotspots.activate(NOUN_ROPE, false); + } else { + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('b', 2)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('b', 3)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('b', 1)); + + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 1, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 5); + + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 4); + + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6],5); + + _scene->_hotspots.activate(NOUN_ROPE, true); + _scene->_hotspots.activate(NOUN_BOAT, true); + _scene->changeVariant(1); + } + + int frame = 0; + if (_globals[kLineStatus] == 2) + frame = -1; + else if (_globals[kLineStatus] == 3) + frame = -2; + + if (_globals[kLineStatus] == 2 || _globals[kLineStatus] == 3) { + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('b', 4)); + _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, frame); + int idx = _scene->_dynamicHotspots.add(NOUN_FISHING_LINE, VERB_WALKTO, _globals._sequenceIndexes[7], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(26, 153), FACING_NORTHEAST); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 3); + if (_globals[kBoatRaised]) + _scene->changeVariant(2); + } + + _lineFrame = -1; + _lineMoving = false; + + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + if (_scene->_priorSceneId == 512) { + _game._player._playerPos = Common::Point(60, 112); + _game._player._facing = FACING_SOUTHEAST; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(55, 152); + _game._player._facing = FACING_NORTHWEST; + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _scene->loadAnimation(formAnimName('R', 1), 70); + } else if (_handingLine) { + _game._player._visible = false; + _lineAnimationMode = 1; + _lineAnimationPosition = 1; + _scene->loadAnimation(formAnimName('R', -1)); + _lineFrame = 2; + } + sceneEntrySound(); +} + +void Scene511::step() { + if ((_lineAnimationMode == 1) && _scene->_activeAnimation) { + if (_lineFrame != _scene->_activeAnimation->getCurrentFrame()) { + _lineFrame = _scene->_activeAnimation->getCurrentFrame(); + int resetFrame = -1; + + if ((_lineAnimationPosition == 2) && (_lineFrame == 14)) + _lineMoving = false; + + if (_lineAnimationPosition == 1) { + if (_lineFrame == 3) { + _lineMoving = false; + resetFrame = 2; + } + + if (_handingLine) + resetFrame = 2; + } + + if ((resetFrame >= 0) && (resetFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(resetFrame); + _lineFrame = resetFrame; + } + } + } + + switch (_game._trigger) { + case 70: + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + _scene->_sequences.addTimer(6, 71); + break; + + case 71: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + break; + + case 72: + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _game._player._stepEnabled = true; + break; + + default: + break; + } +} + +void Scene511::preActions() { + if (!_handingLine) + return; + + if (_action.isAction(VERB_LOOK) || _action.isObject(NOUN_FISHING_LINE) || _action.isAction(VERB_TALKTO)) + _game._player._needToWalk = false; + + if ((!_action.isAction(VERB_TIE, NOUN_FISHING_LINE, NOUN_BOAT) || !_action.isAction(VERB_ATTACH, NOUN_FISHING_LINE, NOUN_BOAT)) && _game._player._needToWalk) { + if (_game._trigger == 0) { + _game._player._readyToWalk = false; + _game._player._stepEnabled = false; + _scene->freeAnimation (); + _lineAnimationMode = 2; + _scene->loadAnimation(formAnimName('R',2), 1); + } else if (_game._trigger == 1) { + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + _game._objects.setRoom(OBJ_FISHING_LINE, 1); + _handingLine = false; + _game._player._stepEnabled = true; + _game._player._readyToWalk = true; + } + } +} + +void Scene511::actions() { + if (_action.isAction(VERB_WALK_INTO, NOUN_RESTAURANT)) + _scene->_nextSceneId = 512; + else if (_action.isAction(VERB_GET_INTO, NOUN_CAR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[1]; + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], syncIdx); + _scene->_sequences.addTimer(6, 2); + } + break; + + case 2: + _game._player._visible = false; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 8, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: { + int syncIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx); + _scene->_nextSceneId = 504; + } + break; + + default: + break; + } + } else if (_action.isAction(VERB_TAKE, NOUN_FISHING_LINE)) { + if (!_globals[kBoatRaised]) { + if (_globals[kLineStatus] == 2) { + if (_globals[kLineStatus] != 3) { + if (_game._trigger == 0) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _lineAnimationMode = 1; + _lineAnimationPosition = 1; + _lineMoving = true; + _scene->loadAnimation(formAnimName('R', -1)); + _scene->_sequences.addTimer(1, 1); + } else if (_game._trigger == 1) { + if (_lineMoving) { + _scene->_sequences.addTimer(1, 1); + } else { + _game._objects.addToInventory(OBJ_FISHING_LINE); + _lineMoving = true; + _handingLine = true; + _game._player._stepEnabled = true; + } + } + } else + _vm->_dialogs->show(51129); + } else + return; + } else { + _vm->_dialogs->show(51130); + } + } else if (_action.isAction(VERB_TIE, NOUN_FISHING_LINE, NOUN_BOAT) || _action.isAction(VERB_ATTACH, NOUN_FISHING_LINE, NOUN_BOAT)) { + if (_globals[kBoatRaised]) + _vm->_dialogs->show(51131); + else if (_globals[kLineStatus] == 1) + _vm->_dialogs->show(51130); + else if (!_globals[kBoatRaised] && _handingLine) { + if (_globals[kLineStatus] != 3) { + if (_game._trigger == 0) { + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[7]); + _lineMoving = true; + _lineAnimationPosition = 2; + _scene->_sequences.addTimer(1, 1); + } else if (_game._trigger == 1) { + if (_lineMoving) + _scene->_sequences.addTimer(1, 1); + else { + _game._player._visible = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 4); + int idx = _scene->_dynamicHotspots.add(NOUN_FISHING_LINE, VERB_WALKTO, _globals._sequenceIndexes[7], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(26, 153), FACING_NORTHEAST); + _game._objects.removeFromInventory(OBJ_FISHING_LINE, 1); + _handingLine = false; + _lineMoving = true; + _globals[kLineStatus] = 3; + _game._player._stepEnabled = true; + } + } + } + } + } else if (_action.isAction(VERB_LOOK, NOUN_STREET) || _action._lookFlag) { + if (_globals[kLineStatus] == 2) + _vm->_dialogs->show(51110); + else { + if (_globals[kLineStatus] == 3) + _vm->_dialogs->show(51111); + else + _vm->_dialogs->show(51112); + } + } else if (_action.isAction(VERB_LOOK, NOUN_CAR)) + _vm->_dialogs->show(51113); + else if (_action.isAction(VERB_LOOK, NOUN_SIDEWALK)) + _vm->_dialogs->show(51114); + else if (_action.isAction(VERB_WALK_DOWN, NOUN_SIDEWALK_TO_EAST) || _action.isAction(VERB_WALK_DOWN, NOUN_SIDEWALK_TO_WEST) || _action.isAction(VERB_WALK_DOWN, NOUN_STREET_TO_EAST)) + _vm->_dialogs->show(51115); + else if (_action.isAction(VERB_LOOK, NOUN_PLEASURE_DOME)) + _vm->_dialogs->show(51116); + else if (_action.isAction(VERB_LOOK, NOUN_TICKET_BOOTH)) + _vm->_dialogs->show(51117); + else if (_action.isAction(VERB_LOOK, NOUN_DOME_ENTRANCE)) + _vm->_dialogs->show(51118); + else if (_action.isAction(VERB_UNLOCK, NOUN_PADLOCK_KEY, NOUN_DOME_ENTRANCE) || _action.isAction(VERB_UNLOCK, NOUN_DOOR_KEY, NOUN_DOME_ENTRANCE)) + _vm->_dialogs->show(51119); + else if ( (_action.isAction(VERB_PUT) || _action.isAction(VERB_THROW)) + && (_action.isObject(NOUN_TIMEBOMB) || _action.isObject(NOUN_BOMB) || _action.isObject(NOUN_BOMBS)) + && _action.isObject(NOUN_DOME_ENTRANCE)) + _vm->_dialogs->show(51120); + else if (_action.isAction(VERB_LOOK, NOUN_RESTAURANT)) { + if (_globals[kBoatRaised]) + _vm->_dialogs->show(51121); + else + _vm->_dialogs->show(51128); + } else if (_action.isAction(VERB_LOOK, NOUN_PORTHOLE)) + _vm->_dialogs->show(51122); + else if (_action.isAction(VERB_LOOK, NOUN_FISHING_LINE) && (_action._mainObjectSource == 4) && (_globals[kLineStatus] == 2)) + _vm->_dialogs->show(51126); + else if (_action.isAction(VERB_LOOK, NOUN_FISHING_LINE) && (_action._mainObjectSource == 4) && (_globals[kLineStatus] == 3)) + _vm->_dialogs->show(51133); + else if (_action.isAction(VERB_LOOK, NOUN_STATUE)) + _vm->_dialogs->show(51127); + else if (_action.isAction(VERB_LOOK, NOUN_BOAT)) + if (_globals[kBoatRaised]) + _vm->_dialogs->show(51123); + else if (_globals[kLineStatus] != 3) + _vm->_dialogs->show(51124); + else + _vm->_dialogs->show(51125); + else if (_action.isAction(VERB_LOOK, NOUN_FISHING_LINE) && (_globals[kLineStatus] == 3)) + _vm->_dialogs->show(51125); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene512::Scene512(MADSEngine *vm) : Scene5xx(vm) { + _fishingRodHotspotId = -1; + _keyHotspotId = -1; +} + +void Scene512::synchronize(Common::Serializer &s) { + Scene5xx::synchronize(s); + + s.syncAsSint16LE(_fishingRodHotspotId); + s.syncAsSint16LE(_keyHotspotId); +} + +void Scene512::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_FISHING_ROD); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_PADLOCK_KEY); + _scene->addActiveVocab(NOUN_REGISTER_DRAWER); +} + +void Scene512::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('r', -1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMRC_9"); + _globals._spriteIndexes[8] = _scene->_sprites.addSprites("*RXMRC_8"); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('x', 2)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('x', 3)); + + if (_game._objects[OBJ_FISHING_ROD]._roomNumber == _scene->_currentSceneId) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 0, 0, 0); + _fishingRodHotspotId = _scene->_dynamicHotspots.add(NOUN_FISHING_ROD, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_fishingRodHotspotId, Common::Point(199, 101), FACING_NORTHEAST); + } + + if (!_game._visitedScenes._sceneRevisited) + _globals[kRegisterOpen] = false; + + _scene->_hotspots.activate(NOUN_PADLOCK_KEY, false); + if (_game._difficulty == DIFFICULTY_EASY) { + if (_game._objects[OBJ_PADLOCK_KEY]._roomNumber == _scene->_currentSceneId) { + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 10, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 3); + _keyHotspotId = _scene->_dynamicHotspots.add(NOUN_PADLOCK_KEY, VERB_WALKTO, _globals._sequenceIndexes[6], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_keyHotspotId, Common::Point(218, 152), FACING_NORTHEAST); + } + if (_globals[kRegisterOpen]) { + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_hotspots.activate(NOUN_PADLOCK_KEY, false); + } + } else if (_globals[kRegisterOpen]) { + if (_game._objects[OBJ_PADLOCK_KEY]._roomNumber == _scene->_currentSceneId) { + _scene->_hotspots.activate(NOUN_PADLOCK_KEY, true); + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 3); + } else { + _scene->_hotspots.activate(NOUN_PADLOCK_KEY, false); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + } + } else + _scene->_hotspots.activate(NOUN_PADLOCK_KEY, false); + + if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(144, 152); + _game._player._facing = FACING_NORTHEAST; + } + + sceneEntrySound(); +} + +void Scene512::actions() { + if (_action.isAction(VERB_WALK, NOUN_OUTSIDE)) + _scene->_nextSceneId = 511; + else if (_action.isAction(VERB_TAKE, NOUN_FISHING_ROD)) { + if (_game._trigger || !_game._objects.isInInventory(OBJ_FISHING_ROD)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 5, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _vm->_sound->command(9); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_dynamicHotspots.remove(_fishingRodHotspotId); + _game._objects.addToInventory(OBJ_FISHING_ROD); + _vm->_dialogs->showItem(OBJ_FISHING_ROD, 51217); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } + } else if (_action.isAction(VERB_OPEN, NOUN_CASH_REGISTER)) { + if (!_globals[kRegisterOpen]) { + switch (_game._trigger) { + case 0: + _vm->_dialogs->show(51236); + _game._player._stepEnabled = false; + _game._player._facing = FACING_NORTH; + _scene->_sequences.addTimer(15, 1); + break; + + case 1: + _game._player._visible = false; + _globals._sequenceIndexes[8] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[8], false, 9, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 1, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[8]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[8]); + _game._player._visible = true; + _scene->_sequences.addTimer(30, 3); + break; + + case 3: + _game._player._facing = FACING_NORTHEAST; + if (!_game._objects.isInRoom(OBJ_PADLOCK_KEY) || (_game._difficulty == DIFFICULTY_EASY)) { + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 4); + } else { + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 5); + } + _vm->_sound->command(23); + break; + + case 4: + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.addTimer(60, 6); + break; + + case 5: + _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 14, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 3); + _scene->_hotspots.activate(NOUN_PADLOCK_KEY, true); + _scene->_sequences.addTimer(60, 6); + break; + + case 6: + _globals[kRegisterOpen] = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else + _vm->_dialogs->show(51239); + } else if (_action.isAction(VERB_CLOSE, NOUN_CASH_REGISTER) && _globals[kRegisterOpen]) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + _game._player._visible = true; + if (!_game._objects.isInRoom(OBJ_PADLOCK_KEY) || _game._difficulty == DIFFICULTY_EASY) { + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } else { + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 3); + _scene->_hotspots.activate(NOUN_PADLOCK_KEY, false); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + + case 2: + _globals[kRegisterOpen] = false; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_TAKE, NOUN_PADLOCK_KEY)) { + if (_game._trigger || !_game._objects.isInInventory(OBJ_PADLOCK_KEY)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + + int endVal; + if (_game._player._playerPos == Common::Point(218, 152)) + endVal = 3; + else + endVal = 2; + + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, endVal); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, endVal, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + if (_game._player._playerPos == Common::Point(218, 152)) { + _scene->_sequences.remove(_globals._sequenceIndexes[6]); + _scene->_dynamicHotspots.remove(_keyHotspotId); + } else { + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_hotspots.activate(NOUN_PADLOCK_KEY, false); + } + _vm->_sound->command(9); + _game._objects.addToInventory(OBJ_PADLOCK_KEY); + _vm->_dialogs->showItem(OBJ_PADLOCK_KEY, 51226); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } + } else if (_action._lookFlag) + _vm->_dialogs->show(51225); + else if (_action.isAction(VERB_LOOK, NOUN_PADLOCK_KEY) && _game._objects.isInRoom(OBJ_PADLOCK_KEY)) + _vm->_dialogs->show(51215); + else if (_action.isAction(VERB_LOOK, NOUN_FISHING_ROD) && (_scene->_activeAnimation->getCurrentFrame() == 4)) + _vm->_dialogs->show(51216); + else if (_action.isAction(VERB_LOOK, NOUN_SHIPS_WHEEL)) + _vm->_dialogs->show(51218); + else if (_action.isAction(VERB_TAKE, NOUN_SHIPS_WHEEL)) + _vm->_dialogs->show(51219); + else if (_action.isAction(VERB_LOOK, NOUN_PORTHOLE) || _action.isAction(VERB_PEER_THROUGH, NOUN_PORTHOLE)) + _vm->_dialogs->show(51220); + else if (_action.isAction(VERB_LOOK, NOUN_TABLE)) + _vm->_dialogs->show(51221); + else if (_action.isAction(VERB_LOOK, NOUN_STARFISH)) + _vm->_dialogs->show(51222); + else if (_action.isAction(VERB_TAKE, NOUN_STARFISH)) + _vm->_dialogs->show(51223); + else if (_action.isAction(VERB_LOOK, NOUN_OUTSIDE)) + _vm->_dialogs->show(51224); + else if (_action.isAction(VERB_LOOK, NOUN_POSTER)) + _vm->_dialogs->show(51227); + else if (_action.isAction(VERB_TAKE, NOUN_POSTER)) + _vm->_dialogs->show(51228); + else if (_action.isAction(VERB_LOOK, NOUN_TROPHY)) { + if (_game._visitedScenes.exists(604)) + _vm->_dialogs->show(51229); + else + _vm->_dialogs->show(51230); + } if (_action.isAction(VERB_LOOK, NOUN_CHAIR)) + _vm->_dialogs->show(51231); + else if (_action.isAction(VERB_LOOK, NOUN_ROPE)) + _vm->_dialogs->show(51232); + else if (_action.isAction(VERB_TAKE, NOUN_ROPE)) + _vm->_dialogs->show(51233); + else if (_action.isAction(VERB_LOOK, NOUN_LAMP)) + _vm->_dialogs->show(51234); + else if (_action.isAction(VERB_LOOK, NOUN_COUNTER)) + _vm->_dialogs->show(51235); + else if (_action.isAction(VERB_LOOK, NOUN_ICE_CHESTS)) + _vm->_dialogs->show(51237); + else if (_action.isAction(VERB_OPEN, NOUN_ICE_CHESTS)) + _vm->_dialogs->show(51238); + else if (_action.isAction(VERB_LOOK, NOUN_CASH_REGISTER)) { + if (!_globals[kRegisterOpen]) + _vm->_dialogs->show(51212); + else if (_game._objects.isInRoom(OBJ_PADLOCK_KEY)) + _vm->_dialogs->show(51214); + else + _vm->_dialogs->show(51213); + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene513::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_ELEVATOR_DOOR); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene513::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXCD_9"); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXMRC_9"); + + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); + + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + if ((_scene->_priorSceneId == 751) || (_scene->_priorSceneId == 701)) { + _game._player._playerPos = Common::Point(296, 147); + _game._player._facing = FACING_WEST; + _game._player._stepEnabled = false; + _scene->_sequences.addTimer(15, 80); + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(63, 149); + _game._player._facing = FACING_NORTHEAST; + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _scene->loadAnimation(formAnimName('R', 1), 70); + } + + sceneEntrySound(); + + if (_scene->_roomChanged) + _game._objects.addToInventory(OBJ_SECURITY_CARD); + + _game.loadQuoteSet(0x278, 0); +} + +void Scene513::step() { + switch (_game._trigger) { + case 80: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); + _vm->_sound->command(24); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 81); + break; + + case 81: + _game._player.walk(Common::Point(265, 152), FACING_WEST); + _scene->_sequences.addTimer(120, 82); + break; + + case 82: + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); + _vm->_sound->command(25); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 83); + break; + + case 83: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); + _game._player._stepEnabled = true; + break; + + default: + break; + } + + switch (_game._trigger) { + case 70: + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + _scene->_sequences.addTimer(6, 71); + break; + + case 71: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + break; + + case 72: + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _game._player._stepEnabled = true; + break; + + default: + break; + } +} + +void Scene513::actions() { + if (_action.isAction(VERB_GET_INTO, NOUN_CAR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[1]; + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], syncIdx); + _scene->_sequences.addTimer(6, 2); + } + break; + + case 2: + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 10, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: { + int syncIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _scene->_nextSceneId = 504; + } + break; + + default: + break; + } + } else if (_action.isAction(VERB_PUT, NOUN_ID_CARD, NOUN_CARD_SLOT) || _action.isAction(VERB_PUT, NOUN_FAKE_ID, NOUN_CARD_SLOT)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[4]); + _game._player._visible = true; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); + _vm->_sound->command(24); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x278)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 2: + _game._player.walk(Common::Point(296, 147), FACING_WEST); + _scene->_sequences.addTimer(120, 3); + break; + + case 3: + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); + _vm->_sound->command(25); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 4); + break; + + case 4: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); + _game._player._stepEnabled = true; + if (_globals[kCityFlooded]) + _scene->_nextSceneId = 701; + else + _scene->_nextSceneId = 751; + + break; + + default: + break; + } + } else if ((_action._lookFlag) || _action.isAction(VERB_LOOK, NOUN_STREET)) + _vm->_dialogs->show(51318); + else if (_action.isAction(VERB_LOOK, NOUN_ELEVATOR)) + _vm->_dialogs->show(51310); + else if (_action.isAction(VERB_LOOK, NOUN_ELEVATOR_DOOR)) + _vm->_dialogs->show(51311); + else if (_action.isAction(VERB_LOOK, NOUN_CARD_SLOT)) + _vm->_dialogs->show(51312); + else if (_action.isAction(VERB_LOOK, NOUN_HANDICAP_SIGN)) + _vm->_dialogs->show(51313); + else if (_action.isAction(VERB_LOOK, NOUN_BIKE_RACK)) + _vm->_dialogs->show(51314); + else if (_action.isAction(VERB_LOOK, NOUN_BUILDING)) + _vm->_dialogs->show(51315); + else if (_action.isAction(VERB_LOOK, NOUN_SIGN)) + _vm->_dialogs->show(51316); + else if (_action.isAction(VERB_LOOK, NOUN_STREET_TO_WEST) || _action.isAction(VERB_WALK_DOWN, NOUN_STREET_TO_WEST)) + _vm->_dialogs->show(51317); + else if (_action.isAction(VERB_OPEN, NOUN_ELEVATOR_DOOR) || _action.isAction(VERB_OPEN, NOUN_ELEVATOR)) + _vm->_dialogs->show(51319); + else if (_action.isAction(VERB_LOOK, NOUN_CAR)) + _vm->_dialogs->show(51321); + else if (_action.isAction(VERB_LOOK, NOUN_BRICK_WALL)) + _vm->_dialogs->show(51322); + else if (_action.isAction(VERB_PUT, NOUN_SECURITY_CARD, NOUN_CARD_SLOT)) + _vm->_dialogs->show(51320); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene515::setup() { + _game._player._spritesPrefix = ""; + setAAName(); +} + +void Scene515::enter() { + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->_sequences.addTimer(30, 70); + + sceneEntrySound(); +} + +void Scene515::step() { + if (_game._trigger == 70) + _scene->loadAnimation(formAnimName('A', -1), 71); + else if (_game._trigger == 71) + _scene->_nextSceneId = 508; +} + +/*------------------------------------------------------------------------*/ + +void Scene551::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene551::enter() { + if (_globals[kSexOfRex] == REX_MALE) + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 0)); + else + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 1)); + + if (_scene->_priorSceneId == 501) + _game._player._playerPos = Common::Point(18, 130); + else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(124, 119); + _game._player._facing = FACING_NORTH; + } + + if (_globals[kTeleporterCommand]) { + _game._player._visible = false; + _game._player._stepEnabled = false; + + char sepChar; + if (_globals[kSexOfRex] == REX_MALE) + sepChar = 'e'; + else + sepChar = 'u'; + + int suffixNum; + int trigger; + + switch (_globals[kTeleporterCommand]) { + case 1: + suffixNum = 3; + trigger = 75; + _globals[kTeleporterUnderstood] = true; + break; + + case 2: + suffixNum = 1; + trigger = 80; + break; + + case 4: + suffixNum = 2; + trigger = 90; + break; + + default: + trigger = 0; + suffixNum = 0; + } + + _globals[kTeleporterCommand] = 0; + + if (suffixNum > 0) + _scene->loadAnimation(formAnimName(sepChar, suffixNum), trigger); + else { + _game._player._visible = true; + _game._player._stepEnabled = true; + } + } + + sceneEntrySound(); +} + +void Scene551::step() { + switch (_game._trigger) { + case 75: + _game._player._stepEnabled = true; + _game._player._visible = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + break; + + case 80: + _globals[kTeleporterCommand] = 1; + _scene->_nextSceneId = _globals[kTeleporterDestination]; + _scene->_reloadSceneFlag = true; + break; + + case 90: + if (_globals[kSexOfRex] == REX_MALE) { + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 8); + } else { + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8); + } + _vm->_sound->command(28); + _scene->_sequences.addTimer(60, 91); + break; + + case 91: + _scene->_reloadSceneFlag = true; + break; + + default: + break; + } +} + +void Scene551::preActions() { + if (_action.isAction(VERB_WALK_DOWN) && (_action.isObject(NOUN_STREET_TO_WEST) || _action.isObject(NOUN_SIDEWALK_TO_WEST))) + _game._player._walkOffScreenSceneId = 501; +} + +void Scene551::actions() { + if (_action.isAction(VERB_STEP_INTO, NOUN_TELEPORTER)) + _scene->_nextSceneId = 502; + else if ((_action._lookFlag)) + _vm->_dialogs->show(55117); + else if (_action.isAction(VERB_LOOK, NOUN_SKELETON)) + _vm->_dialogs->show(55110); + else if (_action.isAction(VERB_LOOK, NOUN_ELEVATOR_SHAFT)) + _vm->_dialogs->show(55111); + else if (_action.isAction(VERB_WALKTO, NOUN_ELEVATOR_SHAFT)) + _vm->_dialogs->show(55112); + else if (_action.isAction(VERB_LOOK, NOUN_BUILDING)) + _vm->_dialogs->show(55113); + else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER)) + _vm->_dialogs->show(55114); + else if (_action.isAction(VERB_LOOK, NOUN_BUILDING)) + _vm->_dialogs->show(55115); + else if (_action.isAction(VERB_LOOK, NOUN_SIDEWALK_TO_WEST)) { + if (_game._visitedScenes.exists(505)) + _vm->_dialogs->show(55116); + else + _vm->_dialogs->show(55115); + } else if (_action.isAction(VERB_LOOK, NOUN_SIDEWALK)) + _vm->_dialogs->show(55118); + else if (_action.isAction(VERB_LOOK, NOUN_EQUIPMENT_OVERHEAD)) + _vm->_dialogs->show(55119); + else if (_action.isAction(VERB_LOOK, NOUN_RAILING)) + _vm->_dialogs->show(55120); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +} // End of namespace Nebular +} // End of namespace MADS diff --git a/engines/mads/nebular/nebular_scenes5.h b/engines/mads/nebular/nebular_scenes5.h new file mode 100644 index 0000000000..2face26508 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes5.h @@ -0,0 +1,254 @@ +/* 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. + * + */ + +#ifndef MADS_NEBULAR_SCENES5_H +#define MADS_NEBULAR_SCENES5_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" + +namespace MADS { + +namespace Nebular { + +class Scene5xx : public NebularScene { +protected: + /** + * Plays an appropriate sound when entering a scene + */ + void setAAName(); + + /** + * Updates the prefix used for getting player sprites for the scene + */ + void setPlayerSpritesPrefix(); + + void sceneEntrySound(); + +public: + Scene5xx(MADSEngine *vm) : NebularScene(vm) {} +}; + +class Scene501 : public Scene5xx{ +private: + int _mainSequenceId; + int _mainSpriteId; + int _doorHotspotid; + bool _rexPunched; + + void handleSlotActions(); + +public: + Scene501(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene502 : public SceneTeleporter { +public: + Scene502(MADSEngine *vm) : SceneTeleporter(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene503 : public Scene5xx{ +private: + int _detonatorHotspotId; + +public: + Scene503(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene504 : public Scene5xx{ +private: + int _carAnimationMode; + int _carFrame; + +public: + Scene504(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene505 : public Scene5xx{ +private: + int _frame; + int _nextButtonId; + int _homeSelectedId; + int _selectedId; + int _activeCars; + + int _carLocations[9]; + +public: + Scene505(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene506 : public Scene5xx{ +private: + Common::Point _doorPos; + Facing _heroFacing; + + int _doorDepth; + int _doorSpriteIdx; + int _doorSequenceIdx; + int _doorWord; + + bool _labDoorFl; + bool _firstDoorFl; + bool _actionFl; + + void handleDoorSequences(); + +public: + Scene506(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene507 : public Scene5xx{ +private: + int _penlightHotspotId; + +public: + Scene507(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene508 : public Scene5xx{ +private: + int _chosenObject; + + void handlePedestral(); + +public: + Scene508(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene511 : public Scene5xx{ +private: + bool _handingLine; + bool _lineMoving; + + int _lineAnimationMode; + int _lineFrame; + int _lineAnimationPosition; + +public: + Scene511(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene512 : public Scene5xx{ +private: + int _fishingRodHotspotId; + int _keyHotspotId; + +public: + Scene512(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene513 : public Scene5xx{ +public: + Scene513(MADSEngine *vm) : Scene5xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene515 : public Scene5xx{ +public: + Scene515(MADSEngine *vm) : Scene5xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions() {}; +}; + +class Scene551 : public Scene5xx{ +public: + Scene551(MADSEngine *vm) : Scene5xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; +} // End of namespace Nebular +} // End of namespace MADS + +#endif /* MADS_NEBULAR_SCENES5_H */ diff --git a/engines/mads/nebular/nebular_scenes6.cpp b/engines/mads/nebular/nebular_scenes6.cpp new file mode 100644 index 0000000000..eb85fa86e1 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes6.cpp @@ -0,0 +1,4743 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "mads/mads.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/nebular/nebular_scenes6.h" + +namespace MADS { + +namespace Nebular { + +void Scene6xx::setAAName() { + _game._aaName = Resources::formatAAName(5); +} + +void Scene6xx::setPlayerSpritesPrefix() { + _vm->_sound->command(5); + Common::String oldName = _game._player._spritesPrefix; + + if ((_scene->_nextSceneId == 605) || (_scene->_nextSceneId == 620)) + _game._player._spritesPrefix = ""; + else if (_globals[kSexOfRex] == REX_MALE) + _game._player._spritesPrefix = "RXM"; + else + _game._player._spritesPrefix = "ROX"; + + if (oldName != _game._player._spritesPrefix) + _game._player._spritesChanged = true; + + _game._player._scalingVelocity = true; + _vm->_palette->setEntry(16, 10, 63, 63); + _vm->_palette->setEntry(17, 10, 45, 45); +} + +void Scene6xx::sceneEntrySound() { + if (!_vm->_musicFlag) { + _vm->_sound->command(2); + return; + } + + switch (_scene->_nextSceneId) { + case 601: + case 602: + case 603: + case 604: + case 605: + case 607: + case 608: + case 609: + case 610: + case 612: + case 620: + _vm->_sound->command(29); + break; + case 611: + _vm->_sound->command(24); + break; + default: + break; + } +} + +/*------------------------------------------------------------------------*/ + +void Scene601::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_LASER_BEAM); + _scene->addActiveVocab(VERB_LOOK_AT); +} + +void Scene601::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('c', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXCD_4"); + + if (_globals[kLaserHoleIsThere]) { + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2); + _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_LOOK_AT, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + } + + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3); + + if (_scene->_priorSceneId == 504) { + _game._player._playerPos = Common::Point(73, 148); + _game._player._facing = FACING_WEST; + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3); + _scene->loadAnimation(formAnimName('R', 1), 70); + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(229, 129); + _game._player._facing = FACING_SOUTHWEST; + } + + sceneEntrySound(); +} + +void Scene601::step() { + switch (_game._trigger) { + case 70: + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + _scene->_sequences.addTimer(30, 71); + break; + + case 71: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + break; + + case 72: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3); + _game._player._stepEnabled = true; + break; + + default: + break; + } +} + +void Scene601::actions() { + if (_action.isAction(VERB_WALK_THROUGH, NOUN_ENTRANCE)) + _scene->_nextSceneId = 602; + else if (_action.isAction(VERB_GET_INSIDE, NOUN_CAR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], syncIdx); + _scene->_sequences.addTimer(6, 2); + } + break; + + case 2: + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 10, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: { + int syncIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _scene->_nextSceneId = 504; + } + break; + + default: + break; + } + } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_STREET)) { + if (!_globals[kLaserHoleIsThere]) + _vm->_dialogs->show(60110); + else + _vm->_dialogs->show(60111); + } else if (_action.isAction(VERB_LOOK, NOUN_CAR)) + _vm->_dialogs->show(60112); + else if (_action.isAction(VERB_LOOK, NOUN_PAPERS)) + _vm->_dialogs->show(60113); + else if (_action.isAction(VERB_LOOK, NOUN_BUILDING)) + _vm->_dialogs->show(60114); + else if (_action.isAction(VERB_WALK_DOWN, NOUN_STREET)) + _vm->_dialogs->show(60115); + else if (_action.isAction(VERB_LOOK, NOUN_BALCONY)) + _vm->_dialogs->show(60116); + else if (_action.isAction(VERB_LOOK, NOUN_ENTRANCE)) + _vm->_dialogs->show(60117); + else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(60118); + else if (_action.isAction(VERB_LOOK, NOUN_CITY)) + _vm->_dialogs->show(60119); + else if (_action.isAction(VERB_LOOK, NOUN_FOUNTAIN)) + _vm->_dialogs->show(60120); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene602::Scene602(MADSEngine *vm) : Scene6xx(vm) { + _lastSpriteIdx = -1; + _lastSequenceIdx = -1; + _cycleIndex = -1; + _safeMode = -1; +} + +void Scene602::synchronize(Common::Serializer &s) { + Scene6xx::synchronize(s); + + s.syncAsSint16LE(_lastSpriteIdx); + s.syncAsSint16LE(_lastSequenceIdx); + s.syncAsSint16LE(_cycleIndex); + s.syncAsSint16LE(_safeMode); +} + +void Scene602::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_SAFE); + _scene->addActiveVocab(NOUN_LASER_BEAM); +} + +void Scene602::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('h', -1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('l', 0)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RXMRC_9"); + + if (!_game._visitedScenes._sceneRevisited) + _globals[kSafeStatus] = 0; + + if (_globals[kLaserHoleIsThere]) { + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 9); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 9); + int idx = _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(80, 134), FACING_NORTHEAST); + _scene->changeVariant(1); + } else + _scene->_hotspots.activate(NOUN_HOLE, false); + + if (_globals[kSafeStatus] == 0) { + _lastSpriteIdx = _globals._spriteIndexes[2]; + _cycleIndex = -1; + } else if (_globals[kSafeStatus] == 1) { + _lastSpriteIdx = _globals._spriteIndexes[2]; + _cycleIndex = -2; + } else if (_globals[kSafeStatus] == 3) { + _lastSpriteIdx = _globals._spriteIndexes[3]; + _cycleIndex = -2; + } else { + _lastSpriteIdx = _globals._spriteIndexes[3]; + _cycleIndex = -1; + } + + _lastSequenceIdx = _scene->_sequences.startCycle(_lastSpriteIdx, false, _cycleIndex); + _scene->_sequences.setDepth(_lastSequenceIdx, 14); + int idx = _scene->_dynamicHotspots.add(NOUN_SAFE, VERB_WALKTO, _lastSequenceIdx, Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(185, 113), FACING_NORTHWEST); + + if (_game._objects.isInRoom(OBJ_DOOR_KEY)) { + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('k', -1)); + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 15); + if (_globals[kSafeStatus] == 0 || _globals[kSafeStatus] == 2) + _scene->_hotspots.activate(NOUN_DOOR_KEY, false); + } else + _scene->_hotspots.activate(NOUN_DOOR_KEY, false); + + if (_scene->_priorSceneId == 603) { + _game._player._playerPos = Common::Point(228, 126); + _game._player._facing = FACING_WEST; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(50, 127); + _game._player._facing = FACING_EAST; + } + + sceneEntrySound(); + _game.loadQuoteSet(0x2F1, 0x2F2, 0x2F3, 0); + + if (_scene->_roomChanged) { + _game._objects.addToInventory(OBJ_NOTE); + _game._objects.addToInventory(OBJ_REARVIEW_MIRROR); + _game._objects.addToInventory(OBJ_COMPACT_CASE); + } +} + +void Scene602::handleSafeActions() { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], true, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_SPRITE, 3, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 1: + if (_safeMode == 1 || _safeMode == 3) { + if (_globals[kSafeStatus] == 0 && _safeMode == 1) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2F1)); + _scene->_sequences.addTimer(120, 4); + } else { + _scene->_sequences.remove(_lastSequenceIdx); + if (_safeMode == 3) + _lastSpriteIdx = _globals._spriteIndexes[2]; + else + _lastSpriteIdx = _globals._spriteIndexes[3]; + + _lastSequenceIdx = _scene->_sequences.addSpriteCycle(_lastSpriteIdx, false, 12, 1, 0, 0); + _scene->_sequences.setDepth(_lastSequenceIdx, 14); + if (_game._objects[OBJ_DOOR_KEY]._roomNumber == _scene->_currentSceneId) + _scene->_hotspots.activate(NOUN_DOOR_KEY, true); + + _scene->_sequences.addSubEntry(_lastSequenceIdx, + SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + } else { + _scene->_sequences.remove(_lastSequenceIdx); + if (_globals[kSafeStatus] == 1) + _lastSpriteIdx = _globals._spriteIndexes[2]; + else + _lastSpriteIdx = _globals._spriteIndexes[3]; + + _lastSequenceIdx = _scene->_sequences.startReverseCycle(_lastSpriteIdx, false, 12, 1, 0, 0); + _scene->_sequences.setDepth(_lastSequenceIdx, 14); + if (_game._objects[OBJ_DOOR_KEY]._roomNumber == _scene->_currentSceneId) + _scene->_hotspots.activate(NOUN_DOOR_KEY, false); + + _scene->_sequences.addSubEntry(_lastSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + + case 2: { + int synxIdx = _lastSequenceIdx; + _lastSequenceIdx = _scene->_sequences.startCycle(_lastSpriteIdx, false, _cycleIndex); + _scene->_sequences.setDepth(_lastSequenceIdx, 14); + _scene->_sequences.updateTimeout(_lastSequenceIdx, synxIdx); + int idx = _scene->_dynamicHotspots.add(NOUN_SAFE, VERB_WALKTO, _lastSequenceIdx, Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(185, 113), FACING_NORTHWEST); + if (_safeMode == 3) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2F3)); + _scene->_sequences.addTimer(120, 4); + } else + _scene->_sequences.addTimer(60, 4); + break; + } + + case 3: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[5]); + _game._player._visible = true; + break; + + case 4: + if (_safeMode == 1) { + if (_globals[kSafeStatus] == 2) + _globals[kSafeStatus] = 3; + } else if (_safeMode == 2) { + if (_globals[kSafeStatus] == 3) + _globals[kSafeStatus] = 2; + else + _globals[kSafeStatus] = 0; + } else + _globals[kSafeStatus] = 1; + + _game._player._stepEnabled = true; + break; + + default: + break; + } +} + +void Scene602::actions() { + if (_action.isAction(VERB_WALK_THROUGH, NOUN_HALLWAY)) + _scene->_nextSceneId = 601; + else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY)) + _scene->_nextSceneId = 603; + else if (_action.isAction(VERB_OPEN, NOUN_SAFE) && ((_globals[kSafeStatus] == 0) || (_globals[kSafeStatus] == 2))) { + _safeMode = 1; + _cycleIndex = -2; + handleSafeActions(); + } else if (_action.isAction(VERB_CLOSE, NOUN_SAFE) && ((_globals[kSafeStatus] == 1) || (_globals[kSafeStatus] == 3))) { + _safeMode = 2; + _cycleIndex = -1; + handleSafeActions(); + } else if (_action.isAction(VERB_UNLOCK, NOUN_COMBINATION, NOUN_SAFE)) { + if ((_globals[kSafeStatus] == 0) && (_game._difficulty != DIFFICULTY_HARD)) { + _safeMode = 3; + _cycleIndex = -2; + handleSafeActions(); + } + } else if ((_action.isAction(VERB_PUT, NOUN_REARVIEW_MIRROR, NOUN_LASER_BEAM) || _action.isAction(VERB_PUT, NOUN_COMPACT_CASE, NOUN_LASER_BEAM) + || _action.isAction(VERB_REFLECT, NOUN_COMPACT_CASE, NOUN_LASER_BEAM) || _action.isAction(VERB_REFLECT, NOUN_REARVIEW_MIRROR, NOUN_LASER_BEAM)) && (_globals[kSafeStatus] == 0)) { + switch (_game._trigger) { + case 0: + _vm->_dialogs->show(60230); + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _scene->_sequences.remove(_lastSequenceIdx); + _scene->loadAnimation(formAnimName('L', 1), 1); + break; + + case 1: { + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + _lastSpriteIdx = _globals._spriteIndexes[3]; + _lastSequenceIdx = _scene->_sequences.startCycle(_lastSpriteIdx, false, -1); + _scene->_sequences.setDepth(_lastSequenceIdx, 14); + int idx = _scene->_dynamicHotspots.add(NOUN_SAFE, VERB_WALKTO, _lastSequenceIdx, Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(185, 113), FACING_NORTHWEST); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 9); + idx = _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(80, 134), FACING_NORTHEAST); + _scene->_sequences.addTimer(60, 2); + } + break; + + case 2: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2F2)); + _globals[kSafeStatus] = 2; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_TAKE, NOUN_DOOR_KEY) && (_game._trigger || _game._objects.isInRoom(OBJ_DOOR_KEY))) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], true, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_SPRITE, 3, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[6]); + _scene->_hotspots.activate(NOUN_DOOR_KEY, false); + _vm->_sound->command(9); + _game._objects.addToInventory(OBJ_DOOR_KEY); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[5]); + _game._player._visible = true; + _game._player._stepEnabled = true; + _vm->_dialogs->showItem(OBJ_DOOR_KEY, 835); + break; + + default: + break; + } + } else if (_action._lookFlag) + _vm->_dialogs->show(60210); + else if (_action.isAction(VERB_LOOK, NOUN_FLOOR)) + _vm->_dialogs->show(60211); + else if (_action.isAction(VERB_LOOK, NOUN_HALLWAY)) + _vm->_dialogs->show(60212); + else if (_action.isAction(VERB_LOOK, NOUN_TABLE)) + _vm->_dialogs->show(60213); + else if (_action.isAction(VERB_LOOK, NOUN_CHAIR) || _action.isAction(VERB_LOOK, NOUN_LOUNGE_CHAIR)) + _vm->_dialogs->show(60214); + else if (_action.isAction(VERB_LOOK, NOUN_NEON_LIGHTS)) + _vm->_dialogs->show(60215); + else if (_action.isAction(VERB_LOOK, NOUN_FIREPLACE)) + _vm->_dialogs->show(60216); + else if (_action.isAction(VERB_LOOK, NOUN_PICTURE)) + _vm->_dialogs->show(60217); + else if (_action.isAction(VERB_LOOK, NOUN_LAMP)) + _vm->_dialogs->show(60218); + else if (_action.isAction(VERB_LOOK, NOUN_MASKS)) + _vm->_dialogs->show(60219); + else if (_action.isAction(VERB_LOOK, NOUN_GLASS_BLOCK_WALL)) + _vm->_dialogs->show(60220); + else if (_action.isAction(VERB_LOOK, NOUN_DOORWAY)) + _vm->_dialogs->show(60221); + else if (_action.isAction(VERB_LOOK, NOUN_SAFE)) { + if (_globals[kSafeStatus] == 0) + _vm->_dialogs->show(60222); + else if (_globals[kSafeStatus] == 1) { + if (!_game._objects.isInRoom(OBJ_DOOR_KEY)) + _vm->_dialogs->show(60223); + else + _vm->_dialogs->show(60224); + } else if (_globals[kSafeStatus] == 2) + _vm->_dialogs->show(60234); + else if (_game._objects.isInRoom(OBJ_DOOR_KEY)) + _vm->_dialogs->show(60235); + else + _vm->_dialogs->show(60236); + } else if (_action.isAction(VERB_UNLOCK, NOUN_DOOR_KEY, NOUN_SAFE) || _action.isAction(VERB_UNLOCK, NOUN_PADLOCK_KEY, NOUN_SAFE)) + _vm->_dialogs->show(60225); + else if (_action.isAction(VERB_PULL, NOUN_SAFE)) + _vm->_dialogs->show(60226); + else if (_action.isAction(VERB_PUT, NOUN_FIREPLACE) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) + _vm->_dialogs->show(60227); + else if (_action.isAction(VERB_LOOK, NOUN_HOLE)) + _vm->_dialogs->show(60228); + else if (_action.isAction(VERB_LOOK, NOUN_LASER_BEAM)) + _vm->_dialogs->show(60229); + else if (_action.isAction(VERB_LOOK, NOUN_FLOWER_BOX)) + _vm->_dialogs->show(60231); + else if (_action.isAction(VERB_THROW, NOUN_BOMB, NOUN_SAFE) || _action.isAction(VERB_THROW, NOUN_BOMBS, NOUN_SAFE)) + _vm->_dialogs->show(60232); + else if (_action.isAction(VERB_PUT, NOUN_TIMEBOMB)) + _vm->_dialogs->show(60233); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene603::Scene603(MADSEngine *vm) : Scene6xx(vm) { + _compactCaseHotspotId = -1; + _noteHotspotId = -1; +} + +void Scene603::synchronize(Common::Serializer &s) { + Scene6xx::synchronize(s); + + s.syncAsSint16LE(_compactCaseHotspotId); + s.syncAsSint16LE(_noteHotspotId); +} + +void Scene603::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_COMPACT_CASE); + _scene->addActiveVocab(NOUN_NOTE); +} + +void Scene603::enter() { + if (_game._objects[OBJ_COMPACT_CASE]._roomNumber == _scene->_currentSceneId) { + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXMRD_3"); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', -1)); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _compactCaseHotspotId = _scene->_dynamicHotspots.add(NOUN_COMPACT_CASE, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_compactCaseHotspotId, Common::Point(250, 152), FACING_SOUTHEAST); + } + + if ((_game._difficulty != DIFFICULTY_HARD) && (_game._objects[OBJ_NOTE]._roomNumber == _scene->_currentSceneId)) { + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXMRC_9"); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('p', -1)); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 14); + _noteHotspotId = _scene->_dynamicHotspots.add(NOUN_NOTE, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_noteHotspotId, Common::Point(242, 118), FACING_NORTHEAST); + } + + if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(113, 134); + + sceneEntrySound(); +} + +void Scene603::actions() { + if (_action.isAction(VERB_WALK_TOWARDS, NOUN_LIVINGROOM)) + _scene->_nextSceneId = 602; + else if (_action.isAction(VERB_TAKE, NOUN_COMPACT_CASE)) { + if ( _game._trigger || !_game._objects.isInInventory(OBJ_COMPACT_CASE)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 5); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 5, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _vm->_sound->command(9); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_dynamicHotspots.remove(_compactCaseHotspotId); + _game._objects.addToInventory(OBJ_COMPACT_CASE); + _vm->_dialogs->showItem(OBJ_COMPACT_CASE, 60330); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[4]); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } + } else if (_action.isAction(VERB_TAKE, NOUN_NOTE)) { + if ( _game._trigger || !_game._objects.isInInventory(OBJ_NOTE)) { + if (_game._trigger == 0) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 1); + } else if (_game._trigger == 1) { + _vm->_sound->command(9); + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _scene->_dynamicHotspots.remove(_noteHotspotId); + _game._objects.addToInventory(OBJ_NOTE); + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._visible = true; + _game._player._stepEnabled = true; + } + } + } else if (_action._lookFlag) + _vm->_dialogs->show(60310); + else if (_action.isAction(VERB_LOOK, NOUN_BED)) + _vm->_dialogs->show(60311); + else if (_action.isAction(VERB_LOOK, NOUN_WIG_STAND)) + _vm->_dialogs->show(60312); + else if (_action.isAction(VERB_TAKE, NOUN_WIG_STAND)) + _vm->_dialogs->show(60313); + else if (_action.isAction(VERB_LOOK, NOUN_REVIEW)) + _vm->_dialogs->show(60314); + else if (_action.isAction(VERB_LOOK, NOUN_SOUVENIR_TICKETS)) + _vm->_dialogs->show(60315); + else if (_action.isAction(VERB_LOOK, NOUN_PHOTOGRAPH)) + _vm->_dialogs->show(60316); + else if (_action.isAction(VERB_LOOK, NOUN_LAMP)) + _vm->_dialogs->show(60317); + else if (_action.isAction(VERB_LOOK, NOUN_DIRECTORS_SLATE) || _action.isAction(VERB_LOOK, NOUN_CROP) || _action.isAction(VERB_LOOK, NOUN_MEGAPHONE)) + _vm->_dialogs->show(60318); + else if (_action.isAction(VERB_LOOK, NOUN_SNAPSHOT)) + _vm->_dialogs->show(60319); + else if (_action.isAction(VERB_TAKE, NOUN_SNAPSHOT)) + _vm->_dialogs->show(60320); + else if (_action.isAction(VERB_LOOK, NOUN_PERFUME)) + _vm->_dialogs->show(60321); + else if (_action.isAction(VERB_TAKE, NOUN_PERFUME)) + _vm->_dialogs->show(60322); + else if (_action.isAction(VERB_TAKE, NOUN_NOTE)) + _vm->_dialogs->show(60323); + else if (_action.isAction(VERB_LOOK, NOUN_NOTE)) { + if (_game._objects[OBJ_NOTE]._roomNumber == _scene->_currentSceneId) + _vm->_dialogs->show(60324); + } else if (_action.isAction(VERB_LOOK, NOUN_CORNER_TABLE)) { + if (_game._objects[OBJ_NOTE]._roomNumber == _scene->_currentSceneId) + _vm->_dialogs->show(60326); + else + _vm->_dialogs->show(60325); + } else if (_action.isAction(VERB_LOOK, NOUN_VANITY)) { + if (_game._objects[OBJ_COMPACT_CASE]._roomNumber == _scene->_currentSceneId) + _vm->_dialogs->show(60327); + else + _vm->_dialogs->show(60328); + } else if (_action.isAction(VERB_LOOK, NOUN_COMPACT_CASE) && (_action._mainObjectSource == 4)) + _vm->_dialogs->show(60329); + // For the next two checks, the second part of the check wasn't surrounded par parenthesis, which was obviously wrong + else if (_action.isAction(VERB_LOOK) && (_action.isObject(NOUN_BRA) || _action.isObject(NOUN_BOA) || _action.isObject(NOUN_SLIP))) + _vm->_dialogs->show(60331); + else if (_action.isAction(VERB_TAKE) && (_action.isObject(NOUN_BRA) || _action.isObject(NOUN_BOA) || _action.isObject(NOUN_SLIP))) + _vm->_dialogs->show(60332); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene604::Scene604(MADSEngine *vm) : Scene6xx(vm) { + _timebombHotspotId = -1; + _bombMode = -1; + _monsterFrame = -1; + + _monsterTimer = 0; + + _monsterActive = false; + _animationActiveFl = false; +} + +void Scene604::synchronize(Common::Serializer &s) { + Scene6xx::synchronize(s); + + s.syncAsSint16LE(_timebombHotspotId); + s.syncAsSint16LE(_bombMode); + s.syncAsSint16LE(_monsterFrame); + + s.syncAsUint32LE(_monsterTimer); + + s.syncAsByte(_monsterActive); + s.syncAsByte(_animationActiveFl); +} + +void Scene604::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_SEA_MONSTER); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_TIMEBOMB); +} + +void Scene604::enter() { + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('c', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXCD_9"); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(Resources::formatName(620, 'b', 0, EXT_SS, "")); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RXMRC_9"); + + if (_globals[kTimebombStatus] == 1) { + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, -1); + _timebombHotspotId = _scene->_dynamicHotspots.add(NOUN_TIMEBOMB, VERB_WALKTO, _globals._sequenceIndexes[6], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_timebombHotspotId, Common::Point(166, 118), FACING_NORTHEAST); + } + + if (_scene->_roomChanged) + _game._objects.addToInventory(OBJ_TIMEBOMB); + + _vm->_palette->setEntry(252, 63, 37, 26); + _vm->_palette->setEntry(253, 45, 24, 17); + _animationActiveFl = false; + + if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(72, 149); + _game._player._facing = FACING_NORTHEAST; + _game._player._visible = false; + _game._player._stepEnabled = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->loadAnimation(formAnimName('R', 1), 70); + _animationActiveFl = true; + } else { + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + } + + _monsterTimer = _scene->_frameStartTime; + _monsterActive = false; + + sceneEntrySound(); + _game.loadQuoteSet(0x2E7, 0x2E8, 0x2E9, 0x2EA, 0x2EB, 0x2EC, 0x2ED, 0x2EE, 0x2EF, 0x2F0, 0); +} + +void Scene604::step() { + switch (_game._trigger) { + case 70: + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + _scene->_sequences.addTimer(30, 71); + break; + + case 71: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + break; + + case 72: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _game._player._stepEnabled = true; + _animationActiveFl = false; + break; + + default: + break; + } + + if (_monsterActive && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _monsterFrame) { + _monsterFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextMonsterFrame = -1; + + switch (_monsterFrame) { + case 50: + case 137: + case 174: { + int randVal = _vm->getRandomNumber(1, 1000); + if ((randVal <= 450) && (_game._player._special)) { + if (_game._player._special == 1) + nextMonsterFrame = 50; + else if (_game._player._special == 2) + nextMonsterFrame = 84; + else + nextMonsterFrame = 137; + } else if (randVal <= 150) + nextMonsterFrame = 50; + else if (randVal <= 300) + nextMonsterFrame = 84; + else if (randVal <= 450) + nextMonsterFrame = 137; + else if (randVal < 750) + nextMonsterFrame = 13; + else + nextMonsterFrame = 114; + + } + break; + + case 84: + nextMonsterFrame = 14; + break; + + default: + break; + } + + if ((nextMonsterFrame >= 0) && (nextMonsterFrame != _monsterFrame)) { + _scene->_activeAnimation->setCurrentFrame(nextMonsterFrame); + _monsterFrame = nextMonsterFrame; + } + } + } + + if ((!_monsterActive && !_animationActiveFl) && (_scene->_frameStartTime > (_monsterTimer + 4))) { + _monsterTimer = _scene->_frameStartTime; + if ((_vm->getRandomNumber(1, 1000) < 25) || !_game._visitedScenes._sceneRevisited) { + _monsterActive = true; + _scene->freeAnimation(); + _scene->loadAnimation(formAnimName('m', -1)); + } + } +} + +void Scene604::handleBombActions() { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 9, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + if (_bombMode == 1) + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_SPRITE, 3, 1); + else + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_SPRITE, 3, 2); + + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 1: + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, -1); + _timebombHotspotId = _scene->_dynamicHotspots.add(NOUN_TIMEBOMB, VERB_WALKTO, _globals._sequenceIndexes[6], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_timebombHotspotId, Common::Point(166, 118), FACING_NORTHEAST); + _game._objects.setRoom(OBJ_TIMEBOMB, _scene->_currentSceneId); + break; + + case 2: + _scene->_sequences.remove(_globals._sequenceIndexes[6]); + _scene->_dynamicHotspots.remove(_timebombHotspotId); + _game._objects.addToInventory(OBJ_TIMEBOMB); + break; + + case 3: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[5]); + _game._player._visible = true; + _game._player._stepEnabled = true; + if (_bombMode == 1) { + _vm->_dialogs->show(60421); + _globals[kTimebombStatus] = TIMEBOMB_ACTIVATED; + _globals[kTimebombTimer] = 0; + } else { + _vm->_dialogs->show(60423); + _globals[kTimebombStatus] = TIMEBOMB_DEACTIVATED; + _globals[kTimebombTimer] = 0; + } + break; + + default: + break; + } +} + +void Scene604::actions() { + if (_action.isAction(VERB_GET_INSIDE, NOUN_CAR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], syncIdx); + _scene->_sequences.addTimer(6, 2); + } + break; + + case 2: + _game._player._visible = false; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: { + int syncIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx); + _scene->_nextSceneId = 504; + } + break; + + default: + break; + } + } else if ((_action.isAction(VERB_PUT, NOUN_LEDGE) || _action.isAction(VERB_PUT, NOUN_VIEWPORT) || _action.isAction(VERB_THROW, NOUN_VIEWPORT)) + && (_action.isObject(NOUN_BOMB) || _action.isObject(NOUN_BOMBS))) + _vm->_dialogs->show(60420); + else if (_action.isAction(VERB_PUT, NOUN_TIMEBOMB, NOUN_LEDGE) || _action.isAction(VERB_PUT, NOUN_TIMEBOMB, NOUN_VIEWPORT)) { + _bombMode = 1; + if ((_game._difficulty == DIFFICULTY_HARD) || _globals[kWarnedFloodCity]) + handleBombActions(); + else if ((_game._objects.isInInventory(OBJ_POLYCEMENT) && _game._objects.isInInventory(OBJ_CHICKEN)) + && ((_globals[kLineStatus] == LINE_TIED) || ((_game._difficulty == DIFFICULTY_EASY) && (!_globals[kBoatRaised])))) + handleBombActions(); + else if (_game._difficulty == DIFFICULTY_EASY) + _vm->_dialogs->show(60424); + else { + _vm->_dialogs->show(60425); + _globals[kWarnedFloodCity] = true; + } + } else if (_action.isAction(VERB_TAKE, NOUN_TIMEBOMB)) { + if (_game._trigger || !_game._objects.isInInventory(OBJ_TIMEBOMB)) { + _bombMode = 2; + handleBombActions(); + } + } else if (_action._lookFlag) + _vm->_dialogs->show(60411); + else if (_action.isAction(VERB_LOOK, NOUN_VIEWPORT)) { + if (_monsterActive) { + _vm->_dialogs->show(60413); + } else { + _vm->_dialogs->show(60412); + } + } else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(60414); + else if (_action.isAction(VERB_LOOK, NOUN_VENT)) + _vm->_dialogs->show(60415); + else if (_action.isAction(VERB_LOOK, NOUN_INDICATOR)) + _vm->_dialogs->show(60416); + else if (_action.isAction(VERB_LOOK, NOUN_SCULPTURE)) + _vm->_dialogs->show(60417); + else if (_action.isAction(VERB_LOOK, NOUN_CAR)) + _vm->_dialogs->show(60418); + else if (_action.isAction(VERB_LOOK, NOUN_FOUNTAIN)) + _vm->_dialogs->show(60419); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene605::setup() { + _game._player._spritesPrefix = ""; + setAAName(); +} + +void Scene605::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('r', -1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('b', -1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('l', -1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('p', -1)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('n', -1)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('f', -1)); + + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 15, 0, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 17, 0, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 14, 0, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 13, 0, 0, 0); + _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 17, 0, 0, 0); + _globals._sequenceIndexes[6] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[6], false, 18, 0, 0, 0); + + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->_sequences.addTimer(600, 70); + _scene->_userInterface.setup(kInputLimitedSentences); + sceneEntrySound(); + _vm->_sound->command(22); +} + +void Scene605::step() { + if (_game._trigger == 70) { + _vm->_sound->command(23); + if (_globals[kResurrectRoom] >= 700) + _vm->_dialogs->show(60598); + else + _vm->_dialogs->show(60599); + + _scene->_nextSceneId = _globals[kResurrectRoom]; + } +} + +void Scene605::actions() { + return; +} + +/*------------------------------------------------------------------------*/ + +Scene607::Scene607(MADSEngine *vm) : Scene6xx(vm) { + _dogTimer = 0; + _lastFrameTime = 0; + + _dogLoop = false; + _dogEatsRex = false; + _dogBarking = false; + _shopAvailable = false; + + _animationMode = -1; + _animationActive = -1; + _counter = -1; +} + +void Scene607::synchronize(Common::Serializer &s) { + Scene6xx::synchronize(s); + + s.syncAsUint32LE(_dogTimer); + s.syncAsUint32LE(_lastFrameTime); + + s.syncAsByte(_dogLoop); + s.syncAsByte(_dogEatsRex); + s.syncAsByte(_dogBarking); + s.syncAsByte(_shopAvailable); + + s.syncAsSint16LE(_animationMode); + s.syncAsSint16LE(_animationActive); + s.syncAsSint16LE(_counter); +} + +void Scene607::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_OBNOXIOUS_DOG); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene607::enter() { + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('c', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXCD_3"); + + if (!_game._visitedScenes._sceneRevisited && (_scene->_priorSceneId != 608)) + _globals[kDogStatus] = 1; + + if ((_scene->_priorSceneId == 608) && (_globals[kDogStatus] < 3)) + _globals[kDogStatus] = 3; + + _animationActive = 0; + + if ((_globals[kDogStatus] == 1) && (_game._difficulty != DIFFICULTY_EASY)) { + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('g', 3)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('g', 7)); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('g', 0)); + + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 6); + _dogBarking = false; + _dogLoop = false; + _shopAvailable = false; + _dogEatsRex = false; + _dogTimer = 0; + } else + _scene->_hotspots.activate(NOUN_OBNOXIOUS_DOG, false); + + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + + if (_scene->_priorSceneId == 608) { + _game._player._playerPos = Common::Point(297, 50); + _game._player._facing = FACING_SOUTHEAST; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(40, 104); + _game._player._facing = FACING_SOUTHEAST; + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->loadAnimation(formAnimName('R', 1), 80); + } else if (_globals[kDogStatus] == 2) { + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('g', 3)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('g', 7)); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('g', 0)); + } + + sceneEntrySound(); + + if (_scene->_roomChanged) + _game._objects.addToInventory(OBJ_BONES); + + _vm->_palette->setEntry(252, 63, 44, 30); + _vm->_palette->setEntry(253, 63, 20, 22); + _game.loadQuoteSet(0x2F8, 0x2F7, 0x2F6, 0x2F9, 0x2FA, 0); +} + +void Scene607::step() { + if (_globals[kDogStatus] == 2) { + int32 diff = _scene->_frameStartTime - _lastFrameTime; + if ((diff >= 0) && (diff <= 4)) + _dogTimer += diff; + else + _dogTimer++; + + _lastFrameTime = _scene->_frameStartTime; + } + + if ((_dogTimer >= 480) && !_dogLoop && !_shopAvailable && (_globals[kDogStatus] == 2) && !_game._player._special) { + _vm->_sound->command(14); + _dogLoop = true; + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 10, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 91); + _dogLoop = false; + _dogTimer = 0; + } + + if (_game._trigger == 91) { + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 6); + _dogBarking = false; + _globals[kDogStatus] = 1; + _scene->_hotspots.activate(NOUN_OBNOXIOUS_DOG, true); + } + + if (!_dogEatsRex && (_game._difficulty != DIFFICULTY_EASY) && !_animationActive && (_globals[kDogStatus] == 1) + && !_dogBarking && (_vm->getRandomNumber(1, 50) == 10)) { + _dogBarking = true; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 5, 8, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 6); + _scene->_kernelMessages.reset(); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_SPRITE, 2, 100); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 70); + _counter = 0; + } + + if ((_game._trigger == 70) && !_dogEatsRex && (_globals[kDogStatus] == 1) && !_animationActive) { + int syncIdx = _globals._sequenceIndexes[1]; + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 6); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], syncIdx); + _scene->_kernelMessages.reset(); + _dogBarking = false; + } + + if (_game._trigger == 100) { + _counter++; + _vm->_sound->command(12); + + if ((_counter >= 1) && (_counter <= 4)) { + Common::Point pos(0, 0); + switch (_counter) { + case 1: + pos = Common::Point(237, 5); + break; + + case 2: + pos = Common::Point(270, 15); + break; + + case 3: + pos = Common::Point(237, 25); + break; + + case 4: + pos = Common::Point(270, 36); + break; + + default: + break; + } + _scene->_kernelMessages.add(pos, 0xFDFC, 0, 0, 120, _game.getQuote(0x2F9)); + } + } + + if (_game._player._moving && (_game._difficulty != DIFFICULTY_EASY) && !_shopAvailable && (_globals[kDogStatus] == 1) && (_scene->_rails.getNext() > 0)) { + _game._player.cancelCommand(); + _game._player.startWalking(Common::Point(268, 72), FACING_NORTHEAST); + _scene->_rails.resetNext(); + } + + if ((_game._player._special > 0) && (_game._difficulty != DIFFICULTY_EASY) && (_globals[kDogStatus] == 1) && _game._player._stepEnabled) + _game._player._stepEnabled = false; + + if ((_game._difficulty != DIFFICULTY_EASY) && (_globals[kDogStatus] == 1) && (_game._player._playerPos == Common::Point(268, 72)) + && (_game._trigger || !_dogEatsRex)) { + _dogEatsRex = true; + switch (_game._trigger) { + case 91: + case 0: + _animationActive = 1; + _game._player._visible = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], -1, 7); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2FA)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 60); + _scene->_sequences.addTimer(10, 64); + break; + + case 60: { + int syncIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 5, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 8, 45); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 61); + } + break; + + case 61: { + int syncIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 15, 3, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 46, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 62); + } + break; + + case 62: { + int syncIdx = _globals._sequenceIndexes[4]; + _animationActive = 2; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx); + _scene->_sequences.addTimer(60, 63); + } + break; + + case 63: + _vm->_dialogs->show(60729); + _animationActive = 0; + _dogEatsRex = false; + _scene->_reloadSceneFlag = true; + _game._player._stepEnabled = true; + break; + + case 64: + if (_dogEatsRex && (_animationActive == 1)) { + _vm->_sound->command(12); + _scene->_sequences.addTimer(10, 64); + } + break; + + default: + break; + } + } + + switch (_game._trigger) { + case 80: + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + _scene->_sequences.addTimer(6, 81); + break; + + case 81: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 82); + break; + + case 82: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _game._player._stepEnabled = true; + break; + + default: + break; + } +} + +void Scene607::handleThrowingBone() { + _animationActive = -1; + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _game._player._visible = false; + _scene->loadAnimation(formAnimName('D', _animationMode), 1); + break; + + case 1: + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + + if (_animationMode != 1) + _scene->_hotspots.activate(NOUN_OBNOXIOUS_DOG, false); + else { + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 6); + } + + _dogBarking = false; + if (_game._objects.isInInventory(OBJ_BONE)) { + _game._objects.setRoom(OBJ_BONE, 1); + if (_animationMode == 1) + _globals[kBone202Status] = 0; + } else { + _game._objects.setRoom(OBJ_BONES, 1); + _game._objects.addToInventory(OBJ_BONE); + } + + _scene->_sequences.addTimer(60, 2); + break; + + case 2: { + int quoteId = 0x2F8; + if (_animationMode == 1) + quoteId = 0x2F7; + + if (_animationMode == 2) { + _globals[kDogStatus] = 2; + _dogTimer = 0; + } + + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(quoteId)); + _scene->_sequences.addTimer(60, 3); + } + break; + + case 3: + _game._player._stepEnabled = true; + _animationActive = 0; + break; + + default: + break; + } +} + +void Scene607::preActions() { + if (_action.isAction(VERB_TALKTO, NOUN_OBNOXIOUS_DOG)) + _game._player._needToWalk = false; + + if (_action.isAction(VERB_WALK_THROUGH, NOUN_SIDE_ENTRANCE) && (_globals[kDogStatus] == 2) && (_game._difficulty != DIFFICULTY_EASY)) { + _shopAvailable = true; + _dogTimer = 0; + } + + if (_action.isAction(VERB_THROW, NOUN_BONES, NOUN_OBNOXIOUS_DOG) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_OBNOXIOUS_DOG)) + _game._player.walk(Common::Point(193, 100), FACING_NORTHEAST); + + if (_action.isAction(VERB_THROW, NOUN_BONES, NOUN_FENCE) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_FENCE)) + _game._player.walk(Common::Point(201, 107), FACING_SOUTHEAST); +} + +void Scene607::actions() { + if (_action.isAction(VERB_WALK_THROUGH, NOUN_SIDE_ENTRANCE)) + _scene->_nextSceneId = 608; + else if (_action.isAction(VERB_GET_INSIDE, NOUN_CAR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], syncIdx); + _scene->_sequences.addTimer(6, 2); + } + break; + + case 2: + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 10, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: { + int syncIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _scene->_nextSceneId = 504; + } + break; + + default: + break; + } + } else if (_action.isAction(VERB_THROW, NOUN_BONES, NOUN_OBNOXIOUS_DOG) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_OBNOXIOUS_DOG)) { + if (_game._difficulty != DIFFICULTY_EASY) { + _animationMode = 1; + _scene->_kernelMessages.reset(); + if (_game._trigger == 0) + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2F6)); + + handleThrowingBone(); + } + } else if ((_action.isAction(VERB_THROW, NOUN_BONES, NOUN_FENCE) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_FENCE)) && (_game._difficulty != DIFFICULTY_EASY) + && ((_globals[kDogStatus] == 1) || _game._trigger)) { + _animationMode = 2; + if (_game._trigger == 0) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2F6)); + } + handleThrowingBone(); + } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_STREET)) { + if ((_globals[kDogStatus] == 1) || (_game._difficulty == DIFFICULTY_EASY)) + _vm->_dialogs->show(60710); + else + _vm->_dialogs->show(60711); + } else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(60712); + else if (_action.isAction(VERB_LOOK, NOUN_FENCE)) + _vm->_dialogs->show(60713); + else if (_action.isAction(VERB_LOOK, NOUN_CAR)) + _vm->_dialogs->show(60714); + else if (_action.isAction(VERB_LOOK, NOUN_MANHOLE)) + _vm->_dialogs->show(60715); + else if (_action.isAction(VERB_LOOK, NOUN_FIRE_HYDRANT) && (_globals[kDogStatus] == 1)) + _vm->_dialogs->show(60716); + else if (_action.isAction(VERB_LOOK, NOUN_SIGN)) + _vm->_dialogs->show(60717); + else if (_action.isAction(VERB_LOOK, NOUN_BROKEN_WINDOW)) + _vm->_dialogs->show(60718); + else if (_action.isAction(VERB_LOOK, NOUN_GARAGE_DOOR)) + _vm->_dialogs->show(60719); + else if (_action.isAction(VERB_LOOK, NOUN_SIDEWALK)) + _vm->_dialogs->show(60720); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_HOSE)) + _vm->_dialogs->show(60721); + else if (_action.isAction(VERB_LOOK, NOUN_AUTO_SHOP)) { + if (_globals[kDogStatus] == 1) + _vm->_dialogs->show(60723); + else + _vm->_dialogs->show(60722); + } else if (_action.isAction(VERB_LOOK, NOUN_SIDE_ENTRANCE)) { + if (_globals[kDogStatus] == 1) + _vm->_dialogs->show(60725); + else + _vm->_dialogs->show(60724); + } else if (_action.isAction(VERB_LOOK, NOUN_OBNOXIOUS_DOG)) + _vm->_dialogs->show(60726); + else if (_action.isAction(VERB_TALKTO, NOUN_OBNOXIOUS_DOG)) + _vm->_dialogs->show(60727); + else if (_action.isAction(VERB_LOOK, NOUN_BARRICADE)) + _vm->_dialogs->show(60728); + else if (_action.isAction(VERB_WALK_DOWN, NOUN_STREET)) + _vm->_dialogs->show(60730); + else if (_action.isObject(NOUN_GARAGE_DOOR) && (_action.isAction(VERB_OPEN) || _action.isAction(VERB_PUSH) || _action.isAction(VERB_PULL))) + _vm->_dialogs->show(60731); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene608::Scene608(MADSEngine *vm) : Scene6xx(vm) { + _carMode = -1; + _carFrame = -1; + _carMoveMode = -1; + _dogDeathMode = -1; + _carHotspotId = -1; + _barkCount = -1; + _polycementHotspotId = -1; + _animationMode = -1; + _nextTrigger = -1; + _throwMode = -1; + + _resetPositionsFl = false; + _dogActiveFl = false; + _dogBarkingFl = false; + _dogFirstEncounter = false; + _rexBeingEaten = false; + _dogHitWindow = false; + _checkFl = false; + _dogSquashFl = false; + _dogSafeFl = false; + _buttonPressedonTimeFl = false; + _dogUnderCar = false; + _dogYelping = false; + + _dogWindowTimer = -1; + _dogRunTimer = -1; + + _dogTimer1 = 0; + _dogTimer2 = 0; +} + +void Scene608::synchronize(Common::Serializer &s) { + Scene6xx::synchronize(s); + + s.syncAsSint16LE(_carMode); + s.syncAsSint16LE(_carFrame); + s.syncAsSint16LE(_carMoveMode); + s.syncAsSint16LE(_dogDeathMode); + s.syncAsSint16LE(_carHotspotId); + s.syncAsSint16LE(_barkCount); + s.syncAsSint16LE(_polycementHotspotId); + s.syncAsSint16LE(_animationMode); + s.syncAsSint16LE(_nextTrigger); + s.syncAsSint16LE(_throwMode); + + s.syncAsByte(_resetPositionsFl); + s.syncAsByte(_dogActiveFl); + s.syncAsByte(_dogBarkingFl); + s.syncAsByte(_dogFirstEncounter); + s.syncAsByte(_rexBeingEaten); + s.syncAsByte(_dogHitWindow); + s.syncAsByte(_checkFl); + s.syncAsByte(_dogSquashFl); + s.syncAsByte(_dogSafeFl); + s.syncAsByte(_buttonPressedonTimeFl); + s.syncAsByte(_dogUnderCar); + s.syncAsByte(_dogYelping); + + s.syncAsSint32LE(_dogWindowTimer); + s.syncAsSint32LE(_dogRunTimer); + + s.syncAsUint32LE(_dogTimer1); + s.syncAsUint32LE(_dogTimer2); +} + +void Scene608::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_POLYCEMENT); + _scene->addActiveVocab(NOUN_CAR); + _scene->addActiveVocab(NOUN_OBNOXIOUS_DOG); +} + +void Scene608::resetDogVariables() { + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1); + int idx = _scene->_dynamicHotspots.add(NOUN_OBNOXIOUS_DOG, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(194, 142), FACING_EAST); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 4); + _dogBarkingFl = false; + _dogFirstEncounter = false; +} + +void Scene608::restoreAnimations() { + _scene->freeAnimation(); + _carMode = 0; + _game._player._stepEnabled = true; + if (_throwMode == 6) + _dogSquashFl = true; + + if (_globals[kCarStatus] == 0) { + _scene->_sequences.remove(_globals._sequenceIndexes[6]); + _scene->_sequences.remove(_globals._sequenceIndexes[7]); + _scene->loadAnimation(formAnimName('A', -1)); + } else { + _scene->_sequences.remove(_globals._sequenceIndexes[8]); + _scene->_sequences.remove(_globals._sequenceIndexes[6]); + _scene->_sequences.remove(_globals._sequenceIndexes[7]); + _scene->loadAnimation(formAnimName('A', -1)); + _scene->_activeAnimation->setCurrentFrame(6); + } +} + +void Scene608::setCarAnimations() { + _scene->freeAnimation(); + if (_globals[kCarStatus] == 0) { + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[6], Common::Point(143, 98)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 6); + _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[7], Common::Point(141, 67)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 15); + } else { + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[6], Common::Point(143, 128)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 6); + _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[7], Common::Point(141, 97)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 15); + _globals._sequenceIndexes[8] = _scene->_sequences.startCycle(_globals._spriteIndexes[8], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[8], Common::Point(144, 126)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 5); + } +} + +void Scene608::handleThrowingBone() { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + setCarAnimations(); + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _animationMode = -1; + _game._player._visible = false; + _carMode = _throwMode; + if (_throwMode == 4) + _scene->loadAnimation(formAnimName('X', 2), 1); + else if (_throwMode == 5) + _scene->loadAnimation(formAnimName('X', 1), 1); + else + _scene->loadAnimation(formAnimName('X', 3), 1); + break; + + case 1: + _nextTrigger = 1; + _scene->_sequences.addTimer(1, 2); + break; + + case 2: + if (_nextTrigger != 2) + _scene->_sequences.addTimer(1, 2); + else { + if (_game._objects.isInInventory(OBJ_BONE)) + _game._objects.setRoom(OBJ_BONE, 1); + else { + _game._objects.setRoom(OBJ_BONES, 1); + _game._objects.addToInventory(OBJ_BONE); + } + _scene->_sequences.addTimer(60, 3); + } + break; + + case 3: + if (_throwMode != 6) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x304)); + _scene->_sequences.addTimer(120, 4); + } else + restoreAnimations(); + break; + + case 4: + restoreAnimations(); + break; + + default: + break; + } +} + +void Scene608::enter() { + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMRD_7"); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXMRC_9"); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('c', 2)); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('c', 0)); + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('c', 1)); + + if (_game._objects.isInRoom(OBJ_POLYCEMENT)) { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('g', -1)); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + int idx = _scene->_dynamicHotspots.add(NOUN_POLYCEMENT, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _polycementHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(249, 129), FACING_NORTHEAST); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 6); + } + + if (_game._objects.isInRoom(OBJ_REARVIEW_MIRROR)) { + _globals._spriteIndexes[12] = _scene->_sprites.addSprites(formAnimName('m', -1)); + _globals._sequenceIndexes[12] = _scene->_sequences.startCycle(_globals._spriteIndexes[12], false, 1); + int idx = _scene->_dynamicHotspots.add(NOUN_REARVIEW_MIRROR, VERB_WALKTO, _globals._sequenceIndexes[12], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(71, 113), FACING_NORTHEAST); + _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 15); + } + + if (_game._difficulty == DIFFICULTY_HARD) { + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('g', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('g', 1)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('g', 2)); + _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('h', 2)); + _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('h', 3)); + _rexBeingEaten = false; + + if (!_game._visitedScenes._sceneRevisited) { + _globals[kDogStatus] = 3; + _dogActiveFl = true; + } else + _dogActiveFl = (_globals[kDogStatus] != 4); + } else { + _globals[kDogStatus] = 4; + _dogActiveFl = false; + } + + _dogSquashFl = false; + _buttonPressedonTimeFl = false; + _dogWindowTimer = 0; + _dogRunTimer = 0; + _dogHitWindow = false; + _checkFl = false; + _dogUnderCar = false; + _dogYelping = false; + + + if (!_game._visitedScenes._sceneRevisited) + _globals[kCarStatus] = 0; + + _animationMode = 0; + _carMoveMode = 0; + _carFrame = -1; + + if (_globals[kCarStatus] == 0) { + _carMode = 0; + _dogDeathMode = 0; + _resetPositionsFl = false; + int idx = _scene->_dynamicHotspots.add(NOUN_CAR, VERB_WALKTO, -1, Common::Rect(99, 69, 99 + 82, 69 + 25)); + _carHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(96, 132), FACING_NORTHEAST); + _scene->loadAnimation(formAnimName('A', -1)); + } else if (_globals[kCarStatus] == 3) { + _carMode = 0; + _dogDeathMode = 0; + _resetPositionsFl = false; + int idx = _scene->_dynamicHotspots.add(NOUN_CAR, VERB_WALKTO, -1, Common::Rect(100, 100, 100 + 82, 100 + 25)); + _carHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(96, 132), FACING_NORTHEAST); + _scene->loadAnimation(formAnimName('A', -1)); + _scene->_activeAnimation->setCurrentFrame(6); + } else if (_globals[kCarStatus] == 1) { + _carMode = 2; + _dogDeathMode = 0; + _resetPositionsFl = false; + int idx = _scene->_dynamicHotspots.add(NOUN_CAR, VERB_WALKTO, -1, Common::Rect(99, 69, 99 + 82, 69 + 25)); + _carHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(96, 132), FACING_NORTHEAST); + _scene->loadAnimation(formAnimName('C', -1)); + } else if (_globals[kCarStatus] == 2) { + _carMode = 1; + _dogDeathMode = 2; + _resetPositionsFl = true; + int idx = _scene->_dynamicHotspots.add(NOUN_CAR, VERB_WALKTO, -1, Common::Rect(99, 69, 99 + 82, 69 + 25)); + _carHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(96, 132), FACING_NORTHEAST); + _scene->loadAnimation(formAnimName('B', -1)); + } else { + _carMode = 3; + _dogDeathMode = 2; + _resetPositionsFl = true; + int idx = _scene->_dynamicHotspots.add(NOUN_CAR, VERB_WALKTO, -1, Common::Rect(100, 100, 100 + 82, 100 + 25)); + _carHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(96, 132), FACING_NORTHEAST); + _scene->loadAnimation(formAnimName('D', -1)); + } + + _vm->_palette->setEntry(252, 63, 44, 30); + _vm->_palette->setEntry(253, 63, 20, 22); + + if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(46, 132); + _game._player._facing = FACING_EAST; + if (_game._difficulty == DIFFICULTY_HARD) { + if (!_game._visitedScenes._sceneRevisited) + _dogFirstEncounter = true; + else if (_dogActiveFl) + resetDogVariables(); + } + } else if ((_game._difficulty == DIFFICULTY_HARD) && !_dogFirstEncounter && _dogActiveFl) { + if (!_dogUnderCar) + resetDogVariables(); + else { + _globals._sequenceIndexes[10] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[10], false, 9, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 10, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 6); + } + } + + sceneEntrySound(); + + if (_scene->_roomChanged) + _game._objects.addToInventory(OBJ_BONES); + + _game.loadQuoteSet(0x2FB, 0x2FC, 0x2FE, 0x2FD, 0x2FF, 0x300, 0x301, 0x302, 0x303, 0x304, 0); +} + +void Scene608::step() { + if (_dogFirstEncounter) { + long diff = _scene->_frameStartTime - _dogTimer1; + if ((diff >= 0) && (diff <= 1)) + _dogWindowTimer += diff; + else + _dogWindowTimer++; + + _dogTimer1 = _scene->_frameStartTime; + } + + if (_dogActiveFl && (_dogWindowTimer >= 2) && !_dogHitWindow) { + _dogHitWindow = true; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 11, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + _vm->_sound->command(14); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 70); + _dogWindowTimer = 0; + } + + if (_game._trigger == 70) + resetDogVariables(); + + if ((_game._difficulty == DIFFICULTY_HARD) && !_animationMode && _dogActiveFl && !_dogFirstEncounter && !_dogUnderCar) { + if (!_dogBarkingFl) { + if (_vm->getRandomNumber(1, 50) == 10) { + _dogBarkingFl = true; + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 5, 8, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 4); + int idx = _scene->_dynamicHotspots.add(NOUN_OBNOXIOUS_DOG, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(194, 142), FACING_EAST); + _barkCount = 0; + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_SPRITE, 2, 100); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 60); + } + } else if (_game._trigger == 60) { + int syncIdx = _globals._sequenceIndexes[5]; + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 6); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], syncIdx); + _scene->_kernelMessages.reset(); + _dogBarkingFl = false; + } + } + + if ((_game._trigger == 100) && _dogBarkingFl) { + _vm->_sound->command(12); + _barkCount++; + + if ((_barkCount >= 1) && (_barkCount <= 4)) { + Common::Point _barkPos(0, 0); + switch (_barkCount) { + case 1: + _barkPos = Common::Point(197, 66); + break; + + case 2: + _barkPos = Common::Point(230, 76); + break; + + case 3: + _barkPos = Common::Point(197, 86); + break; + + case 4: + _barkPos = Common::Point(230, 97); + break; + + default: + break; + } + _scene->_kernelMessages.add(_barkPos, 0xFDFC, 0, 0, 120, _game.getQuote(0x2FB)); + } + } + + if (_dogSquashFl && !_dogFirstEncounter && _dogUnderCar && _dogActiveFl) { + long diff = _scene->_frameStartTime - _dogTimer2; + if ((diff >= 0) && (diff <= 4)) + _dogRunTimer += diff; + else + _dogRunTimer++; + + _dogTimer2 = _scene->_frameStartTime; + } + + if (_dogRunTimer >= 480 && !_checkFl && !_buttonPressedonTimeFl && !_dogFirstEncounter && _dogUnderCar && _dogActiveFl) { + _checkFl = true; + _dogSquashFl = false; + _dogSafeFl = true; + _checkFl = false; + _dogRunTimer = 0; + } else { + _dogSafeFl = false; + if (_game._player._moving && (_game._difficulty == DIFFICULTY_HARD) && _dogActiveFl && (_scene->_rails.getNext() > 0) && _dogUnderCar) + _dogSafeFl = true; + } + + if (_dogActiveFl && _dogSafeFl && !_buttonPressedonTimeFl) { + _dogDeathMode = 0; + _globals[kCarStatus] = 0; + _carMode = 0; + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _dogUnderCar = false; + _dogYelping = false; + _scene->_kernelMessages.reset(); + _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 92); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2FF)); + } + + if (_game._trigger == 92) { + resetDogVariables(); + _animationMode = 0; + } + + if ((_carMode == 4) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) { + _carFrame = _scene->_activeAnimation->getCurrentFrame(); + + if (_carFrame == 10) { + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + } else if (_carFrame == 56) { + resetDogVariables(); + _animationMode = 0; + _nextTrigger = 2; + } + } + } + + if ((_carMode == 5) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) { + _carFrame = _scene->_activeAnimation->getCurrentFrame(); + if (_carFrame == 10) { + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + } else if (_carFrame == 52) { + resetDogVariables(); + _animationMode = 0; + _nextTrigger = 2; + } + } + } + + if ((_carMode == 6) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) { + _carFrame = _scene->_activeAnimation->getCurrentFrame(); + + if (_carFrame == 11) { + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + } else if (_carFrame == 41) { + _globals._sequenceIndexes[10] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[10], false, 9, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 10, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 6); + _dogUnderCar = true; + _nextTrigger = 2; + } + } + } + + if (_dogUnderCar) { + if (!_dogYelping) { + if (_vm->getRandomNumber(1, 50) == 10) { + _dogYelping = true; + _barkCount = 0; + _scene->_sequences.addTimer(12, 110); + _scene->_sequences.addTimer(22, 111); + _scene->_sequences.addTimer(120, 112); + } + _scene->_kernelMessages.reset(); + } + } else + _dogYelping = false; + + if (_game._trigger == 110) { + _vm->_sound->command(12); + _scene->_kernelMessages.add(Common::Point(150, 97), 0xFDFC, 0, 0, 60, _game.getQuote(0x303)); + } + + if (_game._trigger == 111) { + _vm->_sound->command(12); + _scene->_kernelMessages.add(Common::Point(183, 93), 0xFDFC, 0, 0, 60, _game.getQuote(0x303)); + } + + if (_game._trigger == 112) + _dogYelping = false; + + if ((_carMode == 0) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) { + _carFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextFrame = -1; + + if ((_globals[kCarStatus] == 0) || (_globals[kCarStatus] == 3)) { + switch (_carMoveMode) { + case 0: + if (_globals[kCarStatus] == 0) + nextFrame = 0; + else + nextFrame = 6; + break; + + case 1: + if (_scene->_activeAnimation->getCurrentFrame() >= 12) { + nextFrame = 0; + _carMoveMode = 0; + _globals[kCarStatus] = 0; + } + break; + + case 2: + if (_scene->_activeAnimation->getCurrentFrame() >= 6) { + nextFrame = 6; + _carMoveMode = 0; + _globals[kCarStatus] = 3; + } + break; + + default: + break; + } + } + + if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextFrame); + _carFrame = nextFrame; + } + } + } + + if ((_carMode == 2) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) { + _carFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextFrame = -1; + + if (_carMoveMode == 0) + nextFrame = 28; + else if (_scene->_activeAnimation->getCurrentFrame() >= 28) { + nextFrame = 28; + _carMoveMode = 0; + } + + if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextFrame); + _carFrame = nextFrame; + } + } + } + + if ((_carMode == 3) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) { + _carFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextFrame = -1; + + if (_resetPositionsFl) { + nextFrame = 0; + _carMoveMode = 0; + } else if (_carMoveMode == 0) + nextFrame = 6; + else if (_scene->_activeAnimation->getCurrentFrame() >= 6) { + nextFrame = 6; + _carMoveMode = 0; + } + + if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextFrame); + _carFrame = nextFrame; + } + } + } + + + if ((_carMode == 1) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) { + _carFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextFrame = -1; + + if (_resetPositionsFl) { + nextFrame = 0; + _carMoveMode = 0; + } else if (_carMoveMode == 0) + nextFrame = 6; + else if (_scene->_activeAnimation->getCurrentFrame() >= 6) { + nextFrame = 6; + _carMoveMode = 0; + } + + if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextFrame); + _carFrame = nextFrame; + } + } + } + + if (_game._player._moving && (_game._difficulty == DIFFICULTY_HARD) && _dogActiveFl && (_scene->_rails.getNext() > 0)) { + _game._player.cancelCommand(); + _game._player.startWalking(Common::Point(194, 142), FACING_EAST); + _scene->_rails.resetNext(); + if (_dogUnderCar) + _dogSafeFl = true; + } + + if (_game._player._special > 0 && (_game._difficulty == DIFFICULTY_HARD) && _dogActiveFl && _game._player._stepEnabled) + _game._player._stepEnabled = false; + + if ((_game._difficulty == DIFFICULTY_HARD) && _dogActiveFl && (_game._player._playerPos == Common::Point(194, 142)) + && (_game._trigger || !_rexBeingEaten)) { + _rexBeingEaten = true; + switch (_game._trigger) { + case 0: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _animationMode = 1; + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 1, 2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 80); + _scene->_sequences.addTimer(10, 85); + break; + + case 80: + _game._player._visible = false; + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 3, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 5); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], -1); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2FC)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 81); + break; + + case 81: { + int syncIdx = _globals._sequenceIndexes[9]; + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 5, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 6, 38); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 5); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], syncIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 82); + } + break; + + case 82: { + int syncIdx = _globals._sequenceIndexes[9]; + _globals._sequenceIndexes[9] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[9], false, 15, 5, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 39, 40); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 5); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], syncIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 83); + } + break; + + case 83: { + _animationMode = 2; + int syncIdx = _globals._sequenceIndexes[9]; + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 5); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], syncIdx); + _scene->_sequences.addTimer(60, 84); + } + break; + + case 84: + _rexBeingEaten = false; + _animationMode = 0; + _scene->_reloadSceneFlag = true; + _game._player._stepEnabled = true; + break; + + case 85: + if (_rexBeingEaten && (_animationMode == 1)) { + _vm->_sound->command(12); + _scene->_sequences.addTimer(10, 85); + } + break; + + default: + break; + } + } +} + +void Scene608::preActions() { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + + if ((_action.isAction(VERB_THROW, NOUN_BONE, NOUN_REAR_OF_GARAGE) || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_REAR_OF_GARAGE) + || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_FRONT_OF_GARAGE) || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_FRONT_OF_GARAGE) + || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_OBNOXIOUS_DOG) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_OBNOXIOUS_DOG)) && _dogActiveFl) { + _game._player._stepEnabled = false; + _game._player.walk(Common::Point(56, 146), FACING_EAST); + } + + if ((_action.isAction(VERB_THROW, NOUN_BONES, NOUN_AREA_BEHIND_CAR) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_AREA_BEHIND_CAR) + || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_DANGER_ZONE) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_DANGER_ZONE)) && _dogActiveFl) { + _game._player._stepEnabled = false; + _game._player.walk(Common::Point(75, 136), FACING_EAST); + } + + if (_action.isAction(VERB_PUSH, NOUN_DOWN_BUTTON) && _dogUnderCar) { + _buttonPressedonTimeFl = true; + _dogDeathMode = 1; + } else + _buttonPressedonTimeFl = false; +} + +void Scene608::actions() { + if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY)) + _scene->_nextSceneId = 607; + else if (_action.isAction(VERB_PUSH, NOUN_DOWN_BUTTON)) { + _game._player._stepEnabled = true; + switch (_game._trigger) { + case 0: + if ((_globals[kCarStatus] == 0) || (_globals[kCarStatus] == 1) || (_globals[kCarStatus] == 2)) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], true, 6, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + } else + _vm->_dialogs->show(60839); + break; + + case 1: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]); + _game._player._visible = true; + if (_dogDeathMode == 0) + _carMode = 0; + else if (_dogDeathMode == 1) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x300)); + _globals[kCarStatus] = 1; + _carMode = 2; + _globals[kDogStatus] = 4; + _dogActiveFl = false; + _dogUnderCar = false; + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _scene->freeAnimation(); + _scene->loadAnimation(formAnimName('C', -1)); + } else { + _resetPositionsFl = false; + _carMode = 1; + _scene->freeAnimation(); + _scene->loadAnimation(formAnimName('B', -1)); + } + + _carMoveMode = 2; + _scene->_sequences.addTimer(1, 2); + break; + + case 2: + if (_carMoveMode != 0) + _scene->_sequences.addTimer(1, 2); + else { + _scene->_dynamicHotspots.remove(_carHotspotId); + int idx = _scene->_dynamicHotspots.add(NOUN_CAR, VERB_WALKTO, -1, Common::Rect(100, 100, 100 + 82, 100 + 25)); + _carHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(96, 132), FACING_NORTHEAST); + if (_globals[kCarStatus] == 1) + _scene->_sequences.addTimer(120, 3); + else { + if (_dogDeathMode == 0) + _globals[kCarStatus] = 3; + else { + _globals[kCarStatus] = 4; + _carMode = 3; + _dogDeathMode = 2; + } + _game._player._stepEnabled = true; + } + } + break; + + case 3: + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x302)); + _globals[kCarStatus] = 4; + _carMode = 3; + _dogDeathMode = 2; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_PUSH, NOUN_UP_BUTTON)) { + switch (_game._trigger) { + case 0: + if ((_globals[kCarStatus] == 3) || (_globals[kCarStatus] == 4)) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], true, 6, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + } else + _vm->_dialogs->show(60840); + break; + + case 1: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]); + _game._player._visible = true; + if (_dogDeathMode == 0) + _carMode = 0; + else { + _carMode = 3; + _resetPositionsFl = false; + _scene->freeAnimation(); + _scene->loadAnimation(formAnimName('D', -1)); + } + _carMoveMode = 1; + _scene->_sequences.addTimer(1, 2); + break; + + case 2: { + if (_carMoveMode != 0) + _scene->_sequences.addTimer(1, 2); + else if (_dogDeathMode == 0) + _globals[kCarStatus] = 0; + else if (_dogDeathMode == 2) { + _globals[kCarStatus] = 2; + _carMode = 3; + _dogDeathMode = 2; + } + _scene->_dynamicHotspots.remove(_carHotspotId); + int idx = _scene->_dynamicHotspots.add(NOUN_CAR, VERB_WALKTO, -1, Common::Rect(99, 69, 99 + 82, 69 + 25)); + _carHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(96, 132), FACING_NORTHEAST); + _game._player._stepEnabled = true; + } + break; + + default: + break; + } + } else if (_action.isAction(VERB_THROW, NOUN_BONE, NOUN_REAR_OF_GARAGE) || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_REAR_OF_GARAGE) + || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_OBNOXIOUS_DOG) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_OBNOXIOUS_DOG)) { + _game._player._stepEnabled = true; + if (_dogActiveFl) { + if (_game._trigger == 0) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2FE)); + } + _throwMode = 4; + handleThrowingBone(); + } else + _vm->_dialogs->show(60841); + } else if (_action.isAction(VERB_THROW, NOUN_BONE, NOUN_FRONT_OF_GARAGE) || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_FRONT_OF_GARAGE)) { + _game._player._stepEnabled = true; + if (_dogActiveFl) { + if (_game._trigger == 0) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2FD)); + } + _throwMode = 5; + handleThrowingBone(); + } else + _vm->_dialogs->show(60841); + } else if (_action.isAction(VERB_THROW, NOUN_BONES, NOUN_AREA_BEHIND_CAR) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_AREA_BEHIND_CAR) + || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_DANGER_ZONE) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_DANGER_ZONE)) { + _game._player._stepEnabled = true; + if ((_globals[kCarStatus] == 0) && _dogActiveFl) { + if (_dogActiveFl) { + if (_game._trigger == 0) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x301)); + } + _throwMode = 6; + handleThrowingBone(); + } else + _vm->_dialogs->show(60841); + } else + _vm->_dialogs->show(60842); + } else if (_action.isAction(VERB_TAKE, NOUN_POLYCEMENT) && (_game._trigger || !_game._objects.isInInventory(OBJ_POLYCEMENT))) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], true, 6, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 4, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _vm->_sound->command(9); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_dynamicHotspots.remove(_polycementHotspotId); + break; + + case 2: + _game._objects.addToInventory(OBJ_POLYCEMENT); + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + _game._player._visible = true; + _game._player._stepEnabled = true; + _vm->_dialogs->showItem(OBJ_POLYCEMENT, 60833); + break; + + default: + break; + } + } else if (_action.isAction(VERB_TAKE, NOUN_REARVIEW_MIRROR) && (_game._trigger || !_game._objects.isInInventory(OBJ_REARVIEW_MIRROR))) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], true, 6, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 2, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _vm->_sound->command(9); + _scene->_sequences.remove(_globals._sequenceIndexes[12]); + _game._objects.addToInventory(OBJ_REARVIEW_MIRROR); + _vm->_dialogs->showItem(OBJ_REARVIEW_MIRROR, 60827); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action._lookFlag) { + if (_game._difficulty != DIFFICULTY_HARD) + _vm->_dialogs->show(60810); + else if (_globals[kDogStatus] == 4) + _vm->_dialogs->show(60812); + else + _vm->_dialogs->show(60811); + } else if (_action.isAction(VERB_LOOK) && (_action.isObject(NOUN_MUFFLER) || _action.isObject(NOUN_CAR_SEAT) || _action.isObject(NOUN_HUBCAP) + || _action.isObject(NOUN_COILS) || _action.isObject(NOUN_QUARTER_PANEL))) + _vm->_dialogs->show(60813); + else if (_action.isAction(VERB_TAKE) && (_action.isObject(NOUN_MUFFLER) || _action.isObject(NOUN_CAR_SEAT) || _action.isObject(NOUN_HUBCAP) + || _action.isObject(NOUN_COILS) || _action.isObject(NOUN_QUARTER_PANEL))) + _vm->_dialogs->show(60814); + else if (_action.isAction(VERB_LOOK, NOUN_GARAGE_FLOOR) || _action.isAction(VERB_LOOK, NOUN_FRONT_OF_GARAGE) || _action.isAction(VERB_LOOK, NOUN_REAR_OF_GARAGE)) { + if (_dogActiveFl) + _vm->_dialogs->show(60815); + else + _vm->_dialogs->show(60816); + } else if (_action.isAction(VERB_LOOK, NOUN_SPARE_RIBS)) + _vm->_dialogs->show(60817); + else if (_action.isAction(VERB_TAKE, NOUN_SPARE_RIBS)) { + if (_game._difficulty == DIFFICULTY_HARD) + _vm->_dialogs->show(60818); + else + _vm->_dialogs->show(60819); + } else if (_action.isAction(VERB_LOOK, NOUN_UP_BUTTON)) + _vm->_dialogs->show(60820); + else if (_action.isAction(VERB_LOOK, NOUN_DOWN_BUTTON)) + _vm->_dialogs->show(60821); + else if (_action.isAction(VERB_LOOK, NOUN_TRASH_CAN)) + _vm->_dialogs->show(60822); + else if (_action.isAction(VERB_LOOK, NOUN_CALENDAR)) + _vm->_dialogs->show(60823); + else if (_action.isAction(VERB_LOOK, NOUN_STORAGE_BOX)) { + if (_game._objects[OBJ_REARVIEW_MIRROR]._roomNumber == _scene->_currentSceneId) + _vm->_dialogs->show(60825); + else + _vm->_dialogs->show(60824); + } else if (_action.isAction(VERB_OPEN, NOUN_STORAGE_BOX)) + _vm->_dialogs->show(60826); + else if (_action.isAction(VERB_LOOK, NOUN_REARVIEW_MIRROR) && (_action._mainObjectSource == 4)) + _vm->_dialogs->show(60828); + else if (_action.isAction(VERB_LOOK, NOUN_TOOL_BOX)) { + if (_game._objects[OBJ_POLYCEMENT]._roomNumber == _scene->_currentSceneId) + _vm->_dialogs->show(60829); + else + _vm->_dialogs->show(60830); + } else if (_action.isAction(VERB_OPEN, NOUN_TOOL_BOX)) + _vm->_dialogs->show(60831); + else if ((_action.isAction(VERB_LOOK, NOUN_POLYCEMENT)) && (_game._objects.isInRoom(OBJ_POLYCEMENT))) + _vm->_dialogs->show(60832); + else if (_action.isAction(VERB_LOOK, NOUN_GREASE_CAN) || _action.isAction(VERB_LOOK, NOUN_OIL_CAN)) + _vm->_dialogs->show(60834); + else if (_action.isAction(VERB_LOOK, NOUN_CAR_LIFT)) + _vm->_dialogs->show(60835); + else if (_action.isAction(VERB_LOOK, NOUN_CHAIR) || _action.isAction(VERB_LOOK, NOUN_HAT)) + _vm->_dialogs->show(60836); + else if (_action.isAction(VERB_LOOK, NOUN_DANGER_ZONE)) + _vm->_dialogs->show(60838); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene609::Scene609(MADSEngine *vm) : Scene6xx(vm) { + _videoDoorMode = -1; +} + +void Scene609::synchronize(Common::Serializer &s) { + Scene6xx::synchronize(s); + + s.syncAsSint16LE(_videoDoorMode); +} + +void Scene609::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene609::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('h', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXCD_9"); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RXMRC_9"); + + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); + + if (!_game._visitedScenes._sceneRevisited) + _globals[kBeenInVideoStore] = false; + + if (_scene->_priorSceneId == 611) { + _game._player._playerPos = Common::Point(264, 69); + _game._player._facing = FACING_SOUTHWEST; + } else if (_scene->_priorSceneId == 610) { + _game._player._playerPos = Common::Point(23, 90); + _game._player._facing = FACING_EAST; + _scene->_sequences.addTimer(60, 60); + _game._player._stepEnabled = false; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(86, 136); + _game._player._facing = FACING_NORTHEAST; + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); + _scene->loadAnimation(formAnimName('R', 1), 70); + } + + if (_scene->_roomChanged) { + _game._objects.addToInventory(OBJ_DOOR_KEY); + if (_game._difficulty != DIFFICULTY_EASY) + _game._objects.addToInventory(OBJ_PENLIGHT); + } + + sceneEntrySound(); + _game.loadQuoteSet(0x305, 0x306, 0x307, 0x308, 0x309, 0); +} + +void Scene609::step() { + switch (_game._trigger) { + case 60: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 61); + break; + + case 61: + _scene->_hotspots.activate(NOUN_VIDEO_STORE_DOOR, false); + _game._player.walk(Common::Point(101, 100), FACING_EAST); + _scene->_sequences.addTimer(180, 62); + break; + + case 62: + _scene->_sequences.remove( _globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _scene->_hotspots.activate(NOUN_VIDEO_STORE_DOOR, true); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 63); + break; + + case 63: + if (!_globals[kHasTalkedToHermit] && (_game._difficulty != DIFFICULTY_HARD)) { + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 26, 2, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(287, 73)); + _scene->_sequences.setScale(_globals._sequenceIndexes[3], 47); + } + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); + _game._player._stepEnabled = true; + break; + + default: + break; + } + + switch (_game._trigger) { + case 70: + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + _scene->_sequences.addTimer(6, 71); + break; + + case 71: + if (!_globals[kHasTalkedToHermit]) { + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 26, 2, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(287, 73)); + _scene->_sequences.setScale(_globals._sequenceIndexes[3], 47); + } + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + break; + + case 72: + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); + _game._player._stepEnabled = true; + break; + + default: + break; + } +} + +void Scene609::enterStore() { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + if (_videoDoorMode == 2) + _scene->_sequences.addTimer(1, 4); + else { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x305)); + _scene->_sequences.addTimer(120, 1); + } + break; + + case 1: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x306)); + _scene->_sequences.addTimer(60, 2); + break; + + case 2: + _game._player._visible = false; + _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], true, 11, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[5]); + _game._player._visible = true; + _game._objects.setRoom(OBJ_DOOR_KEY, 1); + _scene->_sequences.addTimer(15, 4); + break; + + case 4: + _game._player._visible = false; + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], true, 1); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.addTimer(15, 5); + break; + + case 5: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._visible = true; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 6); + break; + + case 6: + _scene->_hotspots.activate(NOUN_VIDEO_STORE_DOOR, false); + if (_videoDoorMode == 1) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 180, _game.getQuote(0x307)); + } + _game._player.walk(Common::Point(23, 90), FACING_WEST); + _scene->_sequences.addTimer(180, 7); + break; + + case 7: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 8); + break; + + case 8: + _scene->_hotspots.activate(NOUN_VIDEO_STORE_DOOR, true); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); + _globals[kBeenInVideoStore] = true; + _game._player._stepEnabled = true; + _scene->_nextSceneId = 610; + break; + + default: + break; + } +} + +void Scene609::preActions() { + if (_action.isAction(VERB_UNLOCK, NOUN_DOOR_KEY, NOUN_VIDEO_STORE_DOOR)) + _game._player.walk(Common::Point(78, 99), FACING_NORTHWEST); +} + +void Scene609::actions() { + if (_action.isAction(VERB_WALK_TOWARDS, NOUN_ALLEY)) + _scene->_nextSceneId = 611; + else if (_action.isAction(VERB_WALK_THROUGH, NOUN_VIDEO_STORE_DOOR)) { + if (!_globals[kBeenInVideoStore]) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x308)); + _scene->_sequences.addTimer(120, 1); + break; + + case 1: + _game._player._visible = false; + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], true, 1); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.addTimer(30, 2); + break; + + case 2: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._visible = true; + _scene->_sequences.addTimer(60, 3); + break; + + case 3: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x309)); + _scene->_sequences.addTimer(120, 4); + break; + + case 4: + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else { + _videoDoorMode = 2; + enterStore(); + } + } else if (_action.isAction(VERB_UNLOCK, NOUN_DOOR_KEY, NOUN_VIDEO_STORE_DOOR)) { + _videoDoorMode = 1; + enterStore(); + } else if (_action.isAction(VERB_GET_INSIDE, NOUN_CAR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[1]; + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], syncIdx); + _scene->_sequences.addTimer(6, 2); + } + break; + + case 2: + _game._player._visible = false; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: { + int syncIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx); + _scene->_nextSceneId = 504; + } + break; + + default: + break; + } + } else if (_action._lookFlag) + _vm->_dialogs->show(60910); + else if (_action.isAction(VERB_LOOK, NOUN_STREET)) + _vm->_dialogs->show(60911); + else if (_action.isAction(VERB_LOOK, NOUN_SPOT_A_POT)) + _vm->_dialogs->show(60912); + else if (_action.isAction(VERB_LOOK, NOUN_VIDEO_STORE)) + _vm->_dialogs->show(60913); + else if (_action.isAction(VERB_LOOK, NOUN_BILLBOARD)) + _vm->_dialogs->show(60914); + else if (_action.isAction(VERB_LOOK, NOUN_STATUE)) + _vm->_dialogs->show(60915); + else if (_action.isAction(VERB_LOOK, NOUN_CAR)) + _vm->_dialogs->show(60916); + else if (_action.isAction(VERB_LOOK, NOUN_NEWSSTAND)) + _vm->_dialogs->show(60917); + else if (_action.isAction(VERB_LOOK, NOUN_VIDEO_STORE_DOOR)) { + if (!_globals[kBeenInVideoStore]) + _vm->_dialogs->show(60918); + else + _vm->_dialogs->show(60919); + } else if (_action.isAction(VERB_WALK_DOWN, NOUN_STREET)) + _vm->_dialogs->show(60730); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene610::Scene610(MADSEngine *vm) : Scene6xx(vm) { + _handsetHotspotId = -1; + _checkVal = -1; + + _cellCharging = false; + + _cellChargingTimer = -1; + _lastFrameTimer = 0; +} + +void Scene610::synchronize(Common::Serializer &s) { + Scene6xx::synchronize(s); + + s.syncAsSint16LE(_handsetHotspotId); + s.syncAsSint16LE(_checkVal); + + s.syncAsByte(_cellCharging); + + s.syncAsSint32LE(_cellChargingTimer); + s.syncAsUint32LE(_lastFrameTimer); +} + +void Scene610::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_PHONE_HANDSET); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene610::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('p', -1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMRC_9"); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 1)); + + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 60, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 13); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 30, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); + + if (!_game._visitedScenes._sceneRevisited) + _cellCharging = false; + + if (_game._objects[OBJ_PHONE_HANDSET]._roomNumber == _scene->_currentSceneId) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 0, 0, 0); + _handsetHotspotId = _scene->_dynamicHotspots.add(NOUN_PHONE_HANDSET, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_handsetHotspotId, Common::Point(132, 121), FACING_NORTHWEST); + if ((_globals[kHandsetCellStatus] == 2) && (_game._difficulty == DIFFICULTY_HARD) && !_globals[kDurafailRecharged]) + _globals[kHandsetCellStatus] = 1; + } + + if (_scene->_roomChanged && _game._difficulty != DIFFICULTY_EASY) + _game._objects.addToInventory(OBJ_PENLIGHT); + + if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(175, 152); + _game._player._facing = FACING_NORTHWEST; + } + + sceneEntrySound(); +} + +void Scene610::step() { + if (_cellCharging) { + long diff = _scene->_frameStartTime - _lastFrameTimer; + if ((diff >= 0) && (diff <= 60)) + _cellChargingTimer += diff; + else + _cellChargingTimer++; + + _lastFrameTimer = _scene->_frameStartTime; + } + + // CHECKME: _checkVal is always false, could be removed + if ((_cellChargingTimer >= 60) && !_checkVal) { + _checkVal = true; + _globals[kHandsetCellStatus] = 1; + _cellCharging = false; + _checkVal = false; + _cellChargingTimer = 0; + } +} + +void Scene610::actions() { + if (_action.isAction(VERB_EXIT_FROM, NOUN_VIDEO_STORE)) + _scene->_nextSceneId = 609; + else if (_action.isAction(VERB_TAKE, NOUN_PHONE_HANDSET)) { + if ( _game._trigger || !_game._objects.isInInventory(OBJ_PHONE_HANDSET)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], true, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 2, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _vm->_sound->command(9); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_dynamicHotspots.remove(_handsetHotspotId); + _game._objects.addToInventory(OBJ_PHONE_HANDSET); + _vm->_dialogs->showItem(OBJ_PHONE_HANDSET, 61017); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } + } else if (_action.isAction(VERB_PUT, NOUN_PHONE_HANDSET, NOUN_PHONE_CRADLE)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], true, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 2, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 0, 0, 0); + _handsetHotspotId = _scene->_dynamicHotspots.add(NOUN_PHONE_HANDSET, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_handsetHotspotId, Common::Point(132, 121), FACING_NORTHWEST); + _game._objects.setRoom(OBJ_PHONE_HANDSET, _scene->_currentSceneId); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + _game._player._visible = true; + _game._player._stepEnabled = true; + if ((_globals[kHandsetCellStatus] == 2) && (_game._difficulty == DIFFICULTY_HARD) && !_globals[kDurafailRecharged]) + _cellCharging = true; + + _vm->_dialogs->show(61032); + break; + + default: + break; + } + } else if (_action.isAction(VERB_LOOK, NOUN_PIPPY_BILLBOARD)) + _vm->_dialogs->show(61010); + else if (_action.isAction(VERB_LOOK, NOUN_CIVILIZATION_AD)) + _vm->_dialogs->show(61011); + else if (_action.isAction(VERB_LOOK, NOUN_MARX_BROS_POSTER)) + _vm->_dialogs->show(61012); + else if (_action.isAction(VERB_LOOK, NOUN_VIDEO_MONITOR)) + _vm->_dialogs->show(61013); + else if (_action.isAction(VERB_LOOK, NOUN_VIDEO_STORE)) + _vm->_dialogs->show(61014); + else if (_action._lookFlag) + _vm->_dialogs->show(61015); + else if (_action.isAction(VERB_LOOK, NOUN_LOGO)) + _vm->_dialogs->show(61018); + else if (_action.isAction(VERB_LOOK, NOUN_CEMENT)) { + if (_game._visitedScenes.exists(601)) + _vm->_dialogs->show(61020); + else + _vm->_dialogs->show(61019); + } else if (_action.isAction(VERB_LOOK, NOUN_COUNTER)) + _vm->_dialogs->show(61021); + else if (_action.isAction(VERB_LOOK, NOUN_PHONE_ANTENNA)) + _vm->_dialogs->show(61022); + else if (_action.isAction(VERB_LOOK, NOUN_SMELLY_SNEAKER)) + _vm->_dialogs->show(61023); + else if (_action.isAction(VERB_TAKE, NOUN_SMELLY_SNEAKER)) + _vm->_dialogs->show(61024); + else if (_action.isAction(VERB_LOOK, NOUN_SPOTLIGHT)) + _vm->_dialogs->show(61025); + else if (_action.isAction(VERB_LOOK, NOUN_PHONE_HANDSET) && (_action._mainObjectSource == 4)) + _vm->_dialogs->show(61026); + else if (_action.isAction(VERB_LOOK, NOUN_PHONE_CRADLE)) + _vm->_dialogs->show(61027); + else if (_action.isAction(VERB_LOOK, NOUN_RETURN_SLOT)) + _vm->_dialogs->show(61028); + else if (_action.isAction(VERB_PUT, NOUN_RETURN_SLOT) + && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) + _vm->_dialogs->show(61029); + else if ( _action.isObject(NOUN_CLASSIC_VIDEOS) || _action.isObject(NOUN_MORE_CLASSIC_VIDEOS) || _action.isObject(NOUN_DRAMA_VIDEOS) + || _action.isObject(NOUN_NEW_RELEASE_VIDEOS) || _action.isObject(NOUN_PORNO_VIDEOS) || _action.isObject(NOUN_EDUCATIONAL_VIDEOS) + || _action.isObject(NOUN_INSTRUCTIONAL_VIDEOS) || _action.isObject(NOUN_WORKOUT_VIDEOS) || _action.isObject(NOUN_FOREIGN_VIDEOS) + || _action.isObject(NOUN_ADVENTURE_VIDEOS) || _action.isObject(NOUN_COMEDY_VIDEOS)) { + if (_action.isAction(VERB_LOOK)) + _vm->_dialogs->show(61030); + else if (_action.isAction(VERB_TAKE)) + _vm->_dialogs->show(61031); + else + return; + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene611::Scene611(MADSEngine *vm) : Scene6xx(vm), _defaultDialogPos(0, 0) { + _seenRatFl = false; + _eyesRunningFl = false; + _shouldRemoveEyes = false; + _ratPresentFl = false; + _duringDialogFl = false; + _resetBatterieText = false; + _hermitTalkingFl = false; + _hermitMovingFl = false; + _alreadyTalkingFl = false; + _giveBatteriesFl = false; + _startTradingFl = false; + _check1Fl = false; + _stickFingerFl = false; + + _randVal = -1; + _ratHotspotId = -1; + _hermitDialogNode = -1; + _hermitDisplayedQuestion = -1; + _nextFrame = -1; + _hermitMode = -1; + + _ratTimer = 0; +} + +void Scene611::synchronize(Common::Serializer &s) { + Scene6xx::synchronize(s); + + s.syncAsByte(_seenRatFl); + s.syncAsByte(_eyesRunningFl); + s.syncAsByte(_shouldRemoveEyes); + s.syncAsByte(_ratPresentFl); + s.syncAsByte(_duringDialogFl); + s.syncAsByte(_resetBatterieText); + s.syncAsByte(_hermitTalkingFl); + s.syncAsByte(_hermitMovingFl); + s.syncAsByte(_alreadyTalkingFl); + s.syncAsByte(_giveBatteriesFl); + s.syncAsByte(_startTradingFl); + s.syncAsByte(_check1Fl); + s.syncAsByte(_stickFingerFl); + + s.syncAsSint16LE(_randVal); + s.syncAsSint16LE(_ratHotspotId); + s.syncAsSint16LE(_hermitDialogNode); + s.syncAsSint16LE(_hermitDisplayedQuestion); + s.syncAsSint16LE(_nextFrame); + s.syncAsSint16LE(_hermitMode); + + s.syncAsUint32LE(_ratTimer); + + s.syncAsSint16LE(_defaultDialogPos.x); + s.syncAsSint16LE(_defaultDialogPos.y); +} + +void Scene611::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_RAT); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene611::handleRatMoves() { + _ratPresentFl = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 11, -2); + _ratTimer = _game._player._priorTimer; + _scene->_dynamicHotspots.remove(_ratHotspotId); +} + +void Scene611::handleTrading() { + if (_game._objects.isInInventory(OBJ_DURAFAIL_CELLS)) + _game._objects.setRoom(OBJ_DURAFAIL_CELLS, 1); + + if (_game._objects.isInInventory(OBJ_PHONE_CELLS)) + _game._objects.setRoom(OBJ_PHONE_CELLS, 1); + + _game._objects.addToInventory(OBJ_FAKE_ID); +} + +void Scene611::setDialogNode(int node) { + if (node > 0) + _hermitDialogNode = node; + + _game._player._stepEnabled = true; + + switch (node) { + case 0: + _scene->_userInterface.setup(kInputBuildingSentences); + _duringDialogFl = false; + _hermitDialogNode = 0; + break; + + case 1: + _dialog1.start(); + _duringDialogFl = true; + _hermitDialogNode = 1; + break; + + case 2: + _dialog2.start(); + _duringDialogFl = true; + _hermitDialogNode = 2; + break; + + default: + break; + } +} + +bool Scene611::check2ChargedBatteries() { + if ((_game._objects.isInInventory(OBJ_DURAFAIL_CELLS) && !_game._objects.isInInventory(OBJ_PHONE_CELLS)) + || (!_game._objects.isInInventory(OBJ_DURAFAIL_CELLS) && _game._objects.isInInventory(OBJ_PHONE_CELLS))) + return true; + + return false; +} + +bool Scene611::check4ChargedBatteries() { + if (_game._objects.isInInventory(OBJ_DURAFAIL_CELLS) && _game._objects.isInInventory(OBJ_PHONE_CELLS) && _globals[136]) + return true; + + return false; +} + +void Scene611::handleTalking(int delay) { + if (_hermitTalkingFl) + _alreadyTalkingFl = true; + + _hermitTalkingFl = true; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(delay, 100); +} + +void Scene611::handleSubDialog1() { + switch (_action._activeAction._verbId) { + case 0x287: + _stickFingerFl = true; + _nextFrame = 34; + _hermitMovingFl = false; + _hermitMode = 5; + displayHermitQuestions(5); + _dialog1.write(0x287, false); + if (!_dialog1.read(0x288)) + _dialog1.write(0x28E, true); + + _dialog2.write(0x29C, true); + _dialog2.write(0x29D, true); + _dialog2.write(0x29E, true); + setDialogNode(2); + break; + + case 0x288: + handleTalking(500); + displayHermitQuestions(6); + _dialog1.write(0x288, false); + _dialog1.write(0x289, true); + if (!_dialog1.read(0x287)) + _dialog1.write(0x28E, true); + + setDialogNode(1); + break; + + case 0x289: + handleTalking(500); + displayHermitQuestions(10); + _dialog1.write(0x289, false); + _dialog1.write(0x28A, true); + _dialog1.write(0x28B, true); + setDialogNode(1); + break; + + case 0x28A: + handleTalking(500); + displayHermitQuestions(11); + _dialog1.write(0x28A, false); + setDialogNode(1); + break; + + case 0x28B: + handleTalking(500); + displayHermitQuestions(12); + _dialog1.write(0x28C, true); + _dialog1.write(0x28D, true); + _dialog1.write(0x28B, false); + setDialogNode(1); + break; + + case 0x28C: + handleTalking(500); + displayHermitQuestions(13); + _dialog1.write(0x28C, false); + setDialogNode(1); + break; + + case 0x28D: + handleTalking(500); + displayHermitQuestions(14); + _dialog1.write(0x290, true); + _dialog1.write(0x28D, false); + _dialog1.write(0x28F, true); + setDialogNode(1); + break; + + case 0x28E: + handleTalking(500); + displayHermitQuestions(15); + _dialog1.write(0x295, true); + _dialog1.write(0x28E, false); + setDialogNode(1); + break; + + case 0x290: + handleTalking(500); + displayHermitQuestions(17); + _dialog1.write(0x290, false); + _dialog1.write(0x28E, false); + if (!_dialog1.read(0x28F)) + _dialog1.write(0x291, true); + + setDialogNode(1); + break; + + case 0x291: + handleTalking(500); + displayHermitQuestions(18); + _dialog1.write(0x291, false); + if ((!_game._objects.isInInventory(OBJ_DURAFAIL_CELLS)) && (!_game._objects.isInInventory(OBJ_PHONE_CELLS))) { + _dialog1.write(0x292, true); + _dialog1.write(0x293, true); + } + + if ((_game._objects.isInInventory(OBJ_DURAFAIL_CELLS)) || (_game._objects.isInInventory(OBJ_PHONE_CELLS))) + _dialog1.write(0x294, true); + + if (!_game._objects.isInInventory(OBJ_DURAFAIL_CELLS) && !_game._objects.isInInventory(OBJ_PHONE_CELLS)) + _globals[kExecuted_1_11] = true; + + setDialogNode(1); + break; + + case 0x28F: + handleTalking(500); + displayHermitQuestions(16); + _dialog1.write(0x28F, false); + if (!_dialog1.read(0x290)) + _dialog1.write(0x291, true); + + setDialogNode(1); + break; + + case 0x295: + handleTalking(500); + displayHermitQuestions(20); + _dialog1.write(0x295, false); + setDialogNode(1); + break; + + case 0x292: + handleTalking(500); + displayHermitQuestions(19); + _dialog1.write(0x292, false); + _dialog1.write(0x293, false); + setDialogNode(1); + break; + + case 0x293: { + handleTalking(200); + _scene->_kernelMessages.reset(); + + Common::String curQuote = _game.getQuote(0x2D1); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y), 0xFDFC, 0, 0, 120, curQuote); + + curQuote = _game.getQuote(0x2D2); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 120, curQuote); + + _dialog1.write(0x293, false); + setDialogNode(0); + } + break; + + case 0x294: { + bool hermitPleasedFl = false; + + switch (_game._difficulty) { + case DIFFICULTY_EASY: + hermitPleasedFl = _game._objects.isInInventory(OBJ_DURAFAIL_CELLS) || _game._objects.isInInventory(OBJ_PHONE_CELLS); + break; + + case DIFFICULTY_MEDIUM: + hermitPleasedFl = _game._objects.isInInventory(OBJ_DURAFAIL_CELLS) && _game._objects.isInInventory(OBJ_PHONE_CELLS); + break; + + default: // HARD + hermitPleasedFl = check4ChargedBatteries(); + break; + } + + if (hermitPleasedFl) { + _hermitDisplayedQuestion = 21; + if (!_giveBatteriesFl) + setDialogNode(0); + else + _giveBatteriesFl = false; + } else if (((_game._difficulty == DIFFICULTY_MEDIUM) || (_game._difficulty == DIFFICULTY_HARD)) && check2ChargedBatteries()) { + _hermitDisplayedQuestion = 22; + if (!_giveBatteriesFl) + setDialogNode(0); + else + _giveBatteriesFl = false; + } else { + _hermitDisplayedQuestion = 23; + if (!_giveBatteriesFl) + setDialogNode(0); + else + _giveBatteriesFl = false; + } + _startTradingFl = true; + } + break; + + case 0x296: { + _scene->_kernelMessages.reset(); + + Common::String curQuote = _game.getQuote(0x2E6); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 120, curQuote); + + setDialogNode(0); + handleTalking(200); + } + break; + + default: + break; + } +} + +void Scene611::handleSubDialog2() { + switch (_action._activeAction._verbId) { + case 0x29C: + displayHermitQuestions(7); + setDialogNode(1); + handleTalking(500); + break; + + case 0x29D: + displayHermitQuestions(8); + setDialogNode(1); + handleTalking(500); + break; + + case 0x29E: + displayHermitQuestions(9); + setDialogNode(1); + handleTalking(500); + break; + + case 0x29F: { + _scene->_kernelMessages.reset(); + Common::String curQuote = _game.getQuote(0x2A7); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 120, curQuote); + setDialogNode(0); + _dialog2.write(0x29F, false); + } + break; + + default: + break; + } +} + +void Scene611::handleDialog() { + if (_game._trigger == 0) { + _scene->_kernelMessages.reset(); + _game._player._stepEnabled = false; + + Common::String curQuote = _game.getQuote(_action._activeAction._verbId); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + + if (width > 200) { + Common::String subQuote1, subQuote2; + _game.splitQuote(curQuote, subQuote1, subQuote2); + _scene->_kernelMessages.add(Common::Point(0, -14), 0x1110, 34, 0, 150, subQuote1); + + if (_action._activeAction._verbId == 0x29D) + _scene->_kernelMessages.add(Common::Point(-18, 0), 0x1110, 34, 1, 150, subQuote2); + else if (_action._activeAction._verbId == 0x28A) + _scene->_kernelMessages.add(Common::Point(-10, 0), 0x1110, 34, 1, 150, subQuote2); + else + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 1, 150, subQuote2); + + _scene->_sequences.addTimer(170, 50); + } else { + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 1, 120, curQuote); + _scene->_sequences.addTimer(140, 50); + } + } else if (_game._trigger == 50) { + if (_hermitDialogNode == 1) + handleSubDialog1(); + else if (_hermitDialogNode == 2) + handleSubDialog2(); + } +} + +void Scene611::displayHermitQuestions(int question) { + _scene->_kernelMessages.reset(); + _hermitDisplayedQuestion = question; + + switch (question) { + case 1: { + Common::String curQuote = _game.getQuote(0x281); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x282); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 2: { + Common::String curQuote = _game.getQuote(0x283); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x284); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 3: { + Common::String curQuote = _game.getQuote(0x285); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 4: { + Common::String curQuote = _game.getQuote(0x286); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 5: { + Common::String curQuote = _game.getQuote(0x297); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y - 14), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x298); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x299); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 6: { + Common::String curQuote = _game.getQuote(0x29A); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x29B); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 7: { + Common::String curQuote = _game.getQuote(0x2A0); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2A1); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 8: { + Common::String curQuote = _game.getQuote(0x2A2); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2A3); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2A4); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 9: { + Common::String curQuote = _game.getQuote(0x2A5); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2A6); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 10: { + Common::String curQuote = _game.getQuote(0x2A8); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2A9); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2AA); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 11: { + Common::String curQuote = _game.getQuote(0x2AB); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2AC); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2AD); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2AE); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 12: { + Common::String curQuote = _game.getQuote(0x2AF); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2B0); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2B1); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2B2); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 13: { + Common::String curQuote = _game.getQuote(0x2B3); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 3), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2B4); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2B5); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2B6); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + _scene->_kernelMessages.add(Common::Point(11, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x2B7)); + _scene->_kernelMessages.add(Common::Point(11, _defaultDialogPos.y + 73), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x2B8)); + _scene->_kernelMessages.add(Common::Point(11, _defaultDialogPos.y + 87), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x2B9)); + } + break; + + case 14: { + Common::String curQuote = _game.getQuote(0x2BA); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2BB); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2BC); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2BD); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 15: { + Common::String curQuote = _game.getQuote(0x2BE); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2BF); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2C0); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2C1); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 16: { + Common::String curQuote = _game.getQuote(0x2C2); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 3), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2C3); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2C4); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2C5); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2C6); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 17: { + Common::String curQuote = _game.getQuote(0x2C7); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2C8); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2C0); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2CA); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 18: { + Common::String curQuote = _game.getQuote(0x2CB); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2CC); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2CD); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 19: { + Common::String curQuote = _game.getQuote(0x2CE); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2CF); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2D0); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 20: { + Common::String curQuote = _game.getQuote(0x2E1); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 3), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2E2); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2E3); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2E4); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2E5); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 21: { + Common::String curQuote = _game.getQuote(0x2D3); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 3), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2D4); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2D5); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2D6); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2D7); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 22: { + Common::String curQuote = _game.getQuote(0x2D8); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 700, curQuote); + + curQuote = _game.getQuote(0x2D9); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 700, curQuote); + + curQuote = _game.getQuote(0x2DA); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 700, curQuote); + + curQuote = _game.getQuote(0x2DB); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 700, curQuote); + } + break; + + case 23: { + Common::String curQuote = _game.getQuote(0x2DC); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 3), 0xFDFC, 0, 0, 700, curQuote); + + curQuote = _game.getQuote(0x2DD); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 700, curQuote); + + curQuote = _game.getQuote(0x2DE); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 700, curQuote); + + curQuote = _game.getQuote(0x2DF); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 700, curQuote); + + curQuote = _game.getQuote(0x2E0); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 700, curQuote); + } + break; + + default: + break; + } +} + +void Scene611::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXMRC_9"); + + _game.loadQuoteSet(0x279, 0x27A, 0x27B, 0x27C, 0x27D, 0x27E, 0x27F, 0x280, 0x281, 0x282, 0x283, 0x284, + 0x285, 0x286, 0x287, 0x288, 0x289, 0x28A, 0x28B, 0x28C, 0x28D, 0x28E, 0x28F, 0x290, 0x291, 0x292, + 0x293, 0x294, 0x295, 0x296, 0x297, 0x298, 0x299, 0x29A, 0x29B, 0x29C, 0x29D, 0x29E, 0x29F, 0x2A0, + 0x2A1, 0x2A2, 0x2A3, 0x2A4, 0x2A5, 0x2A6, 0x2A7, 0x2A8, 0x2A9, 0x2AA, 0x2AB, 0x2AC, 0x2AD, 0x2AE, + 0x2AF, 0x2B0, 0x2B1, 0x2B2, 0x2B3, 0x2B4, 0x2B5, 0x2B6, 0x2B7, 0x2B8, 0x2B9, 0x2BA, 0x2BB, 0x2BC, + 0x2BD, 0x2BE, 0x2BF, 0x2C0, 0x2C1, 0x2C2, 0x2C3, 0x2C4, 0x2C5, 0x2C6, 0x2C7, 0x2C8, 0x2C9, 0x2CA, + 0x2CB, 0x2CC, 0x2CD, 0x2CE, 0x2CF, 0x2D0, 0x2D1, 0x2D2, 0x2D3, 0x2D4, 0x2D5, 0x2D6, 0x2D7, 0x2D8, + 0x2D9, 0x2DA, 0x2DB, 0x2DC, 0x2DD, 0x2DE, 0x2DF, 0x2E0, 0x2E1, 0x2E2, 0x2E3, 0x2E4, 0x2E5, 0x2E6, + 0x323, 0x324, 0); + + _dialog1.setup(0x82, 0x287, 0x288, 0x289, 0x28A, 0x28B, 0x28C, 0x28D, 0x28E, 0x28F, 0x290, + 0x291, 0x292, 0x293, 0x294, 0x295, 0x296, 0); + + _dialog2.setup(0x83, 0x29C, 0x29D, 0x29E, 0x29F, 0); + + if (!_game._visitedScenes._sceneRevisited) { + _dialog1.set(0x82, 0x287, 0x288, 0x296, 0); + _dialog2.set(0x83, 0x29F, 0); + } + + _vm->_palette->setEntry(252, 51, 51, 47); + _vm->_palette->setEntry(253, 37, 37, 37); + + _ratPresentFl = false; + _seenRatFl = true; + _eyesRunningFl = false; + _shouldRemoveEyes = false; + _randVal = 0; + _defaultDialogPos = Common::Point(264, 43); + _giveBatteriesFl = false; + _resetBatterieText = false; + _alreadyTalkingFl = false; + _startTradingFl = false; + + if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(22, 132); + _game._player._facing = FACING_EAST; + _duringDialogFl = false; + } + + if (!_globals[kHasTalkedToHermit]) { + _scene->loadAnimation(Resources::formatName(611, 'h', -1, EXT_AA, ""), 0); + _scene->loadAnimation(Resources::formatName(203, 'a', -1, EXT_AA, ""), 81); + _nextFrame = 47; + _hermitMode = 1; + _hermitTalkingFl = false; + _hermitMovingFl = true; + _check1Fl = true; + _stickFingerFl = false; + } else { + _hermitMode = 0; + _scene->_hotspots.activate(NOUN_HERMIT, false); + } + + // CHECKME: The last line of the block looks extremely useless + if (_globals[kExecuted_1_11]) { + _dialog1.write(0x294, true); + _dialog1.write(0x292, false); + _globals[kExecuted_1_11] = true; + } + + if (_duringDialogFl) { + _game._player._playerPos = Common::Point(237, 129); + _game._player._facing = FACING_NORTHEAST; + + switch (_hermitDialogNode) { + case 0: + _scene->_userInterface.setup(kInputBuildingSentences); + _hermitDialogNode = 1; + break; + + case 1: + _dialog1.start(); + break; + + case 2: + _dialog2.start(); + break; + + default: + break; + } + displayHermitQuestions(_hermitDisplayedQuestion); + } + + sceneEntrySound(); +} + +void Scene611::step() { + if (_seenRatFl && (_vm->getRandomNumber(1, 100) == 10)) { + _seenRatFl = false; + _scene->_sequences.addTimer(1, 80); + } + + if (_game._trigger == 80) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 8); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _ratPresentFl = true; + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 81); + } else if (_game._trigger == 81) { + int syncId = _globals._sequenceIndexes[1]; + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 20, 0, 0, 0); + int idx = _scene->_dynamicHotspots.add(NOUN_RAT, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _ratHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(272, 154), FACING_SOUTHEAST); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 9, 10); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], syncId); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _ratTimer = _game._player._priorTimer; + } + + if (_ratPresentFl && ((_game._player._priorTimer - _ratTimer) > 1200)) + handleRatMoves(); + + if (!_eyesRunningFl) { + _randVal = _vm->getRandomNumber(1, 30); + _eyesRunningFl = true; + _scene->_sequences.addTimer(1, 70); + } + + if (_game._trigger == 70) { + switch (_randVal) { + case 2: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _shouldRemoveEyes = true; + _scene->_sequences.addTimer(60, 71); + break; + + case 6: + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 12, 3, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 2, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + break; + + case 7: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _shouldRemoveEyes = true; + _scene->_sequences.addTimer(60, 71); + break; + + case 9: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _shouldRemoveEyes = true; + _scene->_sequences.addTimer(60, 71); + break; + + case 13: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 7); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _shouldRemoveEyes = true; + _scene->_sequences.addTimer(60, 71); + break; + + case 14: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 8); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _shouldRemoveEyes = true; + _scene->_sequences.addTimer(60, 71); + break; + + case 15: + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 24, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 5, 8); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + break; + + case 17: + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 20, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 9, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + break; + + case 21: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 9); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _shouldRemoveEyes = true; + _scene->_sequences.addTimer(60, 71); + break; + + case 25: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 10); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _shouldRemoveEyes = true; + _scene->_sequences.addTimer(60, 71); + break; + + case 27: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _shouldRemoveEyes = true; + _scene->_sequences.addTimer(60, 71); + break; + + case 29: + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 20, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + break; + + default: + _scene->_sequences.addTimer(1, 71); + break; + } + } + + if (_game._trigger == 71) { + if (_shouldRemoveEyes) { + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _shouldRemoveEyes = false; + } + _eyesRunningFl = false; + _randVal = 0; + } + + if (_game._trigger == 100) { + if (_alreadyTalkingFl) + _alreadyTalkingFl = false; + else + _hermitMovingFl = true; + } + + if (_stickFingerFl && (_scene->_activeAnimation->getCurrentFrame() == 47)) { + _stickFingerFl = false; + _hermitMovingFl = true; + _hermitMode = 1; + } + + if ((_scene->_activeAnimation->getCurrentFrame() == 240) && _check1Fl) { + _check1Fl = false; + _scene->_kernelMessages.add(Common::Point(33, 88), 0xFDFC, 0, 0, 90, _game.getQuote(0x27E)); + _scene->_sequences.addTimer(120, 120); + } + + if (_game._trigger == 120) { + int msgIdx = _scene->_kernelMessages.add(Common::Point(28, 102), 0xFDFC, 0, 0, 90, _game.getQuote(0x27F)); + _scene->_kernelMessages.setQuoted(msgIdx, 4, true); + _scene->_sequences.addTimer(100, 121); + } + + if (_game._trigger == 121) { + int msgIdx = _scene->_kernelMessages.add(Common::Point(23, 116), 0xFDFC, 0, 0, 90, _game.getQuote(0x280)); + _scene->_kernelMessages.setQuoted(msgIdx, 4, true); + } + + if (_hermitMode == 1) { + if (_startTradingFl) { + _hermitMode = 6; + _hermitMovingFl = false; + _hermitTalkingFl = false; + _scene->_sequences.addTimer(1, 110); + } else if (_hermitTalkingFl) { + _hermitMode = 2; + _nextFrame = 18; + _hermitMovingFl = false; + } else { + switch (_vm->getRandomNumber(1, 5)) { + case 1: + _nextFrame = 46; + break; + + case 2: + _nextFrame = 47; + break; + + case 3: + _nextFrame = 48; + break; + + case 4: + _nextFrame = 49; + break; + + case 5: + _nextFrame = 50; + break; + + default: + break; + } + } + } + + if (_hermitMode == 2) { + if (_startTradingFl) { + _hermitMode = 6; + _hermitMovingFl = false; + _hermitTalkingFl = false; + _scene->_sequences.addTimer(1, 110); + } else if (_hermitMovingFl) { + _hermitMode = 1; + _nextFrame = 47; + _hermitTalkingFl = false; + } else { + switch (_vm->getRandomNumber(1, 4)) { + case 1: + _nextFrame = 18; + break; + + case 2: + _nextFrame = 20; + break; + + case 3: + _nextFrame = 22; + break; + + case 4: + _nextFrame = 24; + break; + + default: + break; + } + } + } + + if (_scene->_activeAnimation->getCurrentFrame() == 254) + _game._player._stepEnabled = true; + + if (_game._trigger == 110) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 111); + } + + if (_game._trigger == 111) { + int syncIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _nextFrame = 1; + } + + if (_game._trigger == 112) { + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._visible = true; + } + + if (_hermitMode == 6) { + if ((_scene->_activeAnimation->getCurrentFrame() == 9) && _check1Fl) { + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 112); + _check1Fl = false; + } + + if ((_scene->_activeAnimation->getCurrentFrame() == 17) && !_check1Fl) { + _nextFrame = 26; + _hermitMode = 4; + _check1Fl = true; + } + } + + if (_hermitMode == 4) { + if ((_scene->_activeAnimation->getCurrentFrame() == 33) && _check1Fl) { + displayHermitQuestions(_hermitDisplayedQuestion); + _nextFrame = 1; + _check1Fl = false; + } + + if ((_scene->_activeAnimation->getCurrentFrame() == 9) && !_check1Fl) { + _nextFrame = 8; + _scene->_sequences.addTimer(1, 113); + _check1Fl = true; + } + } + + if (_game._trigger == 113) { + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 114); + } + + if (_game._trigger == 114) { + _resetBatterieText = true; + int syncIdx = _globals._sequenceIndexes[3]; + _nextFrame = 10; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 115); + } + + if ((_nextFrame >= 0) && (_nextFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(_nextFrame); + _nextFrame = -1; + } + + if (_game._trigger == 115) { + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._visible = true; + if (_hermitDisplayedQuestion == 21) { + _game._player._stepEnabled = false; + handleTrading(); + _hermitMode = 0; + _startTradingFl = false; + _nextFrame = 52; + _globals[kHasTalkedToHermit] = true; + _scene->_hotspots.activate(NOUN_HERMIT, false); + } else { + _game._player._stepEnabled = true; + _hermitMode = 1; + _nextFrame = 47; + _hermitTalkingFl = false; + _startTradingFl = false; + _check1Fl = true; + } + } +} + +void Scene611::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_ALLEY)) + _game._player._walkOffScreenSceneId = 609; + + if (_resetBatterieText) + _scene->_kernelMessages.reset(); +} + +void Scene611::actions() { + if (_game._screenObjects._inputMode == 1) + handleDialog(); + else if ((_action.isAction(VERB_GIVE, NOUN_PHONE_CELLS, NOUN_HERMIT)) || (_action.isAction(VERB_GIVE, NOUN_DURAFAIL_CELLS, NOUN_HERMIT))) { + _action._activeAction._verbId = 0x294; + _giveBatteriesFl = true; + handleSubDialog1(); + } else if (_action.isAction(VERB_GIVE, NOUN_HERMIT)) { + _scene->_kernelMessages.reset(); + + Common::String curQuote = _game.getQuote(0x323); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y), 0xFDFC, 0, 0, 120, curQuote); + + curQuote = _game.getQuote(0x324); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 120, curQuote); + } else if (_game._trigger == 90) { + if (_dialog2.read(0x29C) && _dialog2.read(0x29D) && _dialog2.read(0x29E)) { + handleTalking(180); + if (_vm->getRandomNumber(1, 2) == 1) + displayHermitQuestions(1); + else + displayHermitQuestions(2); + } else { + handleTalking(180); + if (_vm->getRandomNumber(1, 2) == 1) + displayHermitQuestions(3); + else + displayHermitQuestions(4); + } + + _duringDialogFl = true; + if (_dialog2.read(0x29F)) { + _hermitDialogNode = 1; + _dialog1.start(); + _duringDialogFl = true; + } else { + _hermitDialogNode = 2; + _dialog2.write(0x29F, true); + _dialog2.start(); + _duringDialogFl = true; + } + } else if (_action.isAction(VERB_TALKTO, NOUN_HERMIT)) { + if (!_dialog1.read(0x287)) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x27A)); + _scene->_sequences.addTimer(120, 90); + } else { + int nextQuote = 0; + switch (_vm->getRandomNumber(1, 3)) { + case 1: + nextQuote = 0x27B; + break; + + case 2: + nextQuote = 0x27C; + break; + + case 3: + nextQuote = 0x27D; + break; + } + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(nextQuote)); + _scene->_sequences.addTimer(120, 90); + } + } else if ((_action.isAction(VERB_WALKTO) || _action.isAction(VERB_LOOK)) && _action.isObject(NOUN_RAT)) { + switch (_game._trigger) { + case 0: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x279)); + _scene->_sequences.addTimer(60, 1); + break; + + case 1: + handleRatMoves(); + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action._lookFlag) { + if (_globals[kHasTalkedToHermit]) + _vm->_dialogs->show(61111); + else + _vm->_dialogs->show(61110); + } else if (_action.isAction(VERB_LOOK, NOUN_HERMIT)) + _vm->_dialogs->show(61112); + else if (_action.isAction(VERB_LOOK, NOUN_TRASH)) + _vm->_dialogs->show(61113); + else if (_action.isAction(VERB_TAKE, NOUN_TRASH)) + _vm->_dialogs->show(61114); + else if (_action.isAction(VERB_LOOK, NOUN_CARDBOARD_BOX)) + _vm->_dialogs->show(61115); + else if (_action.isAction(VERB_TAKE, NOUN_CARDBOARD_BOX)) + _vm->_dialogs->show(61116); + else if (_action.isAction(VERB_OPEN, NOUN_CARDBOARD_BOX)) + _vm->_dialogs->show(61117); + else if (_action.isAction(VERB_LOOK, NOUN_REFRIGERATOR)) + _vm->_dialogs->show(61118); + else if (_action.isAction(VERB_OPEN, NOUN_REFRIGERATOR)) + _vm->_dialogs->show(61119); + else if (_action.isAction(VERB_TAKE, NOUN_REFRIGERATOR)) + _vm->_dialogs->show(61120); + else if (_action.isAction(VERB_LOOK, NOUN_BUILDING)) + _vm->_dialogs->show(61121); + else if (_action.isAction(VERB_LOOK, NOUN_GRAFFITI)) + _vm->_dialogs->show(61122); + else if (_action.isAction(VERB_LOOK, NOUN_METAL_PIPE)) + _vm->_dialogs->show(61123); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene612::Scene612(MADSEngine *vm) : Scene6xx(vm) { + _actionMode = -1; + _cycleIndex = -1; +} + +void Scene612::synchronize(Common::Serializer &s) { + Scene6xx::synchronize(s); + + s.syncAsSint16LE(_actionMode); + s.syncAsSint16LE(_cycleIndex); +} + +void Scene612::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_FISHING_LINE); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene612::handleWinchMovement() { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 5); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 5, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + // CHECKME: Is the "else" block useful as action is always equal to 1 at this point? + // Or is it a missing bit of code we could fix? + if (_actionMode == 1) { + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 17, 7, 0, 0); + _vm->_sound->command(19); + _game._objects.setRoom(OBJ_PADLOCK_KEY, 1); + _globals[kBoatRaised] = false; + } else { + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 17, 9, 0, 0); + _vm->_sound->command(18); + } + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[4]); + _game._player._visible = true; + break; + + case 3: { + int syncIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, _cycleIndex); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], syncIdx); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2F4)); + _game._player._stepEnabled = true; + + _vm->_dialogs->show(61217); + } + break; + + default: + break; + } +} + +void Scene612::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', -1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('p', -1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXCD_3"); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXRC_6"); + + if ((_globals[kLineStatus] == 2) || (_globals[kLineStatus] == 3)) { + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('f', -1)); + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1); + int idx = _scene->_dynamicHotspots.add(NOUN_FISHING_LINE, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(34, 117), FACING_SOUTHEAST); + } + + if (_globals[kBoatRaised]) + _cycleIndex = -2; + else + _cycleIndex = -1; + + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, _cycleIndex); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + + if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(280, 75); + _game._player._facing = FACING_SOUTHWEST; + _game._player._visible = false; + _game._player._stepEnabled = false; + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 3); + _scene->loadAnimation(formAnimName('R', 1), 70); + } + + sceneEntrySound(); + + if (_scene->_roomChanged) + _game._objects.addToInventory(OBJ_PADLOCK_KEY); + + _game.loadQuoteSet(0x2F5, 0x2F4, 0); +} + +void Scene612::step() { + switch (_game._trigger) { + case 70: + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + _scene->_sequences.addTimer(6, 71); + break; + + case 71: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + break; + + case 72: + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2); + _game._player._stepEnabled = true; + break; + + default: + break; + } +} + +void Scene612::actions() { + if (_action.isAction(VERB_GET_INSIDE, NOUN_CAR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[1]; + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 3); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], syncIdx); + _scene->_sequences.addTimer(6, 2); + } + break; + + case 2: + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], true, 10, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: { + int syncIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], true, -2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _scene->_nextSceneId = 504; + } + break; + + default: + break; + } + } else if (_action.isAction(VERB_UNLOCK, NOUN_PADLOCK_KEY, NOUN_CONTROL_BOX)) { + _cycleIndex = -2; + _actionMode = 1; + handleWinchMovement(); + } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_EXPRESSWAY)) + _vm->_dialogs->show(61210); + else if (_action.isAction(VERB_LOOK, NOUN_ROPE) || _action.isAction(VERB_LOOK, NOUN_ARMATURE)) { + if (_globals[kBoatRaised]) + _vm->_dialogs->show(61211); + else + _vm->_dialogs->show(61212); + } else if (_action.isAction(VERB_TAKE, NOUN_ROPE)) + _vm->_dialogs->show(61213); + else if (_action.isAction(VERB_LOOK, NOUN_CONTROL_BOX)) { + if (_globals[kBoatRaised]) + _vm->_dialogs->show(61214); + else + _vm->_dialogs->show(61216); + } else if (_action.isAction(VERB_OPEN, NOUN_CONTROL_BOX)) + _vm->_dialogs->show(61215); + else if (_action.isAction(VERB_LOOK, NOUN_BUILDINGS)) + _vm->_dialogs->show(61218); + else if (_action.isAction(VERB_LOOK, NOUN_DOME)) + _vm->_dialogs->show(61219); + else if (_action.isAction(VERB_LOOK, NOUN_STATUE)) + _vm->_dialogs->show(61220); + else if (_action.isAction(VERB_LOOK, NOUN_MAINTENANCE_BUILDING)) + _vm->_dialogs->show(61221); + else if (_action.isAction(VERB_OPEN, NOUN_MAINTENANCE_BUILDING)) + _vm->_dialogs->show(61222); + else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(61223); + else if (_action.isAction(VERB_LOOK, NOUN_SUPPORT)) + _vm->_dialogs->show(61224); + else if (_action.isAction(VERB_WALK_DOWN, NOUN_EXPRESSWAY_TO_EAST) || _action.isAction(VERB_WALK_DOWN, NOUN_EXPRESSWAY_TO_WEST)) + _vm->_dialogs->show(61225); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene620::setup() { + _game._player._spritesPrefix = ""; + setAAName(); +} + +void Scene620::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('b', 0)); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_sequences.addTimer(30, 70); + _scene->_userInterface.setup(kInputLimitedSentences); + sceneEntrySound(); +} + +void Scene620::step() { + switch (_game._trigger) { + case 70: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->loadAnimation(formAnimName('E', -1), 71); + break; + + case 71: + if (_scene->_priorSceneId == 751) { + _globals[kCityFlooded] = true; + _globals[kTeleporterRoom + 5] = 0; + _scene->_nextSceneId = 701; + } else if (_scene->_priorSceneId == 752) { + _globals[kCityFlooded] = true; + _globals[kTeleporterRoom + 5] = 0; + _scene->_nextSceneId = 702; + } else if (_scene->_priorSceneId < 501 || _scene->_priorSceneId > 752) { + _globals[kCityFlooded] = true; + _globals[kTeleporterRoom + 5] = 0; + _scene->_nextSceneId = _scene->_priorSceneId; + } else if (_scene->_priorSceneId >= 501 && _scene->_priorSceneId <= 612) { + _globals[kResurrectRoom] = _globals[kHoverCarLocation]; + _game._objects.addToInventory(OBJ_TIMEBOMB); + _globals[kTimebombStatus] = 0; + _globals[kTimebombTimer] = 0; + _scene->_nextSceneId = 605; + } + _game._player._stepEnabled = true; + break; + + default: + break; + } +} + +/*------------------------------------------------------------------------*/ + +} // End of namespace Nebular +} // End of namespace MADS diff --git a/engines/mads/nebular/nebular_scenes6.h b/engines/mads/nebular/nebular_scenes6.h new file mode 100644 index 0000000000..c5cac56626 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes6.h @@ -0,0 +1,322 @@ +/* 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. + * + */ + +#ifndef MADS_NEBULAR_SCENES6_H +#define MADS_NEBULAR_SCENES6_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" + +namespace MADS { + +namespace Nebular { + +class Scene6xx : public NebularScene { +protected: + /** + * Plays an appropriate sound when entering a scene + */ + void setAAName(); + + /** + * Updates the prefix used for getting player sprites for the scene + */ + void setPlayerSpritesPrefix(); + + void sceneEntrySound(); + +public: + Scene6xx(MADSEngine *vm) : NebularScene(vm) {} +}; + +class Scene601 : public Scene6xx{ +public: + Scene601(MADSEngine *vm) : Scene6xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene602 : public Scene6xx{ +private: + int _lastSpriteIdx; + int _lastSequenceIdx; + int _cycleIndex; + int _safeMode; + + void handleSafeActions(); + +public: + Scene602(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene603 : public Scene6xx{ +private: + int _compactCaseHotspotId; + int _noteHotspotId; + +public: + Scene603(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene604 : public Scene6xx{ +private: + int _timebombHotspotId; + int _bombMode; + int _monsterFrame; + + uint32 _monsterTimer; + + bool _monsterActive; + bool _animationActiveFl; + + void handleBombActions(); + +public: + Scene604(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene605 : public Scene6xx{ +public: + Scene605(MADSEngine *vm) : Scene6xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene607 : public Scene6xx{ +private: + uint32 _dogTimer; + uint32 _lastFrameTime; + + bool _dogLoop; + bool _dogEatsRex; + bool _dogBarking; + bool _shopAvailable; + + int _animationMode; + int _animationActive; + int _counter; + + void handleThrowingBone(); + +public: + Scene607(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene608 : public Scene6xx{ +private: + int _carMode; + int _carFrame; + int _carMoveMode; + int _dogDeathMode; + int _carHotspotId; + int _barkCount; + int _polycementHotspotId; + int _animationMode; + int _nextTrigger; + int _throwMode; + + bool _resetPositionsFl; + bool _dogActiveFl; + bool _dogBarkingFl; + bool _dogFirstEncounter; + bool _rexBeingEaten; + bool _dogHitWindow; + bool _checkFl; + bool _dogSquashFl; + bool _dogSafeFl; + bool _buttonPressedonTimeFl; + bool _dogUnderCar; + bool _dogYelping; + + long _dogWindowTimer; + long _dogRunTimer; + + uint32 _dogTimer1; + uint32 _dogTimer2; + + void resetDogVariables(); + void restoreAnimations(); + void setCarAnimations(); + void handleThrowingBone(); + +public: + Scene608(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene609 : public Scene6xx{ +private: + int _videoDoorMode; + + void enterStore(); + +public: + Scene609(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene610 : public Scene6xx{ +private: + int _handsetHotspotId; + int _checkVal; + + bool _cellCharging; + + long _cellChargingTimer; + uint32 _lastFrameTimer; + +public: + Scene610(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene611 : public Scene6xx{ +private: + bool _seenRatFl; + bool _eyesRunningFl; + bool _shouldRemoveEyes; + bool _ratPresentFl; + bool _duringDialogFl; + bool _resetBatterieText; + bool _hermitTalkingFl; + bool _hermitMovingFl; + bool _alreadyTalkingFl; + bool _giveBatteriesFl; + bool _startTradingFl; + bool _check1Fl; + bool _stickFingerFl; + + int _randVal; + int _ratHotspotId; + int _hermitDialogNode; + int _hermitDisplayedQuestion; + int _nextFrame; + int _hermitMode; + + uint32 _ratTimer; + + Conversation _dialog1; + Conversation _dialog2; + + Common::Point _defaultDialogPos; + + void handleTrading(); + void handleRatMoves(); + void handleDialog(); + void handleSubDialog1(); + void handleSubDialog2(); + void handleTalking(int delay); + void setDialogNode(int node); + void displayHermitQuestions(int question); + + bool check2ChargedBatteries(); + bool check4ChargedBatteries(); + +public: + Scene611(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene612 : public Scene6xx{ +private: + int _actionMode; + int _cycleIndex; + + void handleWinchMovement(); + +public: + Scene612(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene620 : public Scene6xx{ +public: + Scene620(MADSEngine *vm) : Scene6xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions() {}; +}; +} // End of namespace Nebular +} // End of namespace MADS + +#endif /* MADS_NEBULAR_SCENES6_H */ diff --git a/engines/mads/nebular/nebular_scenes7.cpp b/engines/mads/nebular/nebular_scenes7.cpp new file mode 100644 index 0000000000..d59f7ff5f3 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes7.cpp @@ -0,0 +1,2678 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "mads/mads.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/nebular/nebular_scenes7.h" + +namespace MADS { + +namespace Nebular { + +void Scene7xx::setAAName() { + _game._aaName = Resources::formatAAName(5); +} + +void Scene7xx::setPlayerSpritesPrefix() { + _vm->_sound->command(5); + + Common::String oldName = _game._player._spritesPrefix; + + if ((_scene->_nextSceneId == 703) || (_scene->_nextSceneId == 704) || (_scene->_nextSceneId == 705) + || (_scene->_nextSceneId == 707) || (_scene->_nextSceneId == 710) || (_scene->_nextSceneId == 711)) + _game._player._spritesPrefix = ""; + else if (_globals[kSexOfRex] == REX_MALE) + _game._player._spritesPrefix = "RXM"; + else + _game._player._spritesPrefix = "ROX"; + + _game._player._scalingVelocity = true; + + if (oldName != _game._player._spritesPrefix) + _game._player._spritesChanged = true; + + _vm->_palette->setEntry(16, 10, 63, 63); + _vm->_palette->setEntry(17, 10, 45, 45); +} + +void Scene7xx::sceneEntrySound() { + if (!_vm->_musicFlag) { + _vm->_sound->command(2); + return; + } + + switch (_scene->_nextSceneId) { + case 701: + case 702: + case 704: + case 705: + case 751: + _vm->_sound->command(38); + break; + case 703: + if (_globals[kMonsterAlive] == 0) + _vm->_sound->command(24); + else + _vm->_sound->command(27); + break; + case 706: + case 707: + case 710: + case 711: + _vm->_sound->command(25); + break; + default: + break; + } +} + +/*------------------------------------------------------------------------*/ + +Scene701::Scene701(MADSEngine *vm) : Scene7xx(vm) { + _fishingLineId = -1; +} + +void Scene701::synchronize(Common::Serializer &s) { + Scene7xx::synchronize(s); + + s.syncAsSint16LE(_fishingLineId); +} + +void Scene701::setup() { + setPlayerSpritesPrefix(); + setAAName(); + + _scene->addActiveVocab(NOUN_BOAT); + _scene->addActiveVocab(VERB_CLIMB_INTO); + _scene->addActiveVocab(NOUN_FISHING_LINE); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene701::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('b', 5)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('b', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('b', 1)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RM202A1"); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('b', 8)); + + if (_scene->_roomChanged) { + _game._objects.addToInventory(OBJ_BINOCULARS); + _game._objects.addToInventory(OBJ_TWINKIFRUIT); + _game._objects.addToInventory(OBJ_BOMB); + _game._objects.addToInventory(OBJ_CHICKEN); + _game._objects.addToInventory(OBJ_BONES); + + _globals[kCityFlooded] = true; + _globals[kLineStatus] = LINE_TIED; + _globals[kBoatRaised] = false; + } + + if (_globals[kBoatStatus] == BOAT_UNFLOODED) { + if (_globals[kBoatRaised]) + _globals[kBoatStatus] = BOAT_GONE; + else if (_globals[kLineStatus] == LINE_TIED) + _globals[kBoatStatus] = BOAT_TIED_FLOATING; + else if (_game._difficulty == DIFFICULTY_HARD) + _globals[kBoatStatus] = BOAT_ADRIFT; + else + _globals[kBoatStatus] = BOAT_TIED; + } + + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + + int boatStatus = (_scene->_priorSceneId == 703) ? BOAT_GONE : _globals[kBoatStatus]; + + switch (boatStatus) { + case BOAT_TIED_FLOATING: + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 20, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 10); + break; + case BOAT_ADRIFT: + _globals._sequenceIndexes[6] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[6], false, 20, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 10); + break; + case BOAT_TIED: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); + break; + case BOAT_GONE: + _scene->_hotspots.activate(NOUN_BOAT, false); + break; + default: + break; + } + + if (_globals[kLineStatus] == LINE_DROPPED || _globals[kLineStatus] == LINE_TIED) { + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_FISHING_LINE, VERB_WALKTO, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _fishingLineId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(234, 129), FACING_NORTHEAST); + } + + if (_scene->_priorSceneId == 702) { + _game._player._playerPos = Common::Point(309, 138); + _game._player._facing = FACING_WEST; + } else if (_scene->_priorSceneId == 710) { + _game._player._playerPos = Common::Point(154, 129); + _game._player._facing = FACING_NORTH; + _game._player._visible = false; + _game._player._stepEnabled = false; + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(155, 129)); + _scene->_sequences.addTimer(15, 60); + } else if (_scene->_priorSceneId == 703) { + _game._player._playerPos = Common::Point(231, 127); + _game._player._facing = FACING_SOUTH; + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->loadAnimation(formAnimName('B', 1), 80); + _vm->_sound->command(28); + } else if (_scene->_priorSceneId != -2 && _scene->_priorSceneId != 620) { + _game._player._playerPos = Common::Point(22, 131); + _game._player._facing = FACING_EAST; + _game._player._stepEnabled = false; + _scene->_sequences.addTimer(60, 70); + } + + _game.loadQuoteSet(0x310, 0x30F, 0); + sceneEntrySound(); +} + +void Scene701::step() { + switch(_game._trigger) { + case 60: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 6, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(155, 129)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 61); + break; + + case 61: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[5]); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + case 70: + _vm->_sound->command(16); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + break; + + case 71: + _game._player.walk(Common::Point(61, 131), FACING_EAST); + _scene->_sequences.addTimer(120, 72); + break; + + case 72: + _vm->_sound->command(17); + _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 73); + break; + + case 73: + _game._player._stepEnabled = true; + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _scene->_kernelMessages.reset(); + break; + + case 80: { + _game._player._visible = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); + int idx = _scene->_dynamicHotspots.add(NOUN_BOAT, VERB_CLIMB_INTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(234, 129), FACING_NORTH); + _globals[kBoatStatus] = BOAT_TIED; + _game._player._stepEnabled = true; + } + break; + + default: + break; + } +} + +void Scene701::preActions() { + if (_action.isAction(VERB_WALKTO, NOUN_EAST_END_OF_PLATFORM)) + _game._player._walkOffScreenSceneId = 702; + + if (_action.isAction(VERB_LOOK, NOUN_BUILDING)) + _game._player.walk(Common::Point(154, 129), FACING_NORTHEAST); + + if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_BUILDING)) + _game._player.walk(Common::Point(154, 129), FACING_NORTH); +} + +void Scene701::actions() { + if (_action.isAction(VERB_WALK_ALONG, NOUN_PLATFORM)) + return; + + if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_BUILDING) && _game._objects[OBJ_VASE]._roomNumber == 706) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 6, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(155, 129)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int temp = _globals._sequenceIndexes[5]; + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, -2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(155, 129)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], temp); + _scene->_sequences.addTimer(15, 2); + } + break; + + case 2: + _scene->_nextSceneId = 710; + break; + + default: + break; + } + } else if (_action.isAction(VERB_STEP_INTO, NOUN_ELEVATOR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _vm->_sound->command(16); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x310, 34, 0, 120, _game.getQuote(0x30D)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: + _game._player.walk(Common::Point(22, 131), FACING_EAST); + _scene->_sequences.addTimer(120, 3); + break; + + case 3: + _vm->_sound->command(17); + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 4); + break; + + case 4: + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _globals[kResurrectRoom] = 701; + _scene->_nextSceneId = 605; + break; + + default: + break; + } + } else if ((_action.isAction(VERB_PULL, NOUN_BOAT) || _action.isAction(VERB_TAKE, NOUN_BOAT) || + _action.isAction(VERB_PULL, NOUN_FISHING_LINE) || _action.isAction(VERB_TAKE, NOUN_FISHING_LINE)) && + !_game._objects.isInInventory(OBJ_FISHING_LINE)) { + if (_globals[kBoatStatus] == BOAT_TIED_FLOATING) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _scene->_dynamicHotspots.remove(_fishingLineId); + _scene->_hotspots.activate(NOUN_BOAT, false); + _game._player._visible = false; + _scene->loadAnimation(formAnimName('E', -1), 1); + break; + + case 1: { + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth (_globals._sequenceIndexes[2], 9); + int idx = _scene->_dynamicHotspots.add(NOUN_BOAT, VERB_CLIMB_INTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(231, 127), FACING_NORTH); + _scene->_sequences.addTimer(15, 2); + } + break; + + case 2: + _globals[kBoatStatus] = BOAT_TIED; + _globals[kLineStatus] = LINE_NOW_UNTIED; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_globals[kBoatStatus] == BOAT_TIED) { + _vm->_dialogs->show(70125); + } else if (_globals[kLineStatus] == LINE_DROPPED) { + _globals[kLineStatus] = LINE_NOW_UNTIED; + _game._objects.addToInventory(OBJ_FISHING_LINE); + _vm->_sound->command(15); + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _vm->_dialogs->showItem(OBJ_FISHING_LINE, 70126); + } else { + _vm->_dialogs->show(70127); + } + } else if (_action.isAction(VERB_CLIMB_INTO, NOUN_BOAT) && _globals[kBoatStatus] == BOAT_TIED) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _game._player._visible = false; + _scene->loadAnimation(formAnimName('B', 0), 1); + break; + + case 1: + _scene->_nextSceneId = 703; + break; + + default: + break; + } + } else if (_action._lookFlag) { + if (_globals[kBoatStatus] != BOAT_GONE) { + if (_globals[kBoatStatus] == BOAT_TIED) + _vm->_dialogs->show(70128); + else + _vm->_dialogs->show(70110); + } else + _vm->_dialogs->show(70111); + } else if (_action.isAction(VERB_LOOK, NOUN_SUBMERGED_CITY)) + _vm->_dialogs->show(70112); + else if (_action.isAction(VERB_LOOK, 0)) + _vm->_dialogs->show(70113); + else if (_action.isAction(VERB_LOOK, NOUN_PLATFORM)) + _vm->_dialogs->show(70114); + else if (_action.isAction(VERB_LOOK, NOUN_CEMENT_PYLON)) + _vm->_dialogs->show(70115); + else if (_action.isAction(VERB_LOOK, NOUN_HOOK)) { + if (_globals[kLineStatus] == LINE_NOT_DROPPED || _globals[kLineStatus] == LINE_NOW_UNTIED) + _vm->_dialogs->show(70116); + else + _vm->_dialogs->show(70117); + } else if (_action.isAction(VERB_LOOK, NOUN_ROCK)) + _vm->_dialogs->show(70118); + else if (_action.isAction(VERB_TAKE, NOUN_ROCK)) + _vm->_dialogs->show(70119); + else if (_action.isAction(VERB_LOOK, NOUN_EAST_END_OF_PLATFORM)) + _vm->_dialogs->show(70120); + else if (_action.isAction(VERB_LOOK, NOUN_BUILDING)) + _vm->_dialogs->show(70121); + else if (_action.isAction(VERB_LOOK, NOUN_BOAT)) { + if (_globals[kBoatStatus] == BOAT_ADRIFT || _globals[kBoatStatus] == BOAT_TIED_FLOATING) + _vm->_dialogs->show(70122); + else + _vm->_dialogs->show(70123); + } else if (_action.isAction(VERB_CAST, NOUN_FISHING_ROD, NOUN_BOAT) && _game._objects.isInInventory(OBJ_FISHING_LINE)) + _vm->_dialogs->show(70124); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene702::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene702::enter() { + _globals._spriteIndexes[12] = _scene->_sprites.addSprites("*RXMBD_8"); + + if (_scene->_priorSceneId == 701) { + _game._player._playerPos = Common::Point(13, 145); + _game._player._facing = FACING_EAST; + } else if (_scene->_priorSceneId != -2 && _scene->_priorSceneId != 620) { + _game._player._playerPos = Common::Point(289, 138); + _game._player.walk(Common::Point(262, 148), FACING_WEST); + _game._player._facing = FACING_WEST; + _game._player._visible = true; + } + + if (_game._globals[kTeleporterCommand]) { + switch(_game._globals[kTeleporterCommand]) { + case TELEPORTER_BEAM_OUT: + case TELEPORTER_WRONG: + case TELEPORTER_STEP_OUT: + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + default: + break; + } + + _game._globals[kTeleporterCommand] = TELEPORTER_NONE; + } + + sceneEntrySound(); +} + +void Scene702::preActions() { + if (_action.isAction(VERB_WALKTO, NOUN_WEST_END_OF_PLATFORM)) + _game._player._walkOffScreenSceneId = 701; +} + +void Scene702::actions() { + if (_action.isAction(VERB_WALK_ALONG, NOUN_PLATFORM)) + ; // Only set the action as finished + else if (_action.isAction(VERB_STEP_INTO, NOUN_TELEPORTER)) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_nextSceneId = 711; + } else if (_action.isAction(VERB_TAKE, NOUN_BONES) && (_action._mainObjectSource == 4) && (!_game._objects.isInInventory(OBJ_BONES) || _game._trigger)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 5, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[12]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_SPRITE, 4, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + case 1: + _vm->_sound->command(0xF); + if (_game._objects.isInInventory(OBJ_BONE)) + _game._objects.setRoom(OBJ_BONE, 1); + _game._objects.addToInventory(OBJ_BONES); + _vm->_dialogs->show(OBJ_BONES, 70218); + break; + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[12]); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + default: + break; + } + } else if (_action._lookFlag) + _vm->_dialogs->show(70210); + else if (_action.isAction(VERB_LOOK, NOUN_PLATFORM)) + _vm->_dialogs->show(70211); + else if (_action.isAction(VERB_LOOK, NOUN_CEMENT_BLOCK)) + _vm->_dialogs->show(70212); + else if (_action.isAction(VERB_LOOK, NOUN_ROCK)) + _vm->_dialogs->show(70213); + else if (_action.isAction(VERB_TAKE, NOUN_ROCK)) + _vm->_dialogs->show(70214); + else if (_action.isAction(VERB_LOOK, NOUN_WEST_END_OF_PLATFORM)) + _vm->_dialogs->show(70215); + else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER)) + _vm->_dialogs->show(70216); + else if (_action.isAction(VERB_LOOK, NOUN_BONES) && (_action._mainObjectSource == 4)) + _vm->_dialogs->show(70217); + else if (_action.isAction(VERB_TAKE, NOUN_BONES) && (_action._mainObjectSource == 4)) { + if (_game._objects.isInInventory(OBJ_BONES)) + _vm->_dialogs->show(70219); + } else if (_action.isAction(VERB_LOOK, NOUN_SUBMERGED_CITY)) + _vm->_dialogs->show(70220); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene703::Scene703(MADSEngine *vm) : Scene7xx(vm) { + _monsterMode = -1; + _boatFrame = -1; + _curSequence = -1; + _boatDir = -1; + + _useBomb = false; + _startMonsterTimer = false; + _rexDeathFl = false; + _restartTrigger70Fl = false; + + _lastFrameTime = 0; + _monsterTime = 0; +} + +void Scene703::synchronize(Common::Serializer &s) { + Scene7xx::synchronize(s); + + s.syncAsSint16LE(_monsterMode); + s.syncAsSint16LE(_boatFrame); + s.syncAsSint16LE(_curSequence); + s.syncAsSint16LE(_boatDir); + + s.syncAsByte(_useBomb); + s.syncAsByte(_startMonsterTimer); + s.syncAsByte(_rexDeathFl); + s.syncAsByte(_restartTrigger70Fl); + + s.syncAsUint32LE(_lastFrameTime); + s.syncAsUint32LE(_monsterTime); +} + +void Scene703::setup() { + _game._player._spritesPrefix = ""; + setAAName(); +} + +void Scene703::handleBottleInterface() { + switch (_globals[kBottleStatus]) { + case 0: + _dialog1.write(0x311, true); + _dialog1.write(0x312, true); + _dialog1.write(0x313, true); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + case 1: + _dialog1.write(0x311, false); + _dialog1.write(0x312, true); + _dialog1.write(0x313, true); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + case 2: + _dialog1.write(0x311, false); + _dialog1.write(0x312, false); + _dialog1.write(0x313, true); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + case 3: + _dialog1.write(0x311, false); + _dialog1.write(0x312, false); + _dialog1.write(0x313, false); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + default: + break; + } +} + +void Scene703::setBottleSequence() { + _scene->_userInterface.setup(kInputBuildingSentences); + _game._player._stepEnabled = false; + if (_boatDir == 2) + _curSequence = 6; + else + _curSequence = 7; +} + +void Scene703::handleFillBottle(int quote) { + switch (quote) { + case 0x311: + _globals[kBottleStatus] = 1; + setBottleSequence(); + break; + + case 0x312: + _globals[kBottleStatus] = 2; + setBottleSequence(); + break; + + case 0x313: + _globals[kBottleStatus] = 3; + setBottleSequence(); + break; + + case 0x314: + _globals[kBottleStatus] = 4; + setBottleSequence(); + break; + + case 0x315: + _scene->_userInterface.setup(kInputBuildingSentences); + break; + + default: + break; + } +} + +void Scene703::enter() { + _game._player._visible = false; + + if (!_game._visitedScenes._sceneRevisited) { + if (_scene->_priorSceneId == 704) + _globals[kMonsterAlive] = false; + else + _globals[kMonsterAlive] = true; + } + + _startMonsterTimer = true; + _rexDeathFl = true; + _monsterTime = 0; + _restartTrigger70Fl = true; + _useBomb = false; + _boatFrame = -1; + + if (!_globals[kMonsterAlive]) + _scene->_hotspots.activate(NOUN_SEA_MONSTER, false); + + if (_scene->_priorSceneId == 704) { + _game._player._stepEnabled = false; + _curSequence = 2; + _boatDir = 2; + _monsterMode = 0; + _scene->loadAnimation(formAnimName('A', -1)); + _scene->_activeAnimation->setCurrentFrame(34); + } else if (_scene->_priorSceneId != -2) { + _game._player._stepEnabled = false; + _boatDir = 1; + if (_globals[kMonsterAlive]) { + _monsterMode = 1; + _curSequence = 0; + _scene->loadAnimation(formAnimName('B', -1)); + } else { + _curSequence = 0; + _monsterMode = 0; + _scene->loadAnimation(formAnimName('A', -1)); + } + } else if (_globals[kMonsterAlive]) { + _curSequence = 0; + _boatDir = 1; + _monsterMode = 1; + _scene->loadAnimation(formAnimName('B', -1)); + _scene->_activeAnimation->setCurrentFrame(39); + } else if (_boatDir == 1) { + _curSequence = 0; + _monsterMode = 0; + _scene->loadAnimation(formAnimName('A', -1)); + _scene->_activeAnimation->setCurrentFrame(9); + } else if (_boatDir == 2) { + _curSequence = 0; + _monsterMode = 0; + _scene->loadAnimation(formAnimName('A', -1)); + _scene->_activeAnimation->setCurrentFrame(56); + } + + if (_scene->_roomChanged) { + _game._objects.addToInventory(OBJ_TWINKIFRUIT); + _game._objects.addToInventory(OBJ_BOMB); + _game._objects.addToInventory(OBJ_CHICKEN); + _game._objects.addToInventory(OBJ_BONES); + } + + _game.loadQuoteSet(0x311, 0x312, 0x313, 0x314, 0x315, 0); + _dialog1.setup(0x98, 0x311, 0x312, 0x313, 0x314, 0x315, 0); + sceneEntrySound(); + _vm->_sound->command(28); +} + +void Scene703::step() { + if (_startMonsterTimer) { + long diff = _scene->_frameStartTime - _lastFrameTime; + if ((diff >= 0) && (diff <= 12)) + _monsterTime += diff; + else + _monsterTime++; + + _lastFrameTime = _scene->_frameStartTime; + } + + if ((_monsterTime >= 2400) && !_rexDeathFl && !_useBomb) { + _startMonsterTimer = false; + _rexDeathFl = true; + _game._player._stepEnabled = false; + _scene->freeAnimation(); + _monsterMode = 3; + _scene->loadAnimation(formAnimName('D', -1)); + _rexDeathFl = false; + _monsterTime = 0; + } + + + if (_game._trigger == 70) + _scene->_reloadSceneFlag = true; + + if ((_monsterMode == 3) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _boatFrame) { + _boatFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextBoatFrame = -1; + + if (_boatFrame == 62) { + nextBoatFrame = 61; + if (_restartTrigger70Fl) { + _restartTrigger70Fl = false; + _scene->_sequences.addTimer(15, 70); + } + } + + if ((nextBoatFrame >= 0) && (nextBoatFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextBoatFrame); + _boatFrame = nextBoatFrame; + } + } + } + + if (_game._trigger == 70) + _scene->_reloadSceneFlag = true; + + if ((_monsterMode == 0) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _boatFrame) { + _boatFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextBoatFrame = -1; + + switch (_boatFrame) { + case 11: + if (_curSequence == 7) { + _curSequence = 0; + nextBoatFrame = 100; + } else if (_curSequence == 5) + nextBoatFrame = 82; + else if (_curSequence == 1) + nextBoatFrame = 11; + else { + nextBoatFrame = 9; + if (!_game._player._stepEnabled) + _game._player._stepEnabled = true; + } + break; + + case 34: + if (_curSequence != 2) + _scene->_nextSceneId = 704; + break; + + case 57: + if (_curSequence == 6) { + _curSequence = 0; + nextBoatFrame = 91; + } else if (_curSequence == 4) + nextBoatFrame = 73; + else if (_curSequence == 3) + nextBoatFrame = 57; + else { + nextBoatFrame = 56; + if (!_game._player._stepEnabled) + _game._player._stepEnabled = true; + } + break; + + case 73: + _scene->_nextSceneId = 701; + break; + + case 82: + nextBoatFrame = 11; + break; + + case 91: + nextBoatFrame = 57; + break; + + case 100: + nextBoatFrame = 56; + if (!_game._player._stepEnabled) { + _scene->_sequences.addTimer(30, 80); + _game._player._stepEnabled = true; + } + break; + + case 110: + nextBoatFrame = 9; + if (!_game._player._stepEnabled) { + _scene->_sequences.addTimer(30, 80); + _game._player._stepEnabled = true; + } + break; + + default: + break; + } + + if ((nextBoatFrame >= 0) && (nextBoatFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextBoatFrame); + _boatFrame = nextBoatFrame; + } + } + } + + if (_game._trigger == 80) { + switch (_globals[kBottleStatus]) { + case 0: + _vm->_dialogs->show(432); + break; + + case 1: + _vm->_dialogs->show(70324); + break; + + case 2: + _vm->_dialogs->show(70325); + break; + + case 3: + _vm->_dialogs->show(70326); + break; + + case 4: + _vm->_dialogs->show(70327); + break; + + default: + break; + } + } + + + if ((_monsterMode == 1) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _boatFrame) { + _boatFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextBoatFrame = -1; + + switch (_boatFrame) { + case 39: + _game._player._stepEnabled = true; + _startMonsterTimer = true; + _rexDeathFl = false; + break; + + case 40: + case 49: + case 54: + case 67: + case 78: + case 87: + case 96: + case 105: + case 114: + case 123: + if (_curSequence == 8) + nextBoatFrame = 129; + + break; + + case 129: + nextBoatFrame = 39; + break; + + case 151: + _scene->_nextSceneId = 701; + break; + + default: + break; + } + + if ((nextBoatFrame >= 0) && (nextBoatFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextBoatFrame); + _boatFrame = nextBoatFrame; + } + } + } + + if ((_monsterMode == 2) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _boatFrame) { + _boatFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextBoatFrame = -1; + + switch (_boatFrame) { + case 14: + if (!_useBomb) { + if (_game._difficulty == DIFFICULTY_HARD) + _game._objects.setRoom(OBJ_CHICKEN, 1); + else + _vm->_dialogs->show(70319); + } + nextBoatFrame = 80; + break; + + case 33: + if (_game._objects.isInInventory(OBJ_BONES)) { + _game._objects.setRoom(OBJ_BONES, 1); + _game._objects.addToInventory(OBJ_BONE); + } else + _game._objects.setRoom(OBJ_BONE, 1); + + nextBoatFrame = 80; + break; + + case 53: + _game._objects.setRoom(OBJ_TWINKIFRUIT, 1); + nextBoatFrame = 80; + _curSequence = 9; + break; + + case 80: + if (_game._difficulty == DIFFICULTY_HARD) { + _game._objects.setRoom(OBJ_BOMB, 1); + _vm->_dialogs->show(70318); + } else + _vm->_dialogs->show(70317); + + _scene->freeAnimation(); + _monsterMode = 1; + _scene->loadAnimation(formAnimName('B', -1)); + _scene->_activeAnimation->setCurrentFrame(39); + _game._player._stepEnabled = true; + break; + + case 91: + if (!_useBomb) { + _scene->freeAnimation(); + _monsterMode = 1; + _scene->loadAnimation(formAnimName('B', -1)); + _scene->_activeAnimation->setCurrentFrame(39); + _game._player._stepEnabled = true; + } else + _game._objects.setRoom(OBJ_CHICKEN_BOMB, 1); + + break; + + case 126: + _scene->_hotspots.activate(NOUN_SEA_MONSTER, false); + _globals[kMonsterAlive] = false; + _scene->freeAnimation(); + _monsterMode = 0; + _scene->loadAnimation(formAnimName('A', -1)); + _scene->_activeAnimation->setCurrentFrame(9); + _game._player._stepEnabled = true; + if (_game._storyMode == STORYMODE_NAUGHTY) + _vm->_dialogs->show(70321); + else + _vm->_dialogs->show(70322); + + break; + + default: + break; + } + + if ((nextBoatFrame >= 0) && (nextBoatFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextBoatFrame); + _boatFrame = nextBoatFrame; + } + } + } +} + +void Scene703::actions() { + if (_game._screenObjects._inputMode == 1) + handleFillBottle(_action._activeAction._verbId); + else if (_action.isAction(VERB_STEER_TOWARDS, NOUN_DOCK_TO_SOUTH)) { + _game._player._stepEnabled = false; + if (_globals[kMonsterAlive]) + _curSequence = 8; + else if (_boatDir == 1) + _curSequence = 5; + else + _curSequence = 3; + } else if (_action.isAction(VERB_STEER_TOWARDS, NOUN_BUILDING_TO_NORTH)) { + _game._player._stepEnabled = false; + if (_globals[kMonsterAlive]) { + _startMonsterTimer = false; + _rexDeathFl = true; + _monsterTime = 0; + _scene->freeAnimation(); + _monsterMode = 3; + _scene->loadAnimation(formAnimName('D', -1)); + } else if (_boatDir == 2) + _curSequence = 4; + else + _curSequence = 1; + } else if (_action.isAction(VERB_THROW, NOUN_BONE, NOUN_SEA_MONSTER) || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_SEA_MONSTER)) { + _game._player._stepEnabled = false; + _scene->freeAnimation(); + _monsterMode = 2; + _scene->loadAnimation(formAnimName('C', -1)); + _scene->_activeAnimation->setCurrentFrame(19); + } else if (_action.isAction(VERB_THROW, NOUN_CHICKEN, NOUN_SEA_MONSTER)) { + _game._player._stepEnabled = false; + _scene->freeAnimation(); + _monsterMode = 2; + _scene->loadAnimation(formAnimName('C', -1)); + } else if (_action.isAction(VERB_THROW, NOUN_TWINKIFRUIT, NOUN_SEA_MONSTER)) { + _game._player._stepEnabled = false; + _scene->freeAnimation(); + _monsterMode = 2; + _scene->loadAnimation(formAnimName('C', -1)); + _scene->_activeAnimation->setCurrentFrame(39); + } else if (_action.isAction(VERB_THROW, NOUN_BOMB, NOUN_SEA_MONSTER)) { + _game._player._stepEnabled = false; + _scene->freeAnimation(); + _monsterMode = 2; + _scene->loadAnimation(formAnimName('C', -1)); + _scene->_activeAnimation->setCurrentFrame(59); + } else if (_action.isAction(VERB_THROW, NOUN_CHICKEN_BOMB, NOUN_SEA_MONSTER)) { + _useBomb = true; + _game._player._stepEnabled = false; + _scene->freeAnimation(); + _monsterMode = 2; + _scene->loadAnimation(formAnimName('C', -1)); + } else if (_action.isAction(VERB_PUT, NOUN_BOTTLE, NOUN_WATER) || _action.isAction(VERB_FILL, NOUN_BOTTLE, NOUN_WATER)) { + if (_globals[kBottleStatus] != 4) { + handleBottleInterface(); + _dialog1.start(); + } else + _vm->_dialogs->show(70323); + } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_SEA_MONSTER)) { + if (_globals[kMonsterAlive]) + _vm->_dialogs->show(70310); + } else if (_action.isAction(VERB_LOOK, NOUN_WATER)) { + if (!_globals[kMonsterAlive]) + _vm->_dialogs->show(70311); + else + _vm->_dialogs->show(70312); + } else if (_action.isAction(VERB_LOOK, NOUN_BUILDING_TO_NORTH)) { + if (_globals[kMonsterAlive]) + _vm->_dialogs->show(70313); + else if (_game._visitedScenes.exists(710)) + _vm->_dialogs->show(70314); + else + _vm->_dialogs->show(70315); + } else if (_action.isAction(VERB_LOOK, NOUN_VOLCANO_RIM)) + _vm->_dialogs->show(70316); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene704::Scene704(MADSEngine *vm) : Scene7xx(vm) { + _bottleHotspotId = -1; + _boatCurrentFrame = -1; + _animationMode = -1; + _boatDirection = -1; + + _takeBottleFl = false; +} + +void Scene704::synchronize(Common::Serializer &s) { + Scene7xx::synchronize(s); + + s.syncAsSint16LE(_bottleHotspotId); + s.syncAsSint16LE(_boatCurrentFrame); + s.syncAsSint16LE(_animationMode); + s.syncAsSint16LE(_boatDirection); + + s.syncAsByte(_takeBottleFl); +} + +void Scene704::setup() { + _game._player._spritesPrefix = ""; + setAAName(); + _scene->addActiveVocab(NOUN_BOTTLE); + _scene->addActiveVocab(VERB_LOOK_AT); +} + +void Scene704::handleBottleInterface() { + switch (_globals[kBottleStatus]) { + case 0: + _dialog1.write(0x311, true); + _dialog1.write(0x312, true); + _dialog1.write(0x313, true); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + case 1: + _dialog1.write(0x311, false); + _dialog1.write(0x312, true); + _dialog1.write(0x313, true); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + case 2: + _dialog1.write(0x311, false); + _dialog1.write(0x312, false); + _dialog1.write(0x313, true); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + case 3: + _dialog1.write(0x311, false); + _dialog1.write(0x312, false); + _dialog1.write(0x313, false); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + default: + break; + } +} + +void Scene704::setBottleSequence() { + _scene->_userInterface.setup(kInputBuildingSentences); + _game._player._stepEnabled = false; + if (_boatDirection == 2) + _animationMode = 6; + else + _animationMode = 7; +} + +void Scene704::handleFillBottle(int quote) { + switch (quote) { + case 0x311: + _globals[kBottleStatus] = 1; + setBottleSequence(); + break; + + case 0x312: + _globals[kBottleStatus] = 2; + setBottleSequence(); + break; + + case 0x313: + _globals[kBottleStatus] = 3; + setBottleSequence(); + break; + + case 0x314: + _globals[kBottleStatus] = 4; + setBottleSequence(); + break; + + case 0x315: + _scene->_userInterface.setup(kInputBuildingSentences); + break; + + default: + break; + } +} + +void Scene704::enter() { + if (_game._objects[OBJ_BOTTLE]._roomNumber == _scene->_currentSceneId) { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('b', 0)); + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + if (_scene->_priorSceneId == 705) { + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(123, 125)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + } else { + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(190, 122)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2); + } + int idx = _scene->_dynamicHotspots.add(NOUN_BONES, VERB_LOOK_AT, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _bottleHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(-2, 0), FACING_NONE); + } + + _game._player._visible = false; + _takeBottleFl = false; + _boatCurrentFrame = -1; + + if (_scene->_priorSceneId == 705) { + _game._player._stepEnabled = false; + _animationMode = 2; + _boatDirection = 2; + _scene->loadAnimation(formAnimName('A', -1)); + _scene->_activeAnimation->setCurrentFrame(36); + } else if (_scene->_priorSceneId != -2) { + _game._player._stepEnabled = false; + _boatDirection = 1; + _scene->loadAnimation(formAnimName('A', -1)); + } else if (_boatDirection == 1) { + _scene->loadAnimation(formAnimName('A', -1)); + _scene->_activeAnimation->setCurrentFrame(8); + } else if (_boatDirection == 2) { + if (_game._objects[OBJ_BOTTLE]._roomNumber == _scene->_currentSceneId) { + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(123, 125)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + } + _scene->loadAnimation(formAnimName('A', -1)); + _scene->_activeAnimation->setCurrentFrame(57); + } + + if (_scene->_roomChanged) + _globals[kMonsterAlive] = false; + + _game.loadQuoteSet(0x311, 0x312, 0x313, 0x314, 0x315, 0); + _dialog1.setup(0x98, 0x311, 0x312, 0x313, 0x314, 0x315, 0); + + sceneEntrySound(); + _vm->_sound->command(28); +} + +void Scene704::step() { + if (_scene->_activeAnimation != nullptr) { + if (_scene->_activeAnimation->getCurrentFrame() != _boatCurrentFrame) { + _boatCurrentFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextFrame = -1; + + switch (_boatCurrentFrame) { + case 10: + switch (_animationMode) { + case 1: + nextFrame = 10; + break; + case 5: + nextFrame = 74; + break; + case 7: + _animationMode = 0; + nextFrame = 92; + break; + default: + if (!_game._player._stepEnabled) + _game._player._stepEnabled = true; + + nextFrame = 8; + break; + } + break; + + case 36: + if (_animationMode != 2) + _scene->_nextSceneId = 705; + break; + + case 59: + switch (_animationMode) { + case 3: + nextFrame = 59; + break; + + case 4: + nextFrame = 65; + break; + + case 6: + _animationMode = 0; + nextFrame = 83; + break; + + default: + if (!_game._player._stepEnabled) { + _game._player._stepEnabled = true; + } + nextFrame = 57; + break; + } + break; + + case 65: + _scene->_nextSceneId = 703; + break; + + case 74: + nextFrame = 10; + break; + + case 83: + nextFrame = 59; + break; + + case 90: + if (_takeBottleFl) { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_dynamicHotspots.remove(_bottleHotspotId); + _game._objects.addToInventory(OBJ_BOTTLE); + _vm->_sound->command(15); + _vm->_dialogs->showItem(OBJ_BOTTLE, 70415); + } + break; + + case 92: + nextFrame = 57; + if (!_game._player._stepEnabled && !_takeBottleFl) { + _scene->_sequences.addTimer(30, 70); + _game._player._stepEnabled = true; + } + break; + + case 98: + if (_takeBottleFl) { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_dynamicHotspots.remove(_bottleHotspotId); + _game._objects.addToInventory(OBJ_BOTTLE); + _vm->_sound->command(15); + _vm->_dialogs->showItem(OBJ_BOTTLE, 70415); + } + break; + + case 101: + nextFrame = 8; + if (!_game._player._stepEnabled && !_takeBottleFl) { + _scene->_sequences.addTimer(30, 70); + _game._player._stepEnabled = true; + } + break; + + default: + break; + } + + if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextFrame); + _boatCurrentFrame = nextFrame; + } + } + } + + if (_game._trigger == 70) { + switch (_globals[kBottleStatus]) { + case 0: + _vm->_dialogs->show(432); + break; + + case 1: + _vm->_dialogs->show(70324); + break; + + case 2: + _vm->_dialogs->show(70325); + break; + + case 3: + _vm->_dialogs->show(70326); + break; + + case 4: + _vm->_dialogs->show(70327); + break; + + default: + break; + } + } +} + +void Scene704::actions() { + if (_game._screenObjects._inputMode == 1) + handleFillBottle(_action._activeAction._verbId); + else if (_action.isAction(VERB_STEER_TOWARDS, NOUN_OPEN_WATER_TO_SOUTH)) { + _game._player._stepEnabled = false; + if (_boatDirection == 1) + _animationMode = 5; + else + _animationMode = 3; + } else if (_action.isAction(VERB_STEER_TOWARDS, NOUN_BUILDING_TO_NORTH)) { + _game._player._stepEnabled = false; + if (_boatDirection == 2) + _animationMode = 4; + else + _animationMode = 1; + } else if (_action.isAction(VERB_TAKE, NOUN_BOTTLE)) { + if (!_game._objects.isInInventory(OBJ_BOTTLE)) { + _game._player._stepEnabled = false; + _takeBottleFl = true; + if (_boatDirection == 2) { + _animationMode = 6; + } else { + _animationMode = 7; + } + } + } else if (_action.isAction(VERB_PUT, NOUN_BOTTLE, NOUN_WATER) || _action.isAction(VERB_FILL, NOUN_BOTTLE, NOUN_WATER)) { + if (_game._objects.isInInventory(OBJ_BOTTLE)) { + if (_globals[kBottleStatus] != 4) { + _takeBottleFl = false; + handleBottleInterface(); + _dialog1.start(); + } else + _vm->_dialogs->show(70323); + } + } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_WATER)) + _vm->_dialogs->show(70410); + else if (_action.isAction(VERB_LOOK, NOUN_BUILDING_TO_NORTH)) { + if (_game._visitedScenes.exists(710)) + _vm->_dialogs->show(70411); + else + _vm->_dialogs->show(70412); + } else if (_action.isAction(VERB_LOOK, NOUN_VOLCANO_RIM)) + _vm->_dialogs->show(70413); + else if (_action.isAction(VERB_LOOK, NOUN_BOTTLE) && (_action._mainObjectSource == 4)) + _vm->_dialogs->show(70414); + else if (_action.isAction(VERB_LOOK, NOUN_OPEN_WATER_TO_SOUTH)) + _vm->_dialogs->show(70416); + else if (_action.isAction(VERB_LOOK, NOUN_SKY)) + _vm->_dialogs->show(70417); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene705::setup() { + _game._player._spritesPrefix = ""; + setAAName(); +} + +void Scene705::synchronize(Common::Serializer &s) { + Scene7xx::synchronize(s); +} + +void Scene705::handleBottleInterface() { + switch (_globals[kBottleStatus]) { + case 0: + _dialog1.write(0x311, true); + _dialog1.write(0x312, true); + _dialog1.write(0x313, true); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + case 1: + _dialog1.write(0x311, false); + _dialog1.write(0x312, true); + _dialog1.write(0x313, true); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + case 2: + _dialog1.write(0x311, false); + _dialog1.write(0x312, false); + _dialog1.write(0x313, true); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + case 3: + _dialog1.write(0x311, false); + _dialog1.write(0x312, false); + _dialog1.write(0x313, false); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + default: + break; + } +} + +void Scene705::setBottleSequence() { + _scene->_userInterface.setup(kInputBuildingSentences); + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->loadAnimation(formAnimName('F', -1), 90); +} + +void Scene705::handleFillBottle(int quote) { + switch (quote) { + case 0x311: + _globals[kBottleStatus] = 1; + setBottleSequence(); + break; + + case 0x312: + _globals[kBottleStatus] = 2; + setBottleSequence(); + break; + + case 0x313: + _globals[kBottleStatus] = 3; + setBottleSequence(); + break; + + case 0x314: + _globals[kBottleStatus] = 4; + setBottleSequence(); + break; + + case 0x315: + _scene->_userInterface.setup(kInputBuildingSentences); + break; + + default: + break; + } +} + +void Scene705::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('b', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('b', 1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 0)); + + _game._player._visible = false; + + if (_scene->_priorSceneId == 706) { + _game._player._stepEnabled = false; + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + } else if (_scene->_priorSceneId != -2) { + _game._player._stepEnabled = false; + _scene->_sequences.addTimer(1, 80); + _vm->_sound->command(28); + } else + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + + if (_scene->_roomChanged) + _game._objects.addToInventory(OBJ_BOTTLE); + + _game.loadQuoteSet(0x311, 0x312, 0x313, 0x314, 0x315, 0); + _dialog1.setup(0x98, 0x311, 0x312, 0x313, 0x314, 0x315, 0); + sceneEntrySound(); +} + +void Scene705::step() { + switch (_game._trigger) { + case 70: + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + break; + + case 71: { + int syncIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _game._player._stepEnabled = true; + } + break; + + default: + break; + } + + switch (_game._trigger) { + case 80: + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 81); + break; + + case 81: { + _vm->_sound->command(19); + int syncIdx = _globals._sequenceIndexes[1]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _game._player._stepEnabled = true; + } + break; + + default: + break; + } + + switch (_game._trigger) { + case 90: + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.addTimer(30, 91); + break; + + case 91: + switch (_globals[kBottleStatus]) { + case 0: + _vm->_dialogs->show(432); + break; + + case 1: + _vm->_dialogs->show(70324); + break; + + case 2: + _vm->_dialogs->show(70325); + break; + + case 3: + _vm->_dialogs->show(70326); + break; + + case 4: + _vm->_dialogs->show(70327); + break; + + default: + break; + } + _game._player._stepEnabled = true; + break; + + default: + break; + } +} + +void Scene705::actions() { + if (_game._screenObjects._inputMode == 1) + handleFillBottle(_action._activeAction._verbId); + else if (_action.isAction(VERB_STEER_TOWARDS, NOUN_OPEN_WATER_TO_SOUTH)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _vm->_sound->command(18); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], syncIdx); + _scene->_nextSceneId = 704; + _game._player._stepEnabled = true; + } + break; + + default: + break; + } + } else if (_action.isAction(VERB_CLIMB_THROUGH, NOUN_WINDOW)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 16); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 16); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _scene->_nextSceneId = 706; + _game._player._stepEnabled = true; + } + break; + + default: + break; + } + } else if (_action.isAction(VERB_FILL, NOUN_BOTTLE, NOUN_WATER) || _action.isAction(VERB_PUT, NOUN_BOTTLE, NOUN_WATER)) { + if (_globals[kBottleStatus] != 4) { + handleBottleInterface(); + _dialog1.start(); + } else + _vm->_dialogs->show(70323); + } if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_WATER)) + _vm->_dialogs->show(70511); + else if (_action.isAction(VERB_LOOK, NOUN_VOLCANO_RIM)) + _vm->_dialogs->show(70512); + else if (_action.isAction(VERB_LOOK, NOUN_OPEN_WATER_TO_SOUTH)) + _vm->_dialogs->show(70513); + else if (_action.isAction(VERB_LOOK, NOUN_SKY)) + _vm->_dialogs->show(70514); + else if (_action.isAction(VERB_LOOK, NOUN_BUILDING)) + _vm->_dialogs->show(70515); + else if (_action.isAction(VERB_LOOK, NOUN_WINDOW)) + _vm->_dialogs->show(70516); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene706::Scene706(MADSEngine *vm) : Scene7xx(vm) { + _vaseHotspotId = -1; + _vaseMode = -1; + _animationMode = -1; + _animationFrame = -1; + + _emptyPedestral = false; +} + +void Scene706::synchronize(Common::Serializer &s) { + Scene7xx::synchronize(s); + + s.syncAsSint16LE(_vaseHotspotId); + s.syncAsSint16LE(_vaseMode); + s.syncAsSint16LE(_animationMode); + s.syncAsSint16LE(_animationFrame); + + s.syncAsByte(_emptyPedestral); +} + +void Scene706::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_BOTTLE); + _scene->addActiveVocab(NOUN_VASE); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene706::handleRexDeath() { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->loadAnimation(formAnimName('a', -1), 2); + break; + + case 2: + if (_animationMode == 1) + _vm->_dialogs->show(70625); + else if (_globals[kBottleStatus] < 2) + _vm->_dialogs->show(70628); + else + _vm->_dialogs->show(70629); + + _game._objects.setRoom(OBJ_VASE, _scene->_currentSceneId); + if (_animationMode == 2) + _game._objects.setRoom(OBJ_BOTTLE, 2); + + _animationMode = 0; + _scene->_reloadSceneFlag = true; + break; + + default: + break; + } +} + +void Scene706::handleTakeVase() { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 4, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 7, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _vm->_sound->command(9); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_dynamicHotspots.remove(_vaseHotspotId); + _game._objects.addToInventory(OBJ_VASE); + if (_vaseMode == 1) { + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 4); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(195, 99)); + int idx = _scene->_dynamicHotspots.add(NOUN_BOTTLE, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(175, 124), FACING_SOUTHEAST); + _game._objects.setRoom(OBJ_BOTTLE, _scene->_currentSceneId); + } + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]); + _game._player._visible = true; + _vm->_dialogs->showItem(OBJ_VASE, 70630); + _game._player._stepEnabled = true; + break; + } +} + +void Scene706::enter() { + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXMRC_3"); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('b', -1)); + + if (!_game._visitedScenes._sceneRevisited) + _emptyPedestral = false; + + if (_game._objects[OBJ_VASE]._roomNumber == _scene->_currentSceneId) { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('v', -1)); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 4); + int idx = _scene->_dynamicHotspots.add(NOUN_VASE, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _vaseHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(175, 124), FACING_SOUTHEAST); + } else if (_game._objects.isInRoom(OBJ_BOTTLE)) { + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 4); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(195, 99)); + int idx = _scene->_dynamicHotspots.add(NOUN_BOTTLE, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(175, 124), FACING_SOUTHEAST); + } + + _game._player._visible = true; + + if (_scene->_priorSceneId == 707) { + _game._player._playerPos = Common::Point(277, 103); + _game._player._facing = FACING_SOUTHWEST; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(167, 152); + _game._player._facing = FACING_NORTH; + } + + if (_globals[kTeleporterCommand]) { + _game._player._visible = false; + _game._player._stepEnabled = false; + + switch (_globals[kTeleporterCommand]) { + case 1: + _scene->loadAnimation(formAnimName('E', 1), 75); + break; + + case 2: + _scene->loadAnimation(formAnimName('E', -1), 80); + break; + + default: + _game._player.walk(Common::Point(264, 116), FACING_SOUTHWEST); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + } + _globals[kTeleporterCommand] = 0; + } + + _animationMode = 0; + + if (_scene->_roomChanged) { + _game._objects.addToInventory(OBJ_BOTTLE); + _globals[kBottleStatus] = 2; + } + + sceneEntrySound(); +} + +void Scene706::step() { + if (_game._trigger == 75) { + _game._player._stepEnabled = true; + _game._player._visible = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player.walk(Common::Point(264, 116), FACING_SOUTHWEST); + } + + if (_game._trigger == 80) { + _globals[kTeleporterCommand] = 1; + _scene->_nextSceneId = _globals[kTeleporterDestination]; + _scene->_reloadSceneFlag = true; + } + + if (_scene->_activeAnimation != nullptr) { + if ((_animationMode != 0) && (_scene->_activeAnimation->getCurrentFrame() != _animationFrame)) { + _animationFrame = _scene->_activeAnimation->getCurrentFrame(); + + if (_animationFrame == 6) { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _game._objects.setRoom(OBJ_VASE, 2); + + if (_animationMode == 2) { + _game._objects.setRoom(OBJ_BOTTLE, 1); + + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 4); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(195, 99)); + int idx = _scene->_dynamicHotspots.add(NOUN_BOTTLE, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(175, 124), FACING_SOUTHEAST); + } + } + } + } +} + +void Scene706::preActions() { + if (_action.isAction(VERB_LOOK, NOUN_PORTRAIT)) + _game._player._needToWalk = true; +} + +void Scene706::actions() { + if (_action.isAction(VERB_WALK_INSIDE, NOUN_TELEPORTER)) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_nextSceneId = 707; + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_EXIT, NOUN_ROOM)) { + _scene->_nextSceneId = 705; + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_VASE)) { + if (_game._difficulty != DIFFICULTY_EASY) { + _animationMode = 1; + handleRexDeath(); + } else if (_game._trigger || !_game._objects.isInInventory(OBJ_VASE)) { + handleTakeVase(); + _emptyPedestral = true; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_PUT, NOUN_BOTTLE, NOUN_PEDESTAL)) { + if ((_globals[kBottleStatus] == 2 && _game._difficulty == DIFFICULTY_HARD) || + (_globals[kBottleStatus] != 0 && _game._difficulty != DIFFICULTY_HARD)) { + if (!_game._objects.isInInventory(OBJ_VASE) || _game._trigger) { + _vaseMode = 1; + handleTakeVase(); + _action._inProgress = false; + return; + } + } else if (_game._objects.isInRoom(OBJ_VASE) || _game._trigger) { + _animationMode = 2; + handleRexDeath(); + _action._inProgress = false; + return; + } + } + + if (_action.isAction(VERB_PUT, NOUN_PEDESTAL) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) { + int objectId = _game._objects.getIdFromDesc(_action._activeAction._objectNameId); + if (_game._objects[objectId].hasQuality(10)) + _vm->_dialogs->show(70626); + else + _vm->_dialogs->show(70627); + } else if (_action.isAction(VERB_TAKE, NOUN_BOTTLE) && _game._objects.isInInventory(OBJ_VASE)) + _vm->_dialogs->show(70631); + else if (_action._lookFlag) { + if (_game._objects[OBJ_VASE]._roomNumber == _scene->_currentSceneId) + _vm->_dialogs->show(70610); + else + _vm->_dialogs->show(70611); + } else if (_action.isAction(VERB_LOOK, NOUN_FLOOR)) + _vm->_dialogs->show(70612); + else if (_action.isAction(VERB_LOOK, NOUN_PILLAR)) + _vm->_dialogs->show(70613); + else if (_action.isAction(VERB_LOOK, NOUN_OLD_TEA_CUP)) + _vm->_dialogs->show(70614); + else if (_action.isAction(VERB_TAKE, NOUN_OLD_TEA_CUP)) + _vm->_dialogs->show(70615); + else if (_action.isAction(VERB_LOOK, NOUN_OLD_VASE)) + _vm->_dialogs->show(70616); + else if (_action.isAction(VERB_LOOK, NOUN_PORTRAIT)) + _vm->_dialogs->show(70617); + else if (_action.isAction(VERB_LOOK, NOUN_NAME_PLATE)) + _vm->_dialogs->show(70618); + else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(70619); + else if (_action.isAction(VERB_LOOK, NOUN_PEDESTAL)) { + if (_game._objects[OBJ_VASE]._roomNumber == _scene->_currentSceneId) + _vm->_dialogs->show(70620); + else if (_game._objects[OBJ_BOTTLE]._roomNumber == _scene->_currentSceneId) + _vm->_dialogs->show(70622); + else + _vm->_dialogs->show(70621); + } else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER)) + _vm->_dialogs->show(70623); + else if (_action.isAction(VERB_LOOK, NOUN_VASE) && (_game._objects[OBJ_VASE]._roomNumber == _scene->_currentSceneId)) + _vm->_dialogs->show(70624); + else if (_action.isAction(VERB_LOOK, NOUN_BOTTLE) && (_action._mainObjectSource == 4)) + _vm->_dialogs->show(70632); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene707::setup() { + _game._player._spritesPrefix = ""; + // The original calls Scene7xx::setAAName() + _game._aaName = Resources::formatAAName(5); +} + +void Scene707::enter() { + _handSpriteId = _scene->_sprites.addSprites("*REXHAND"); + teleporterEnter(); + + // The original uses Scene7xx_sceneEntrySound + if (!_vm->_musicFlag) + _vm->_sound->command(2); + else + _vm->_sound->command(25); +} + +void Scene707::step() { + teleporterStep(); +} + +void Scene707::actions() { + if (teleporterActions()) { + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_VIEWPORT) || _action.isAction(VERB_PEER_THROUGH, NOUN_VIEWPORT)) + _vm->_dialogs->show(70710); + else if (_action.isAction(VERB_LOOK, NOUN_KEYPAD)) + _vm->_dialogs->show(70711); + else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY)) + _vm->_dialogs->show(70712); + else if (_action.isAction(VERB_LOOK, NOUN_0_KEY) || _action.isAction(VERB_LOOK, NOUN_1_KEY) + || _action.isAction(VERB_LOOK, NOUN_2_KEY) || _action.isAction(VERB_LOOK, NOUN_3_KEY) + || _action.isAction(VERB_LOOK, NOUN_4_KEY) || _action.isAction(VERB_LOOK, NOUN_5_KEY) + || _action.isAction(VERB_LOOK, NOUN_6_KEY) || _action.isAction(VERB_LOOK, NOUN_7_KEY) + || _action.isAction(VERB_LOOK, NOUN_8_KEY) || _action.isAction(VERB_LOOK, NOUN_9_KEY) + || _action.isAction(VERB_LOOK, NOUN_SMILE_KEY) || _action.isAction(VERB_LOOK, NOUN_ENTER_KEY) + || _action.isAction(VERB_LOOK, NOUN_FROWN_KEY)) + _vm->_dialogs->show(70713); + else if (_action.isAction(VERB_LOOK, NOUN_DEVICE) || _action._lookFlag) + _vm->_dialogs->show(70714); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene710::setup() { + _game._player._spritesPrefix = ""; + setAAName(); +} + +void Scene710::enter() { + _scene->_userInterface.setup(kInputLimitedSentences); + + if (_game._objects[OBJ_VASE]._roomNumber == 706) { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('g', -1)); + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 0, 0, 0); + } + + _game._player._visible = false; + _scene->_sequences.addTimer(600, 70); + + sceneEntrySound(); +} + +void Scene710::step() { + if (_game._trigger == 70) { + if (_game._globals[kCityFlooded]) + _scene->_nextSceneId = 701; + else + _scene->_nextSceneId = 751; + } +} + +void Scene710::actions() { + if (_action.isAction(VERB_PUT_DOWN, NOUN_BINOCULARS)) { + _game._player._stepEnabled = false; + + if (_game._globals[kCityFlooded]) + _scene->_nextSceneId = 701; + else + _scene->_nextSceneId = 751; + + _action._inProgress = false; + } +} + +/*------------------------------------------------------------------------*/ + +void Scene711::setup() { + // The original was calling Scene7xx::setPlayerSpreitesPrefix() + _vm->_sound->command(5); + Common::String oldName = _game._player._spritesPrefix; + _game._player._spritesPrefix = ""; + _game._player._scalingVelocity = true; + + if (oldName != _game._player._spritesPrefix) + _game._player._spritesChanged = true; + + _vm->_palette->setEntry(16, 10, 63, 63); + _vm->_palette->setEntry(17, 10, 45, 45); + + // The original was calling Scene7xx::setAAName() + _game._aaName = Resources::formatAAName(5); + + _game._player._spritesPrefix = ""; +} + +void Scene711::enter() { + if (_globals[kSexOfRex] == REX_FEMALE) + _handSpriteId = _scene->_sprites.addSprites("*ROXHAND"); + else + _handSpriteId = _scene->_sprites.addSprites("*REXHAND"); + + teleporterEnter(); + + // The original was using Scene7xx_SceneEntrySound() + if (!_vm->_musicFlag) + _vm->_sound->command(2); + else + _vm->_sound->command(25); +} + +void Scene711::step() { + teleporterStep(); +} + +void Scene711::actions() { + if (teleporterActions()) + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene751::Scene751(MADSEngine *vm) : Scene7xx(vm) { + _rexHandingLine = false; +} + +void Scene751::synchronize(Common::Serializer &s) { + Scene7xx::synchronize(s); + + s.syncAsByte(_rexHandingLine); +} + +void Scene751::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_FISHING_LINE); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene751::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*RM701X0"); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('f', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RM202A1"); + + if (!_game._visitedScenes._sceneRevisited) + _rexHandingLine = false; + + if (_globals[kLineStatus] == 2 || _globals[kLineStatus] == 3) { + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + int idx = _scene->_dynamicHotspots.add(NOUN_FISHING_LINE, VERB_WALKTO, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(268, 140), FACING_NORTHWEST); + } + + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + + if (_scene->_priorSceneId == 752) { + _game._player._playerPos = Common::Point(309, 138); + _game._player._facing = FACING_WEST; + } else if (_scene->_priorSceneId == 710) { + _game._player._playerPos = Common::Point(154, 129); + _game._player._facing = FACING_NORTH; + _game._player._visible = false; + _game._player._stepEnabled = false; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(155, 129)); + _scene->_sequences.addTimer(15, 70); + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(22, 131); + _game._player._facing = FACING_EAST; + _game._player._stepEnabled = false; + _scene->_sequences.addTimer(60, 60); + } else if (_rexHandingLine) { + _game._player._visible = false; + _game._player._playerPos = Common::Point(268, 140); + _game._player._facing = FACING_NORTHWEST; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 7); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + } else if (_globals[kLineStatus] == 2) { + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + int idx = _scene->_dynamicHotspots.add(NOUN_FISHING_LINE, VERB_WALKTO, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(268, 140), FACING_NORTHWEST); + } + + if (_scene->_roomChanged) { + _game._objects.addToInventory(OBJ_FISHING_LINE); + _game._objects.addToInventory(OBJ_BINOCULARS); + } + + sceneEntrySound(); + _game.loadQuoteSet(0x30A, 0x30B, 0x30C, 0x30D, 0x30E, 0); + + if (_globals[kTimebombTimer] > 0) + _globals[kTimebombTimer] = 10200; +} + +void Scene751::step() { + switch (_game._trigger) { + case 70: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 6, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(155, 129)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + break; + + case 71: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[4]); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + + if ((_globals[kTimebombTimer] >= 10800) && (_globals[kTimebombStatus] == 1)) { + _globals[kTimebombStatus] = 3; + _globals[kTimebombTimer] = 0; + _globals[kCheckDaemonTimebomb] = false; + _scene->_nextSceneId = 620; + } + + switch (_game._trigger) { + case 60: + _vm->_sound->command(16); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 61); + break; + + case 61: + _game._player.walk(Common::Point(61, 131), FACING_EAST); + _scene->_sequences.addTimer(120, 62); + break; + + case 62: + _vm->_sound->command(17); + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 63); + break; + + case 63: + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _game._player._stepEnabled = true; + _scene->_kernelMessages.reset(); + break; + + default: + break; + } +} + +void Scene751::preActions() { + if (_action.isAction(VERB_LOOK, NOUN_TALL_BUILDING)) + _game._player.walk(Common::Point(154, 129), FACING_NORTHEAST); + + if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_TALL_BUILDING)) + _game._player.walk(Common::Point(154, 129), FACING_NORTH); + + if (_action.isAction(VERB_WALKTO, NOUN_EAST_END_OF_PLATFORM)) + _game._player._walkOffScreenSceneId = 752; + + if (!_rexHandingLine) + return; + + if (_action.isAction(VERB_LOOK) || _action.isObject(NOUN_FISHING_LINE) || _action.isAction(VERB_TALKTO)) + _game._player._needToWalk = false; + + if ((!_action.isAction(VERB_PUT, NOUN_FISHING_LINE, NOUN_HOOK) || !_action.isAction(VERB_TIE, NOUN_FISHING_LINE, NOUN_HOOK) || !_action.isAction(VERB_ATTACH, NOUN_FISHING_LINE, NOUN_HOOK)) + && (_game._player._needToWalk)) { + switch (_game._trigger) { + case 0: + _game._player._readyToWalk = false; + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 11, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, 7); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + _game._player._visible = true; + _rexHandingLine = false; + _game._player._stepEnabled = true; + _game._player._readyToWalk = true; + break; + + default: + break; + } + } +} + +void Scene751::actions() { + if (_action.isAction(VERB_WALK_ALONG, NOUN_PLATFORM)) + ; // Nothing + else if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_TALL_BUILDING)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(155, 129)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(155, 129)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx); + _scene->_sequences.addTimer(15, 2); + } + break; + + case 2: + _scene->_nextSceneId = 710; + break; + + default: + break; + } + } else if (_action.isAction(VERB_STEP_INTO, NOUN_ELEVATOR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _vm->_sound->command(16); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x30D)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: + _game._player.walk(Common::Point(22, 131), FACING_EAST); + _scene->_sequences.addTimer(120, 3); + break; + + case 3: + _vm->_sound->command(17); + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 4); + break; + + case 4: + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _scene->_sequences.addTimer(60, 5); + break; + + case 5: + _game._player._stepEnabled = true; + _scene->_nextSceneId = 513; + break; + + default: + break; + } + } else if (_action.isAction(VERB_PUT, NOUN_FISHING_LINE, NOUN_HOOK) || _action.isAction(VERB_TIE, NOUN_FISHING_LINE, NOUN_HOOK) || _action.isAction(VERB_ATTACH, NOUN_FISHING_LINE, NOUN_HOOK)) { + if (_globals[kLineStatus] == 1) { + switch (_game._trigger) { + case 0: + _game._player._visible = false; + _game._player._stepEnabled = false; + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, 6); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], -1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 7); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], syncIdx); + _scene->_sequences.addTimer(30, 2); + } + break; + + case 2: + _rexHandingLine = true; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 8, -2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: { + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + _game._player._visible = true; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + int idx = _scene->_dynamicHotspots.add(NOUN_FISHING_LINE, VERB_WALKTO, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(268, 140), FACING_NORTHWEST); + _scene->_kernelMessages.reset(); + _game._objects.setRoom(OBJ_FISHING_LINE, _scene->_currentSceneId); + _rexHandingLine = false; + _globals[kLineStatus] = 2; + _game._player._stepEnabled = true; + _vm->_dialogs->show(75120); + } + break; + + default: + break; + } + } + } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_CITY)) + _vm->_dialogs->show(75110); + else if (_action.isAction(VERB_LOOK, NOUN_ELEVATOR)) + _vm->_dialogs->show(75112); + else if (_action.isAction(VERB_LOOK, NOUN_PLATFORM)) + _vm->_dialogs->show(75113); + else if (_action.isAction(VERB_LOOK, NOUN_CEMENT_PYLON)) + _vm->_dialogs->show(75114); + else if ((_action.isAction(VERB_LOOK, NOUN_HOOK) || _action.isAction(VERB_LOOK, NOUN_FISHING_LINE)) + && (_globals[kLineStatus] == 2 || _globals[kLineStatus] == 3)) + _vm->_dialogs->show(75116); + else if (_action.isAction(VERB_LOOK, NOUN_HOOK)) + _vm->_dialogs->show(75115); + else if (_action.isAction(VERB_LOOK, NOUN_ROCK)) + _vm->_dialogs->show(75117); + else if (_action.isAction(VERB_TAKE, NOUN_ROCK)) + _vm->_dialogs->show(75118); + else if (_action.isAction(VERB_LOOK, NOUN_EAST_END_OF_PLATFORM)) + _vm->_dialogs->show(75119); + else if (_action.isAction(VERB_TAKE, NOUN_FISHING_LINE) && (_globals[kLineStatus] == 3 || _globals[kLineStatus] == 2)) + _vm->_dialogs->show(75121); + else if (_action.isAction(VERB_LOOK, NOUN_TALL_BUILDING)) + _vm->_dialogs->show(75122); + else if (_action.isAction(VERB_TIE, NOUN_FISHING_LINE, NOUN_CEMENT_PYLON) || _action.isAction(VERB_ATTACH, NOUN_FISHING_LINE, NOUN_CEMENT_PYLON)) + _vm->_dialogs->show(75123); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene752::Scene752(MADSEngine *vm) : Scene7xx(vm) { + _cardId = -1; +} + +void Scene752::synchronize(Common::Serializer &s) { + Scene7xx::synchronize(s); + + s.syncAsSint16LE(_cardId); +} + +void Scene752::setup() { + setPlayerSpritesPrefix(); + setAAName(); + + _scene->addActiveVocab(NOUN_ID_CARD); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(VERB_LOOK_AT); + _scene->addActiveVocab(NOUN_LASER_BEAM); +} + +void Scene752::enter() { + _globals._spriteIndexes[14] = _scene->_sprites.addSprites(formAnimName('l', -1)); + _globals._spriteIndexes[12] = _scene->_sprites.addSprites("*RXMBD_8"); + + if (_scene->_priorSceneId == 751) { + _game._player._playerPos = Common::Point(13, 145); + _game._player._facing = FACING_EAST; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(289, 138); + _game._player.walk(Common::Point(262, 148), FACING_WEST); + _game._player._facing = FACING_WEST; + _game._player._visible = true; + } + + if (_game._objects[OBJ_ID_CARD]._roomNumber == 752) { + _globals._spriteIndexes[13] = _scene->_sprites.addSprites(formAnimName('i', -1)); + _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_ID_CARD, VERB_WALKTO, _globals._sequenceIndexes[13], Common::Rect(0, 0, 0, 0)); + _cardId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(234, 135), FACING_NORTH); + } + + if (_game._globals[kLaserHoleIsThere]) { + _globals._sequenceIndexes[14] = _scene->_sequences.startCycle(_globals._spriteIndexes[14], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[14], 13); + int idx = _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_LOOK_AT, _globals._sequenceIndexes[14], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(215, 130), FACING_NORTHWEST); + } + + if (_game._globals[kTeleporterCommand]) { + switch(_game._globals[kTeleporterCommand]) { + case TELEPORTER_BEAM_OUT: + case TELEPORTER_WRONG: + case TELEPORTER_STEP_OUT: + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + default: + break; + } + + _game._globals[kTeleporterCommand] = TELEPORTER_NONE; + } + + if (_globals._timebombTimer > 0) + _globals._timebombTimer = 10800 - 600; + + sceneEntrySound(); +} + +void Scene752::step() { + if (_globals._timebombTimer >= 10800 && _game._globals[kTimebombStatus] == TIMEBOMB_ACTIVATED) { + _globals[kTimebombStatus] = TIMEBOMB_DEAD; + _globals._timebombTimer = 0; + _globals[kCheckDaemonTimebomb] = false; + _scene->_nextSceneId = 620; + } +} + +void Scene752::preActions() { + if (_action.isAction(VERB_WALKTO, NOUN_WEST_END_OF_PLATFORM)) { + _game._player._walkOffScreenSceneId = 751; + } +} + +void Scene752::actions() { + if (_action.isAction(VERB_WALK_ALONG, NOUN_PLATFORM)) + ; + else if (_action.isAction(VERB_STEP_INTO, NOUN_TELEPORTER)) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_nextSceneId = 711; + } else if (_action.isAction(VERB_TAKE, NOUN_ID_CARD) && (!_game._objects.isInInventory(OBJ_ID_CARD) || _game._trigger)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 5, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[12]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_SPRITE, 4, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + case 1: + _vm->_sound->command(0xF); + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _game._objects.addToInventory(OBJ_ID_CARD); + _scene->_dynamicHotspots.remove(_cardId); + _vm->_dialogs->show(OBJ_ID_CARD, 830); + break; + case 2: + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + default: + break; + } + } else if (_action.isAction(VERB_TAKE, NOUN_BONES) && (_action._mainObjectSource == 4) && (!_game._objects.isInInventory(OBJ_BONES) || _game._trigger)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 5, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[12]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_SPRITE, 4, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + case 1: + _vm->_sound->command(0xF); + if (_game._objects.isInInventory(OBJ_BONE)) + _game._objects.setRoom(OBJ_BONE, 1); + _game._objects.addToInventory(OBJ_BONES); + _vm->_dialogs->show(OBJ_BONES, 75221); + break; + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[12]); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + default: + break; + } + } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_CITY)) { + if (_globals[kLaserHoleIsThere]) + _vm->_dialogs->show(75212); + else + _vm->_dialogs->show(75210); + } else if (_action.isAction(VERB_LOOK, NOUN_PLATFORM)) + _vm->_dialogs->show(75213); + else if (_action.isAction(VERB_LOOK, NOUN_CEMENT_BLOCK)) + _vm->_dialogs->show(75214); + else if (_action.isAction(VERB_LOOK, NOUN_ROCK)) + _vm->_dialogs->show(75215); + else if (_action.isAction(VERB_TAKE, NOUN_ROCK)) + _vm->_dialogs->show(75216); + else if (_action.isAction(VERB_LOOK, NOUN_WEST_END_OF_PLATFORM)) + _vm->_dialogs->show(75217); + else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER)) + _vm->_dialogs->show(75218); + else if ((_action.isAction(VERB_LOOK, NOUN_BONES) || _action.isAction(VERB_LOOK, NOUN_ID_CARD)) && (_action._mainObjectSource == 4)) { + if (_game._objects[OBJ_ID_CARD]._roomNumber == 752) + _vm->_dialogs->show(75219); + else + _vm->_dialogs->show(75220); + } else if (_action.isAction(VERB_TAKE, NOUN_BONES) && (_action._mainObjectSource == 4)) { + if (_game._objects.isInInventory(OBJ_BONES)) + _vm->_dialogs->show(75222); + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +} // End of namespace Nebular +} // End of namespace MADS diff --git a/engines/mads/nebular/nebular_scenes7.h b/engines/mads/nebular/nebular_scenes7.h new file mode 100644 index 0000000000..dfb3c0f16e --- /dev/null +++ b/engines/mads/nebular/nebular_scenes7.h @@ -0,0 +1,238 @@ +/* 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. + * + */ + +#ifndef MADS_NEBULAR_SCENES7_H +#define MADS_NEBULAR_SCENES7_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" + +namespace MADS { + +namespace Nebular { + +class Scene7xx : public NebularScene { +protected: + /** + * Plays an appropriate sound when entering a scene + */ + void setAAName(); + + /** + * Updates the prefix used for getting player sprites for the scene + */ + void setPlayerSpritesPrefix(); + + void sceneEntrySound(); + +public: + Scene7xx(MADSEngine *vm) : NebularScene(vm) {} +}; + +class Scene701 : public Scene7xx { +private: + int _fishingLineId; + +public: + Scene701(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void preActions(); + virtual void actions(); + virtual void step(); +}; + +class Scene702 : public Scene7xx { +public: + Scene702(MADSEngine *vm) : Scene7xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene703 : public Scene7xx{ +private: + int _monsterMode; + int _boatFrame; + int _curSequence; + int _boatDir; + + bool _useBomb; + bool _startMonsterTimer; + bool _rexDeathFl; + bool _restartTrigger70Fl; + + uint32 _lastFrameTime; + uint32 _monsterTime; + + Conversation _dialog1; + + void handleBottleInterface(); + void setBottleSequence(); + void handleFillBottle(int quote); + +public: + Scene703(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene704 : public Scene7xx{ +private: + int _bottleHotspotId; + int _boatCurrentFrame; + int _animationMode; + int _boatDirection; + + bool _takeBottleFl; + + Conversation _dialog1; + + void handleFillBottle(int quote); + void setBottleSequence(); + void handleBottleInterface(); + +public: + Scene704(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene705 : public Scene7xx{ +private: + Conversation _dialog1; + + void handleFillBottle(int quote); + void setBottleSequence(); + void handleBottleInterface(); + +public: + Scene705(MADSEngine *vm) : Scene7xx(vm) {} + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene706 : public Scene7xx{ +private: + int _vaseHotspotId; + int _vaseMode; + int _animationMode; + int _animationFrame; + + bool _emptyPedestral; + + void handleTakeVase(); + void handleRexDeath(); + +public: + Scene706(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene707 : public SceneTeleporter { +public: + Scene707(MADSEngine *vm) : SceneTeleporter(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene710 : public Scene7xx { +public: + Scene710(MADSEngine *vm) : Scene7xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene711 : public SceneTeleporter { +public: + Scene711(MADSEngine *vm) : SceneTeleporter(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene751 : public Scene7xx{ +private: + bool _rexHandingLine; + +public: + Scene751(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene752 : public Scene7xx { +private: + int _cardId; + +public: + Scene752(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +} // End of namespace Nebular +} // End of namespace MADS + +#endif /* MADS_NEBULAR_SCENES7_H */ diff --git a/engines/mads/nebular/nebular_scenes8.cpp b/engines/mads/nebular/nebular_scenes8.cpp new file mode 100644 index 0000000000..66502831cc --- /dev/null +++ b/engines/mads/nebular/nebular_scenes8.cpp @@ -0,0 +1,1524 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "mads/mads.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/nebular/nebular_scenes8.h" + +namespace MADS { + +namespace Nebular { + +void Scene8xx::setPlayerSpritesPrefix() { + _vm->_sound->command(5); + if ((_globals[kFromCockpit] && !_globals[kExitShip]) || + _scene->_nextSceneId == 804 || _scene->_nextSceneId == 805 || + _scene->_nextSceneId == 808 || _scene->_nextSceneId == 810) { + _game._player._spritesPrefix = ""; + } else + _game._player._spritesPrefix = _globals[kSexOfRex] == SEX_FEMALE ? "ROX" : "RXM"; + + _vm->_palette->setEntry(16, 0x0A, 0x3F, 0x3F); + _vm->_palette->setEntry(17, 0x0A, 0x2D, 0x2D); +} + +void Scene8xx::setAAName() { + _game._aaName = Resources::formatAAName(5); +} + +void Scene8xx::sceneEntrySound() { + if (!_vm->_musicFlag) + _vm->_sound->command(2); + else { + switch (_scene->_nextSceneId) { + case 801: + case 802: + case 803: + case 804: + case 806: + case 807: + case 808: + _vm->_sound->command(20); + break; + + case 805: + _vm->_sound->command(23); + break; + + case 810: + _vm->_sound->command(10); + break; + + default: + break; + } + } +} + +/*------------------------------------------------------------------------*/ + +Scene801::Scene801(MADSEngine *vm) : Scene8xx(vm) { + _walkThroughDoor = false; +} + +void Scene801::synchronize(Common::Serializer &s) { + Scene8xx::synchronize(s); + + s.syncAsByte(_walkThroughDoor); +} + +void Scene801::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene801::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 2)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 3)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('a', -1)); + + if (_scene->_priorSceneId != 802) { + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 13); + } + + if ((_globals[kCameFromCut]) && (_globals[kCutX] != 0)) { + _game._player._playerPos = Common::Point(_globals[kCutX], _globals[kCutY]); + _game._player._facing = (Facing)_globals[kCutFacing]; + _globals[kCutX] = 0; + _globals[kCameFromCut] = false; + _globals[kReturnFromCut] = false; + _globals[kBeamIsUp] = false; + _globals[kForceBeamDown] = false; + _globals[kDontRepeat] = false; + } else if (_scene->_priorSceneId == 808) { + _game._player._playerPos = Common::Point(148, 110); + _game._player._facing = FACING_NORTH; + } else if (_scene->_priorSceneId == 802) { + _game._player._playerPos = Common::Point(307, 111); + _game._player.walk(Common::Point(270, 118), FACING_WEST); + _game._player._visible = true; + } else if ((_scene->_priorSceneId != -2) && !_globals[kTeleporterCommand]) { + _game._player._playerPos = Common::Point(8, 117); + _game._player.walk(Common::Point(41, 115), FACING_EAST); + _game._player._visible = true; + } + + _globals[kBetweenRooms] = false; + + if (_globals[kTeleporterCommand]) { + _game._player._stepEnabled = false; + switch (_globals[kTeleporterCommand]) { + case 1: + _game._player._playerPos = Common::Point(8, 117); + _globals[kTeleporterUnderstood] = true; + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 13); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 75); + _vm->_sound->command(30); + break; + + case 2: + _game._player._playerPos = Common::Point(8, 117); + _globals[kTeleporterUnderstood] = true; + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 13); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 8090); + _vm->_sound->command(30); + break; + + case 3: + case 4: + _game._player._playerPos = Common::Point(8, 117); + _game._player.walk(Common::Point(41, 115), FACING_EAST); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + _globals[kTeleporterCommand] = 0; + } + + _walkThroughDoor = false; + if (_scene->_priorSceneId == 802) { + _game._player._stepEnabled = false; + _walkThroughDoor = true; + } + + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 11, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], -1, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 14); + + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 9, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], -1, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 14); + + sceneEntrySound(); +} + +void Scene801::step() { + if (_game._trigger == 75) { + if (_globals[kSexOfRex] == REX_FEMALE) { + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 140); + } else { + _game._player._stepEnabled = true; + _game._player._visible = true; + _game._player._playerPos = Common::Point(8, 117); + _game._player.walk(Common::Point(41, 115), FACING_EAST); + } + } + + if (_game._trigger == 140) { + _vm->_sound->command(27); + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 8); + _scene->_sequences.addTimer(100, 141); + } + + if (_game._trigger == 141) { + _scene->_reloadSceneFlag = true; + _scene->_nextSceneId = _scene->_priorSceneId; + _globals[kTeleporterCommand] = 0; + } + + if (_game._trigger == 80) { + _globals[kTeleporterCommand] = 1; + _scene->_nextSceneId = _globals[kTeleporterDestination]; + _scene->_reloadSceneFlag = true; + } + + if (_walkThroughDoor && (_game._player._playerPos == Common::Point(270, 118))) { + _game._player._stepEnabled = false; + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 4, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 10); + _walkThroughDoor = false; + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 120); + } + + if (_game._trigger == 120) { + _vm->_sound->command(12); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 10); + _game._player._stepEnabled = true; + } + + if (_game._trigger == 90) { + _game._player.walk(Common::Point(307, 111), FACING_EAST); + _scene->_sequences.addTimer(80, 130); + } + + if (_game._trigger == 130) { + _vm->_sound->command(12); + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 4, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 10); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 110); + } + + if (_game._trigger == 110) { + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 10); + _scene->_nextSceneId = 802; + } +} + +void Scene801::preActions() { + if (_action.isAction(VERB_LOOK, NOUN_CONTROL_PANEL)) { + _game._player.walk(Common::Point(148, 110), FACING_NORTH); + _game._player._needToWalk = true; + _game._player._readyToWalk = true; + } + + if (_action.isAction(VERB_WALK_INSIDE, NOUN_TELEPORTER) && _globals[kBeamIsUp]) { + _globals[kCutX] = _game._player._playerPos.x; + _globals[kCutY] = _game._player._playerPos.y; + _globals[kCutFacing] = _game._player._facing; + _globals[kForceBeamDown] = true; + _globals[kDontRepeat] = true; + _scene->_nextSceneId = 803; + } +} + +void Scene801::actions() { + if (_action.isAction(VERB_LOOK, NOUN_CONTROL_PANEL)) + _scene->_nextSceneId = 808; + else if (_action.isAction(VERB_WALK_INSIDE, NOUN_TELEPORTER)) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_nextSceneId = 807; + } else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOOR) && (_game._player._playerPos == Common::Point(270, 118))) { + _game._player._stepEnabled = false; + _game._player._facing = FACING_EAST; + _game._player.selectSeries(); + _globals[kBetweenRooms] = true; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 4, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 90); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 13); + _vm->_sound->command(11); + } else if (_action.isAction(VERB_LOOK, NOUN_CEILING)) + _vm->_dialogs->show(80110); + else if (_action.isAction(VERB_LOOK, NOUN_MONITOR)) + _vm->_dialogs->show(80111); + else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER)) + _vm->_dialogs->show(80112); + else if (_action.isAction(VERB_LOOK, NOUN_EQUIPMENT) || _action._lookFlag) + _vm->_dialogs->show(80113); + else if (_action.isAction(VERB_LOOK, NOUN_SPEAKER)) + _vm->_dialogs->show(80114); + else if (_action.isAction(VERB_LOOK, NOUN_EYE_CHART)) + _vm->_dialogs->show(80115); + else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(80116); + else if (_action.isAction(VERB_LOOK, NOUN_DOOR)) + _vm->_dialogs->show(80117); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene802::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_SHIELD_MODULATOR); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_REMOTE); +} + +void Scene802::enter() { + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMRC_8"); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('f', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('f', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('f', 1)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RXMBD_8"); + _globals[kBetweenRooms] = false; + + if ((_globals[kCameFromCut]) && (_globals[kCutX] != 0)) { + _game._player._playerPos.x = _globals[kCutX]; + _game._player._playerPos.y = _globals[kCutY]; + _game._player._facing = (Facing)_globals[kCutFacing]; + _globals[kCutX] = 0; + _globals[kCameFromCut] = false; + _globals[kReturnFromCut] = false; + _globals[kBeamIsUp] = false; + _globals[kForceBeamDown] = false; + _globals[kDontRepeat] = false; + _globals[kAntigravClock] = _scene->_frameStartTime; + } else if (_scene->_priorSceneId == 801) { + _game._player._playerPos = Common::Point(15, 129); + _game._player._facing = FACING_EAST; + } else if (_scene->_priorSceneId == 803) { + _game._player._playerPos = Common::Point(303, 119); + _game._player._facing = FACING_WEST; + + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(15, 129); + _game._player._facing = FACING_EAST; + } + + _game._player._visible = true; + + + + if (_globals[kHasWatchedAntigrav] && !_globals[kRemoteSequenceRan]) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(200, 70); + } + + if ((_globals[kRemoteOnGround]) && (!_game._objects.isInInventory(OBJ_REMOTE))) { + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_REMOTE, VERB_WALKTO,_globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(107, 99), FACING_NORTH); + } + + if (!_game._objects.isInInventory(OBJ_SHIELD_MODULATOR) && !_globals[kShieldModInstalled]) { + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_SHIELD_MODULATOR, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(93, 97), FACING_NORTH); + } + sceneEntrySound(); +} + +void Scene802::step() { + if (_game._trigger == 70) { + _game._player._stepEnabled = false; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 19); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 4, 72); + } + + if (_game._trigger == 71) { + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_REMOTE, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(107, 99), FACING_NORTH); + + _globals[kRemoteSequenceRan] = true; + _globals[kRemoteOnGround] = true; + _game._player._stepEnabled = true; + } + + if (_game._trigger == 72) + _vm->_sound->command(13); +} + +void Scene802::preActions() { + if (_action.isAction(VERB_WALK_TOWARDS, NOUN_BUILDING_TO_WEST)) + _game._player._walkOffScreenSceneId = 801; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_EAST)) { + _game._player._walkOffScreenSceneId = 803; + _globals[kForceBeamDown] = false; + } + + if (_action.isAction(VERB_TAKE, NOUN_SHIP)) + _game._player._needToWalk = false; +} + +void Scene802::actions() { + if (_action.isAction(VERB_TAKE, NOUN_SHIELD_MODULATOR) && !_game._objects.isInInventory(OBJ_SHIELD_MODULATOR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], true, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 2, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _vm->_sound->command(9); + break; + + case 2: + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + _scene->_sequences.addTimer(20, 3); + break; + + case 3: + _game._player._stepEnabled = true; + _game._objects.addToInventory(OBJ_SHIELD_MODULATOR); + _vm->_dialogs->showItem(OBJ_SHIELD_MODULATOR, 80215); + break; + + default: + break; + } + } else if ((_action.isAction(VERB_TAKE, NOUN_REMOTE)) && (!_game._objects.isInInventory(OBJ_REMOTE))) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], true, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 4); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_SPRITE, 4, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _vm->_sound->command(9); + _globals[kRemoteOnGround] = false; + break; + + case 2: + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + _scene->_sequences.addTimer(20, 3); + break; + + case 3: + _game._player._stepEnabled = true; + _game._objects.addToInventory(OBJ_REMOTE); + _vm->_dialogs->showItem(OBJ_REMOTE, 80223); + break; + + default: + break; + } + } else if (!_globals[kRemoteOnGround] && (_game._objects.isInInventory(OBJ_SHIELD_MODULATOR) || _globals[kShieldModInstalled]) + && (_action.isAction(VERB_LOOK, NOUN_LAUNCH_PAD) || _action._lookFlag)) + _vm->_dialogs->show(80210); + else if (!_globals[kRemoteOnGround]&& !_game._objects.isInInventory(OBJ_SHIELD_MODULATOR) && !_globals[kShieldModInstalled] + && (_action.isAction(VERB_LOOK, NOUN_LAUNCH_PAD) || _action._lookFlag)) + _vm->_dialogs->show(80211); + else if (_globals[kRemoteOnGround] && !_game._objects.isInInventory(OBJ_SHIELD_MODULATOR) && !_globals[kShieldModInstalled] + && (_action.isAction(VERB_LOOK, NOUN_LAUNCH_PAD) || _action._lookFlag)) + _vm->_dialogs->show(80213); + else if (_globals[kRemoteOnGround] && (_game._objects.isInInventory(OBJ_SHIELD_MODULATOR) || _globals[kShieldModInstalled]) + && (_action.isAction(VERB_LOOK, NOUN_LAUNCH_PAD) || _action._lookFlag)) + _vm->_dialogs->show(80212); + else if (!_game._objects.isInInventory(OBJ_SHIELD_MODULATOR) && !_globals[kShieldModInstalled] && _action.isAction(VERB_LOOK, NOUN_SHIELD_MODULATOR)) + _vm->_dialogs->show(80214); + else if (_globals[kRemoteOnGround] && _action.isAction(VERB_LOOK, NOUN_REMOTE)) + _vm->_dialogs->show(80216); + else if (_action.isAction(VERB_LOOK, NOUN_SHIP)) { + if ((!_game._objects.isInInventory(OBJ_SHIELD_MODULATOR)) && (!_globals[kShieldModInstalled])) + _vm->_dialogs->show(80218); + else + _vm->_dialogs->show(80217); + } else if (_action.isAction(VERB_LOOK, NOUN_BUSHES)) + _vm->_dialogs->show(80219); + else if (_action.isAction(VERB_LOOK, NOUN_PATH_TO_EAST)) + _vm->_dialogs->show(80220); + else if (_action.isAction(VERB_LOOK, NOUN_SKY)) + _vm->_dialogs->show(80221); + else if (_action.isAction(VERB_TAKE, NOUN_SHIP)) + _vm->_dialogs->show(80222); + else if (_action.isAction(VERB_LOOK, NOUN_TREE) || _action.isAction(VERB_LOOK, NOUN_TREES)) + _vm->_dialogs->show(80224); + else if (_action.isAction(VERB_LOOK, NOUN_BUILDING_TO_WEST)) + _vm->_dialogs->show(80225); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene803::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_GUTS); + _scene->addActiveVocab(VERB_WALKTO); + + if ((!_globals[kFromCockpit] && _globals[kReturnFromCut] && !_globals[kBeamIsUp]) + || (_globals[kFromCockpit] && !_globals[kExitShip])) { + _game._player._spritesPrefix = ""; + _game._player._spritesChanged = true; + } +} + +void Scene803::enter() { + _globals[kBetweenRooms] = false; + _game._player._visible = false; + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('f', 1)); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites("*RXMBD_2"); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('d', 1)); + + _game.loadQuoteSet(0x31B, 0x31C, 0x31D, 0x31E, 0x31F, 0x320, 0x321, 0x322, 0); + + if (_globals[kHoppyDead]) { + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('e', 1)); + _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, 1); + int idx = _scene->_dynamicHotspots.add(NOUN_GUTS, VERB_WALKTO, _globals._sequenceIndexes[7], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(66, 123), FACING_SOUTH); + } + + if (!_globals[kBeamIsUp] && !_globals[kReturnFromCut] && (!_globals[kFromCockpit] || _globals[kExitShip])) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 2, 2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + } + + if (!_globals[kFromCockpit]) { + if (!_globals[kReturnFromCut]) { + if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(15, 130); + _game._player._facing = FACING_EAST; + } + _game._player._visible = true; + } else if (!_globals[kBeamIsUp]){ + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 3)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('a', 2)); + _game._player._visible = false; + _game._player._stepEnabled = false; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 15); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 80); + _vm->_sound->command(14); + } + + if (_globals[kBeamIsUp] && !_globals[kReturnFromCut]){ + if (_globals[kForceBeamDown]) + _game._player._visible = false; + else + _game._player._visible = true; + + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('b', 1)); + _vm->_sound->command(15); + _game._player._stepEnabled = false; + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 100); + } + } else if (!_globals[kExitShip]) { + if (!_globals[kBeamIsUp]) { + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _game._player._visible = false; + _game._player._stepEnabled = false; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 130); + _vm->_sound->command(14); + } else { + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('c', 1)); + _game._player._visible = false; + _game._player._stepEnabled = false; + _globals._sequenceIndexes[8] = _scene->_sequences.startCycle(_globals._spriteIndexes[8], false, 1); + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 140); + } + } else { + _game._player._stepEnabled = false; + _game._player._playerPos = Common::Point(197, 96); + _game._player._facing = FACING_SOUTHWEST; + _game._player._visible = true; + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('d', 1)); + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 19); + _scene->_sequences.addTimer(1, 150); + } + + sceneEntrySound(); +} + +void Scene803::step() { + if (_game._trigger == 120) { + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 19); + _scene->_nextSceneId = 804; + } + + if (_game._trigger == 100) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 2, 2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + if (!_globals[kHoppyDead]) { + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 7, 12); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5],SEQUENCE_TRIGGER_EXPIRE, 0, 101); + } else { + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, -2); + int idx = _scene->_dynamicHotspots.add(NOUN_GUTS, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(66, 123), FACING_SOUTH); + _vm->_sound->command(16); + _globals[kCameFromCut] = true; + _globals[kBeamIsUp] = false; + _globals[kReturnFromCut] = false; + _globals[kDontRepeat] = false; + _globals[kHoppyDead] = true; + _globals[kHasWatchedAntigrav] = true; + + if (_globals[kForceBeamDown]) + _scene->_nextSceneId = _scene->_priorSceneId; + else + _game._player._stepEnabled = true; + } + } + + if (_game._trigger == 101) { + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, -2); + int idx = _scene->_dynamicHotspots.add(NOUN_GUTS, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(66, 123), FACING_SOUTH); + _vm->_sound->command(16); + _globals[kCameFromCut] = true; + _globals[kBeamIsUp] = false; + _globals[kReturnFromCut] = false; + _globals[kDontRepeat] = false; + _globals[kHoppyDead] = true; + _globals[kHasWatchedAntigrav] = true; + + if (_globals[kForceBeamDown]) + _scene->_nextSceneId = _scene->_priorSceneId; + else + _game._player._stepEnabled = true; + } + + if (_game._trigger == 80) { + if (!_globals[kHoppyDead]) + _scene->_sequences.addTimer(350, 70); + + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 90); + } + + if (_game._trigger == 70) { + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + _vm->_sound->command(31); + } + + if (_game._trigger == 71) + _scene->_sequences.addTimer(200, 110); + + if (_game._trigger == 90) { + int syncIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 15, 0, 0, 0); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 4, 9); + if (_globals[kHoppyDead]) + _scene->_sequences.addTimer(200, 110); + } + + if (_game._trigger == 110) + _scene->_nextSceneId = 808; + + if (_game._trigger == 130) { + _globals[kBeamIsUp] = true; + _scene->_nextSceneId = 804; + } + + if (_game._trigger == 140) { + if (!_globals[kWindowFixed]) { + _scene->_nextSceneId = 810; + _globals[kInSpace] = true; + } else { + if (!_globals[kShieldModInstalled]) + _game._winStatus = 1; + else if (!_globals[kTargetModInstalled]) + _game._winStatus = 2; + else + _game._winStatus = 3; + + _vm->quitGame(); + } + } + + if (_game._trigger == 150) { + _scene->_sequences.remove(_globals._sequenceIndexes[6]); + _vm->_sound->command(18); + _globals._sequenceIndexes[6] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[6], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 19); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 151); + } + + if (_game._trigger == 151) { + _globals[kBeamIsUp] = false; + _globals[kFromCockpit] = false; + _globals[kExitShip] = false; + _game._player._stepEnabled = true; + } +} + +void Scene803::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_WEST)) + _game._player._walkOffScreenSceneId = 802; + + if (_action.isAction(VERB_TAKE, NOUN_SHIP)) + _game._player._needToWalk = false; +} + +void Scene803::actions() { + if (_action.isAction(VERB_TAKE, NOUN_GUTS)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], true, 6, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 1, 4); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[9]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 160); + break; + + case 160: { + int syncIdx = _globals._sequenceIndexes[9]; + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 4); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], syncIdx); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[9]); + _scene->_sequences.addTimer(60, 161); + } + break; + + case 161: { + int quoteId = 0x31A + _vm->getRandomNumber(1, 8); + _scene->_kernelMessages.add(Common::Point(64, 67), 0x1110, 32, 0, 80, _game.getQuote(quoteId)); + _scene->_sequences.addTimer(60, 162); + } + break; + + case 162: + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _globals._sequenceIndexes[9] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[9], true, 6, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 1, 4); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[9]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 163); + break; + + case 163: + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_ENTER, NOUN_SHIP)) { + _vm->_sound->command(17); + _game._player._stepEnabled = false; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 19); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 120); + _globals[kBeamIsUp] = false; + } else if (_action.isAction(VERB_LOOK, NOUN_LAUNCH_PAD)) + _vm->_dialogs->show(80310); + else if (_action._lookFlag) + _vm->_dialogs->show(80310); + else if (_action.isAction(VERB_LOOK, NOUN_PAD_TO_WEST)) + _vm->_dialogs->show(80311); + else if (_action.isAction(VERB_LOOK, NOUN_GUTS)) { + if (_game._storyMode == STORYMODE_NICE) + _vm->_dialogs->show(80312); + else + _vm->_dialogs->show(80313); + } else if (_action.isAction(VERB_LOOK, NOUN_BUSHES)) + _vm->_dialogs->show(80315); + else if (_action.isAction(VERB_LOOK, NOUN_SHIP)) + _vm->_dialogs->show(80317); + else if (_action.isAction(VERB_LOOK, NOUN_TOWER)) + _vm->_dialogs->show(80318); + else if (_action.isAction(VERB_LOOK, NOUN_TREE) || _action.isAction(VERB_LOOK, NOUN_TREES)) + _vm->_dialogs->show(80319); + else if (_action.isAction(VERB_LOOK, NOUN_SKY)) + _vm->_dialogs->show(80320); + else if (_action.isAction(VERB_TAKE, NOUN_SHIP)) + _vm->_dialogs->show(80321); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene804::Scene804(MADSEngine *vm) : Scene8xx(vm) { + _messWithThrottle = false; + _movingThrottle = false; + _throttleGone = false; + _dontPullThrottleAgain = false; + _pullThrottleReally = false; + _alreadyOrgan = false; + _alreadyPop = false; + + _throttleCounter = 0; + _resetFrame = -1; +} + +void Scene804::synchronize(Common::Serializer &s) { + Scene8xx::synchronize(s); + + s.syncAsByte(_messWithThrottle); + s.syncAsByte(_movingThrottle); + s.syncAsByte(_throttleGone); + s.syncAsByte(_dontPullThrottleAgain); + s.syncAsByte(_pullThrottleReally); + s.syncAsByte(_alreadyOrgan); + s.syncAsByte(_alreadyPop); + + s.syncAsSint16LE(_resetFrame); + s.syncAsUint32LE(_throttleCounter); +} + +void Scene804::setup() { + Scene8xx::setPlayerSpritesPrefix(); + Scene8xx::setAAName(); +} + +void Scene804::enter() { + _messWithThrottle = false; + _throttleCounter = 0; + _movingThrottle = false; + _throttleGone = false; + _dontPullThrottleAgain = false; + _resetFrame = -1; + _pullThrottleReally = false; + _alreadyOrgan = false; + _alreadyPop = false; + + + if (_globals[kCopyProtectFailed]) { + // Copy protection failed + _globals[kInSpace] = true; + _globals[kWindowFixed] = 0; + } + + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('x', 2)); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 3)); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('x', 4)); + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('f', 1)); + + _game.loadQuoteSet(791, 0); + + if (_globals[kInSpace]) { + if (_globals[kWindowFixed]) { + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], 0, 1); + _scene->_sequences.addTimer(60, 100); + } else { + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 1); + _globals._sequenceIndexes[7] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[7], false, 4, 0, 0, 0); + _scene->_sequences.addTimer(160, 70); + _game._player._stepEnabled = false; + } + } else { + if (_globals[kBeamIsUp] == 0) + _globals._sequenceIndexes[8] = _scene->_sequences.startCycle(_globals._spriteIndexes[8], false, 1); + + if (_globals[kWindowFixed] == 0) + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(133, 139)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 8); + } + + _scene->loadAnimation(Resources::formatName(804, 'r', 1, EXT_AA, "")); + + Scene8xx::sceneEntrySound(); + + if (_globals[kInSpace] && !_globals[kWindowFixed]) { + _scene->_userInterface.setup(kInputLimitedSentences); + _vm->_sound->command(19); + } +} + +void Scene804::step() { + if (!_messWithThrottle) { + + if ((_throttleGone) && (_movingThrottle) && (_scene->_activeAnimation->getCurrentFrame() == 39)) { + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle + (_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(133, 139)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 8); + _throttleGone = false; + } + + if ((_movingThrottle) && (_scene->_activeAnimation->getCurrentFrame() == 42)) { + _resetFrame = 0; + _movingThrottle = false; + } + + if (_game._trigger == 70) { + _resetFrame = 42; + } + + if (_scene->_activeAnimation->getCurrentFrame() == 65) + _scene->_sequences.remove(_globals._sequenceIndexes[7]); + + switch (_game._storyMode) { + case STORYMODE_NAUGHTY: + if (_scene->_activeAnimation->getCurrentFrame() == 81) { + _resetFrame = 80; + _globals[kInSpace] = false; + _globals[kBeamIsUp] = true; + + assert(!_globals[kCopyProtectFailed]); + _game._winStatus = 4; + _vm->quitGame(); + } + break; + + case STORYMODE_NICE: + if (_scene->_activeAnimation->getCurrentFrame() == 68) { + _resetFrame = 66; + _globals[kInSpace] = false; + _globals[kBeamIsUp] = true; + + assert(!_globals[kCopyProtectFailed]); + _game._winStatus = 4; + _vm->quitGame(); + } + } + + if (_scene->_activeAnimation->getCurrentFrame() == 34) { + _resetFrame = 36; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + } + + if (_scene->_activeAnimation->getCurrentFrame() == 37) { + _resetFrame = 36; + if (!_dontPullThrottleAgain) { + _dontPullThrottleAgain = true; + _scene->_sequences.addTimer(60, 80); + } + } + + if (_game._trigger == 80) { + _scene->_nextSceneId = 803; + } + + if ((_scene->_activeAnimation->getCurrentFrame() == 7) && (!_globals[kWindowFixed])) { + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.addTimer(20, 110); + _globals[kWindowFixed] = true; + } + + if (_scene->_activeAnimation->getCurrentFrame() == 10) { + _resetFrame = 0; + _game._player._stepEnabled = true; + _game._objects.setRoom(OBJ_POLYCEMENT, NOWHERE); + } + + if (_scene->_activeAnimation->getCurrentFrame() == 1) { + int randomVal = _vm->getRandomNumber(29) + 1; + switch (randomVal) { + case 1: + _resetFrame = 25; + break; + case 2: + _resetFrame = 27; + break; + case 3: + _resetFrame = 29; + break; + default: + _resetFrame = 0; + break; + } + } + + switch (_scene->_activeAnimation->getCurrentFrame()) { + case 26: + case 28: + case 31: + _resetFrame = 0; + break; + } + } else { + if ((_scene->_activeAnimation->getCurrentFrame() == 36) && (!_throttleGone)) { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _throttleGone = true; + } + + if (_scene->_activeAnimation->getCurrentFrame() == 39) { + _movingThrottle = false; + switch (_throttleCounter) { + case 1: + break; + case 3: + _scene->_sequences.addTimer(130, 120); + break; + } + } + + if (!_movingThrottle) { + ++_throttleCounter; + _movingThrottle = true; + if (_throttleCounter < 4) { + _resetFrame = 34; + } else { + _messWithThrottle = false; + _throttleCounter = 0; + _game._player._stepEnabled = true; + } + } + } + + if (_game._trigger == 120) { + _vm->_dialogs->show(80422); + } + + if (_game._trigger == 110) { + _vm->_dialogs->show(80426); + } + + if (_pullThrottleReally) { + _resetFrame = 32; + _pullThrottleReally = false; + } + + if (_resetFrame >= 0) { + if (_resetFrame != _scene->_activeAnimation->getCurrentFrame()) { + _scene->_activeAnimation->setCurrentFrame(_resetFrame); + _resetFrame = -1; + } + } + + if (_game._trigger == 90) { + _scene->_nextSceneId = 803; + } + + if ((_scene->_activeAnimation->getCurrentFrame() == 72) && !_alreadyPop) { + _vm->_sound->command(21); + _alreadyPop = true; + } + + if ((_scene->_activeAnimation->getCurrentFrame() == 80) && !_alreadyOrgan) { + _vm->_sound->command(22); + _alreadyOrgan = true; + } +} + +/*------------------------------------------------------------------------*/ + +void Scene805::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(VERB_REMOVE); + _scene->addActiveVocab(NOUN_TARGET_MODULE); + _scene->addActiveVocab(NOUN_SHIELD_MODULATOR); +} + +void Scene805::enter() { + _game._player._visible = false; + _scene->_userInterface.setup(kInputLimitedSentences); + + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 2)); + + if (_globals[kShieldModInstalled]) { + _scene->_hotspots.activate(OBJ_SHIELD_MODULATOR, false); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 25); + int idx = _scene->_dynamicHotspots.add(NOUN_SHIELD_MODULATOR, VERB_REMOVE, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_DUMMY); + } + + if (_globals[kTargetModInstalled]) { + _scene->_hotspots.activate(OBJ_TARGET_MODULE, false); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 12); + int idx = _scene->_dynamicHotspots.add(NOUN_TARGET_MODULE, VERB_REMOVE, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_DUMMY); + } + + sceneEntrySound(); +} + +void Scene805::step() { + if (_game._trigger == 70) { + _scene->_hotspots.activate(OBJ_SHIELD_MODULATOR, false); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 25); + int idx = _scene->_dynamicHotspots.add(NOUN_SHIELD_MODULATOR, VERB_REMOVE, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_DUMMY); + _globals[kShieldModInstalled] = true; + _game._objects.setRoom(OBJ_SHIELD_MODULATOR, NOWHERE); + _game._player._stepEnabled = true; + _vm->_sound->command(24); + } + + if (_game._trigger == 80) { + _scene->_hotspots.activate(OBJ_TARGET_MODULE, false); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 12); + int idx = _scene->_dynamicHotspots.add(NOUN_TARGET_MODULE, VERB_REMOVE, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_DUMMY); + _globals[kTargetModInstalled] = true; + _game._objects.setRoom(OBJ_TARGET_MODULE, NOWHERE); + _game._player._stepEnabled = true; + _vm->_sound->command(24); + } + + if (_game._trigger == 71) { + _scene->_hotspots.activate(OBJ_SHIELD_MODULATOR, true); + _globals[kShieldModInstalled] = false; + _game._objects.addToInventory(OBJ_SHIELD_MODULATOR); + _game._player._stepEnabled = true; + } + + if (_game._trigger == 81) { + _scene->_hotspots.activate(OBJ_TARGET_MODULE, true); + _globals[kTargetModInstalled] = false; + _game._objects.addToInventory(OBJ_TARGET_MODULE); + _game._player._stepEnabled = true; + } +} + +void Scene805::preActions() { + _game._player._needToWalk = false; +} + +void Scene805::actions() { + if (_action.isAction(VERB_EXIT, NOUN_SERVICE_PANEL)) + _scene->_nextSceneId = 804; + else if (_action.isAction(VERB_INSTALL, NOUN_SHIELD_MODULATOR) && _game._objects.isInInventory(OBJ_SHIELD_MODULATOR)) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], -1, -2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 70); + _game._player._stepEnabled = false; + } else if (_action.isAction(VERB_INSTALL, NOUN_TARGET_MODULE) && _game._objects.isInInventory(OBJ_TARGET_MODULE)) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, -2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 80); + _game._player._stepEnabled = false; + } else if (_action.isAction(VERB_REMOVE, NOUN_SHIELD_MODULATOR) && _globals[kShieldModInstalled]) { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], -1, -2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + _game._player._stepEnabled = false; + } else if (_action.isAction(VERB_REMOVE, NOUN_TARGET_MODULE) && _globals[kTargetModInstalled]) { + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, -2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 81); + _game._player._stepEnabled = false; + } else if (_action.isAction(VERB_INSTALL, NOUN_SHIELD_MODULATOR) && !_game._objects.isInInventory(OBJ_SHIELD_MODULATOR)) + _vm->_dialogs->show(80511); + else if (_action.isAction(VERB_INSTALL, NOUN_TARGET_MODULE) && !_game._objects.isInInventory(OBJ_TARGET_MODULE)) + _vm->_dialogs->show(80510); + else if (_action.isAction(VERB_REMOVE, NOUN_LIFE_SUPPORT_MODULE)) + _vm->_dialogs->show(80512); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene807::setup() { + _game._player._spritesPrefix = ""; + // The original was calling Scene8xx::setAAName() + _game._aaName = Resources::formatAAName(5); +} + +void Scene807::enter() { + if (_globals[kSexOfRex] == REX_FEMALE) + _handSpriteId = _scene->_sprites.addSprites("*ROXHAND"); + else + _handSpriteId = _scene->_sprites.addSprites("*REXHAND"); + + teleporterEnter(); + + // The original uses Scene8xx::SceneEntrySound() + if (!_vm->_musicFlag) + _vm->_sound->command(2); + else + _vm->_sound->command(20); +} + +void Scene807::step() { + teleporterStep(); +} + +void Scene807::actions() { + if (teleporterActions()) { + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_VIEWPORT)) + _vm->_dialogs->show(80710); + else if (_action.isAction(VERB_PEER_THROUGH, NOUN_VIEWPORT)) + _vm->_dialogs->show(80710); + else if (_action.isAction(VERB_LOOK, NOUN_KEYPAD) && _action.isAction(VERB_INSPECT, NOUN_KEYPAD)) + _vm->_dialogs->show(80711); + else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY)) + _vm->_dialogs->show(80712); + else if (_action.isAction(VERB_LOOK, NOUN_1_KEY) || _action.isAction(VERB_LOOK, NOUN_2_KEY) + || _action.isAction(VERB_LOOK, NOUN_3_KEY) || _action.isAction(VERB_LOOK, NOUN_4_KEY) + || _action.isAction(VERB_LOOK, NOUN_5_KEY) || _action.isAction(VERB_LOOK, NOUN_6_KEY) + || _action.isAction(VERB_LOOK, NOUN_7_KEY) || _action.isAction(VERB_LOOK, NOUN_8_KEY) + || _action.isAction(VERB_LOOK, NOUN_9_KEY) || _action.isAction(VERB_LOOK, NOUN_0_KEY) + || _action.isAction(VERB_LOOK, NOUN_SMILE_KEY) || _action.isAction(VERB_LOOK, NOUN_FROWN_KEY)) + _vm->_dialogs->show(80713); + else if (_action.isAction(VERB_LOOK, NOUN_DEVICE) && _action._lookFlag) + _vm->_dialogs->show(80714); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene808::Scene808(MADSEngine *vm) : Scene8xx(vm) { + _goingTo803 = false; +} + +void Scene808::synchronize(Common::Serializer &s) { + Scene8xx::synchronize(s); + + s.syncAsByte(_goingTo803); +} + +void Scene808::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene808::enter() { + _scene->_userInterface.setup(kInputLimitedSentences); + + _globals._spriteIndexes[4] = _scene->_sprites.addSprites ("*REXHAND"); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('b', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('b', 1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('b', 2)); + + if (_globals[kTopButtonPushed]) + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + else + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + + _goingTo803 = false; + + if (_globals[kCameFromCut] && _globals[kCutX] != 0) { + _globals[kCutX] = 0; + _globals[kCameFromCut] = false; + _globals[kReturnFromCut] = false; + _globals[kBeamIsUp] = false; + _globals[kForceBeamDown] = false; + _globals[kDontRepeat] = false; + } else if ((_scene->_priorSceneId == 803) && _globals[kReturnFromCut]){ + _globals[kDontRepeat] = false; + _globals[kBeamIsUp] = true; + _globals[kAntigravClock] = _scene->_frameStartTime; + _globals[kAntigravTiming] = _scene->_frameStartTime; + _globals[kForceBeamDown] = false; + _globals[kReturnFromCut] = false; + } + + _globals[kBetweenRooms] = false; + + if (_globals[kBeamIsUp]) { + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8); + } + + sceneEntrySound(); +} + +void Scene808::actions() { + if (_action.isAction(VERB_PRESS, NOUN_START_BUTTON_2)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 211)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 70); + break; + + case 70: + if (!_globals[kBeamIsUp] && !_globals[kTopButtonPushed]) { + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8); + _goingTo803 = true; + _vm->_sound->command(20); + _vm->_sound->command(25); + } + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 211)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + break; + + case 71: + _game._player._stepEnabled = true; + if (_goingTo803 && !_globals[kTopButtonPushed]) { + _goingTo803 = false; + _globals[kReturnFromCut] = true; + _scene->_nextSceneId = 803; + } + break; + + default: + break; + } + } else if (_action.isAction(VERB_PRESS, NOUN_TIMER_BUTTON_2)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 186)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 90); + break; + case 90: + if (_globals[kTopButtonPushed]) { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 8); + _vm->_sound->command(20); + } + _globals[kTopButtonPushed] = false; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 186)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 91); + break; + + case 91: + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_PRESS, NOUN_REMOTE_BUTTON_2)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 163)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 80); + break; + + case 80: + if (!_globals[kTopButtonPushed]) { + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 8); + _vm->_sound->command(20); + } + _globals[kTopButtonPushed] = true; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 163)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 81); + break; + + case 81: + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_PRESS, NOUN_START_BUTTON_1)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 2, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(168, 211)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 70); + break; + + case 70: + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_PRESS, NOUN_REMOTE_BUTTON_1)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 2, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(172, 163)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 80); + break; + + case 80: + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_PRESS, NOUN_TIMER_BUTTON_1)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 2, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(172, 186)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 90); + break; + + case 90: + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_EXIT, NOUN_PANEL)) { + _scene->_nextSceneId = 801; + _globals[kBetweenRooms] = true; + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene810::Scene810(MADSEngine *vm) : Scene8xx(vm) { + _moveAllowed = false; +} + +void Scene810::synchronize(Common::Serializer &s) { + Scene8xx::synchronize(s); + + s.syncAsByte(_moveAllowed); +} + +void Scene810::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene810::enter() { + _scene->_userInterface.setup(kInputLimitedSentences); + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->loadAnimation(Resources::formatName(810, 'a', -1, EXT_AA, "")); + _moveAllowed = true; + + sceneEntrySound(); +} + +void Scene810::step() { + if ((_scene->_activeAnimation->getCurrentFrame() == 200) && _moveAllowed) { + _scene->_sequences.addTimer(100, 70); + _moveAllowed = false; + } + + if (_game._trigger == 70) + _scene->_nextSceneId = 804; +} + +/*------------------------------------------------------------------------*/ + +} // End of namespace Nebular +} // End of namespace MADS diff --git a/engines/mads/nebular/nebular_scenes8.h b/engines/mads/nebular/nebular_scenes8.h new file mode 100644 index 0000000000..39e022e31f --- /dev/null +++ b/engines/mads/nebular/nebular_scenes8.h @@ -0,0 +1,165 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 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. + * + */ + +#ifndef MADS_NEBULAR_SCENES8_H +#define MADS_NEBULAR_SCENES8_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" + +namespace MADS { + +namespace Nebular { + +class Scene8xx : public NebularScene { +protected: + /** + * Initial setup code shared by several scenes + */ + void setPlayerSpritesPrefix(); + + /** + * Initial setup code shared by several scenes + */ + void setAAName(); + + /** + * Common scene enter code used by multiple scenes + */ + void sceneEntrySound(); +public: + Scene8xx(MADSEngine *vm) : NebularScene(vm) {} +}; + +class Scene801 : public Scene8xx{ +private: + bool _walkThroughDoor; + +public: + Scene801(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene802 : public Scene8xx{ +public: + Scene802(MADSEngine *vm) : Scene8xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene803 : public Scene8xx{ +public: + Scene803(MADSEngine *vm) : Scene8xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene804 : public Scene8xx { +private: + bool _messWithThrottle; + bool _movingThrottle; + bool _throttleGone; + bool _dontPullThrottleAgain; + bool _pullThrottleReally; + bool _alreadyOrgan; + bool _alreadyPop; + uint32 _throttleCounter; + int _resetFrame; + +public: + Scene804(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions() {}; +}; + +class Scene805 : public Scene8xx{ +public: + Scene805(MADSEngine *vm) : Scene8xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene807 : public SceneTeleporter { +public: + Scene807(MADSEngine *vm) : SceneTeleporter(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene808 : public Scene8xx{ +private: + bool _goingTo803; + +public: + Scene808(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene810 : public Scene8xx{ +private: + bool _moveAllowed; + +public: + Scene810(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions() {}; +}; + +} // End of namespace Nebular +} // End of namespace MADS + +#endif /* MADS_NEBULAR_SCENES8_H */ diff --git a/engines/mads/nebular/sound_nebular.cpp b/engines/mads/nebular/sound_nebular.cpp new file mode 100644 index 0000000000..fc2755db2f --- /dev/null +++ b/engines/mads/nebular/sound_nebular.cpp @@ -0,0 +1,3119 @@ +/* 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. + * + */ + +#include "audio/audiostream.h" +#include "audio/decoders/raw.h" +#include "common/algorithm.h" +#include "common/debug.h" +#include "common/memstream.h" +#include "mads/sound.h" +#include "mads/nebular/sound_nebular.h" + +namespace MADS { + +namespace Nebular { + +bool AdlibChannel::_channelsEnabled; + +AdlibChannel::AdlibChannel() { + _activeCount = 0; + _field1 = 0; + _field2 = 0; + _field3 = 0; + _field4 = 0; + _sampleIndex = 0; + _volume = 0; + _field7 = 0; + _field8 = 0; + _field9 = 0; + _fieldA = 0; + _fieldB = 0; + _fieldC = 0; + _fieldD = 0; + _fieldE = 0; + _ptr1 = nullptr; + _pSrc = nullptr; + _ptr3 = nullptr; + _ptr4 = nullptr; + _field17 = 0; + _field19 = 0; + _soundData = nullptr; + _field1D = 0; + _field1E = 0; + _field1F = 0; + + _field20 = 0; +} + +void AdlibChannel::reset() { + _activeCount = 0; + _field1 = 0; + _field2 = 0; + _field3 = 0; +} + +void AdlibChannel::enable(int flag) { + if (_activeCount) { + _fieldE = flag; + + // WORKAROUND: Original set _soundData pointer to flag. Since this seems + // just intended to invalidate any prior pointer, I've replaced it with + // a simple null pointer + _soundData = nullptr; + } + + _channelsEnabled = true; +} + +void AdlibChannel::setPtr2(byte *pData) { + _pSrc = pData; + _field2 = 0xFF; + _fieldA = 1; + _field9 = 1; +} + +void AdlibChannel::load(byte *pData) { + _ptr1 = _pSrc = _ptr3 = pData; + _ptr4 = _soundData = pData; + _fieldA = 0xFF; + _activeCount = 1; + _fieldD = 64; + _field1 = 0; + _field1F = 0; + _field2 = _field3 = 0; + _volume = _field7 = 0; + _field1D = _field1E = 0; + _fieldE = 0; + _field9 = 0; + _fieldB = 0; + _field17 = 0; + _field19 = 0; +} + +void AdlibChannel::check(byte *nullPtr) { + if (_activeCount && _fieldE) { + if (!_field1E) { + _pSrc = nullPtr; + _fieldE = 0; + } else { + _field2 = 0xFF; + _fieldA = 4; + if (!_field9) + _field9 = 1; + } + } +} + +/*-----------------------------------------------------------------------*/ + +AdlibSample::AdlibSample(Common::SeekableReadStream &s) { + _attackRate = s.readByte(); + _decayRate = s.readByte(); + _sustainLevel = s.readByte(); + _releaseRate = s.readByte(); + _egTyp = s.readByte() != 0; + _ksr = s.readByte() != 0; + _totalLevel = s.readByte(); + _scalingLevel = s.readByte(); + _waveformSelect = s.readByte(); + _freqMultiple = s.readByte(); + _feedback = s.readByte(); + _ampMod = s.readByte() != 0; + _vib = s.readByte(); + _alg = s.readByte(); + _fieldE = s.readByte(); + s.skip(1); + _freqMask = s.readUint16LE(); + _freqBase = s.readUint16LE(); + _field14 = s.readUint16LE(); +} + +/*-----------------------------------------------------------------------*/ + +ASound::ASound(Audio::Mixer *mixer, const Common::String &filename, int dataOffset) { + // Open up the appropriate sound file + if (!_soundFile.open(filename)) + error("Could not open file - %s", filename.c_str()); + + // Initialize fields + _commandParam = 0; + _activeChannelPtr = nullptr; + _samplePtr = nullptr; + _frameCounter = 0; + _isDisabled = false; + _v1 = 0; + _v2 = 0; + _activeChannelNumber = 0; + _freqMask1 = _freqMask2 = 0; + _freqBase1 = _freqBase2 = 0; + _channelNum1 = _channelNum2 = 0; + _v7 = 0; + _v8 = 0; + _v9 = 0; + _v10 = 0; + _pollResult = 0; + _resultFlag = 0; + _nullData[0] = _nullData[1] = 0; + Common::fill(&_ports[0], &_ports[256], 0); + _stateFlag = false; + _activeChannelReg = 0; + _v11 = 0; + _randomSeed = 1234; + _amDep = _vibDep = _splitPoint = true; + + _samplesTillCallback = 0; + _samplesTillCallbackRemainder = 0; + _samplesPerCallback = getRate() / CALLBACKS_PER_SECOND; + _samplesPerCallbackRemainder = getRate() % CALLBACKS_PER_SECOND; + + for (int i = 0; i < 11; ++i) { + _channelData[i]._field0 = 0; + _channelData[i]._freqMask = 0; + _channelData[i]._freqBase = 0; + _channelData[i]._field6 = 0; + } + + AdlibChannel::_channelsEnabled = false; + + // Store passed parameters, and setup OPL + _dataOffset = dataOffset; + _mixer = mixer; + _opl = OPL::Config::create(); + assert(_opl); + + _opl->init(getRate()); + _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, + Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); + + // Initialize the Adlib + adlibInit(); + + // Reset the adlib + command0(); +} + +ASound::~ASound() { + Common::List<CachedDataEntry>::iterator i; + for (i = _dataCache.begin(); i != _dataCache.end(); ++i) + delete[] (*i)._data; + + _mixer->stopHandle(_soundHandle); + delete _opl; +} + +void ASound::adlibInit() { + write(4, 0x60); + write(4, 0x80); + write(2, 0xff); + write(4, 0x21); + write(4, 0x60); + write(4, 0x80); +} + +int ASound::stop() { + command0(); + int result = _pollResult; + _pollResult = 0; + return result; +} + +int ASound::poll() { + // Update any playing sounds + update(); + + // Return result + int result = _pollResult; + _pollResult = 0; + return result; +} + +void ASound::noise() { + int randomVal = getRandomNumber(); + + if (_v1) { + setFrequency(_channelNum1, ((randomVal ^ 0xFFFF) & _freqMask1) + _freqBase1); + } + + if (_v2) { + setFrequency(_channelNum2, (randomVal & _freqMask2) + _freqBase2); + } +} + +void ASound::write(int reg, int val) { + _queue.push(RegisterValue(reg, val)); +} + +int ASound::write2(int state, int reg, int val) { + // TODO: Original has a state parameter, not used when in Adlib mode? + _ports[reg] = val; + write(reg, val); + return state; +} + +void ASound::flush() { + Common::StackLock slock(_driverMutex); + + while (!_queue.empty()) { + RegisterValue v = _queue.pop(); + _opl->writeReg(v._regNum, v._value); + } +} + +void ASound::channelOn(int reg, int volume) { + write2(8, reg, (_ports[reg] & 0xC0) | (volume & 0x3F)); +} + +void ASound::channelOff(int reg) { + write2(8, reg, _ports[reg] | 0x3F); +} + +void ASound::resultCheck() { + if (_resultFlag != 1) { + _resultFlag = 1; + _pollResult = 1; + } +} + +byte *ASound::loadData(int offset, int size) { + // First scan for an existing copy + Common::List<CachedDataEntry>::iterator i; + for (i = _dataCache.begin(); i != _dataCache.end(); ++i) { + CachedDataEntry &e = *i; + if (e._offset == offset) + return e._data; + } + + // No existing entry found, so load up data and store as a new entry + CachedDataEntry rec; + rec._offset = offset; + rec._data = new byte[size]; + _soundFile.seek(_dataOffset + offset); + _soundFile.read(rec._data, size); + _dataCache.push_back(rec); + + // Return the data + return rec._data; +} + +void ASound::playSound(int offset, int size) { + // Load the specified data block + playSoundData(loadData(offset, size)); +} + +void ASound::playSoundData(byte *pData, int startingChannel) { + // Scan for a high level free channel + for (int i = startingChannel; i < ADLIB_CHANNEL_COUNT; ++i) { + if (!_channels[i]._activeCount) { + _channels[i].load(pData); + return; + } + } + + // None found, do a secondary scan for an interruptable channel + for (int i = ADLIB_CHANNEL_COUNT - 1; i >= startingChannel; --i) { + if (_channels[i]._fieldE == 0xFF) { + _channels[i].load(pData); + return; + } + } +} + +bool ASound::isSoundActive(byte *pData) { + for (int i = 0; i < ADLIB_CHANNEL_MIDWAY; ++i) { + if (_channels[i]._activeCount && _channels[i]._soundData == pData) + return true; + } + + return false; +} + +void ASound::setFrequency(int channel, int freq) { + write2(8, 0xA0 + channel, freq & 0xFF); + write2(8, 0xB0 + channel, (freq >> 8) | 0x20); +} + +int ASound::getRandomNumber() { + int v = 0x9248 + (int)_randomSeed; + _randomSeed = ((v >> 3) | (v << 13)) & 0xFFFF; + return _randomSeed; +} + +void ASound::update() { + getRandomNumber(); + if (_isDisabled) + return; + + ++_frameCounter; + pollChannels(); + checkChannels(); + + if (_v1 == _v2) { + if (_resultFlag != -1) { + _resultFlag = -1; + _pollResult = -1; + } + } else { + if (_v1) { + _freqBase1 += _v7; + if (!--_v1) { + if (!_v2 || _channelNum1 != _channelNum2) { + write2(8, 0xA0 + _channelNum1, 0); + write2(8, 0xB0 + _channelNum1, 0); + } + } + } + + if (_v2) { + _freqBase2 += _v8; + if (!--_v2) { + if (!_v1 || _channelNum2 != _channelNum1) { + write2(8, 0xA0 + _channelNum2, 0); + write2(8, 0xB0 + _channelNum2, 0); + } + } + } + } +} + +void ASound::pollChannels() { + _activeChannelNumber = 0; + for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i) { + _activeChannelPtr = &_channels[i]; + pollActiveChannel(); + } +} + +void ASound::checkChannels() { + if (AdlibChannel::_channelsEnabled) { + for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i) + _channels[i].check(_nullData); + } +} + +void ASound::pollActiveChannel() { + AdlibChannel *chan = _activeChannelPtr; + + if (chan->_activeCount) { + if (chan->_field8 > 0 && --chan->_field8 == 0) + updateOctave(); + + bool updateFlag = true; + if (--_activeChannelPtr->_activeCount <= 0) { + for (;;) { + byte *pSrc = chan->_pSrc; + if (!chan->_ptr1) { + warning("pollActiveChannel(): No data found for sound channel"); + break; + } + if (!(*pSrc & 0x80) || (*pSrc <= 0xF0)) { + if (updateFlag) + updateActiveChannel(); + + chan->_field4 = *pSrc++; + chan->_activeCount = *pSrc++; + chan->_pSrc += 2; + + if (!chan->_field4 || !chan->_activeCount) { + updateOctave(); + } else { + chan->_field8 = chan->_activeCount - chan->_field7; + updateChannelState(); + } + + // Break out of processing loop + break; + } else { + updateFlag = false; + + switch ((~*pSrc) & 0xF) { + case 0: + if (!chan->_field17) { + if (*++pSrc == 0) { + chan->_pSrc += 2; + chan->_ptr3 = chan->_pSrc; + chan->_field17 = 0; + } else { + chan->_field17 = *pSrc; + chan->_pSrc = chan->_ptr3; + } + } else if (--chan->_field17) { + chan->_pSrc = chan->_ptr3; + } else { + chan->_pSrc += 2; + chan->_ptr3 = chan->_pSrc; + } + break; + + case 1: + if (!chan->_field19) { + if (*++pSrc == 0) { + chan->_pSrc += 2; + chan->_ptr4 = chan->_pSrc; + chan->_ptr3 = chan->_pSrc; + chan->_field17 = 0; + chan->_field19 = 0; + } else { + chan->_field19 = *pSrc; + chan->_pSrc = chan->_ptr4; + chan->_ptr3 = chan->_ptr4; + } + } else if (--chan->_field19) { + chan->_ptr4 = chan->_pSrc; + chan->_ptr3 = chan->_pSrc; + } else { + chan->_pSrc += 2; + chan->_ptr4 = chan->_pSrc; + chan->_ptr3 = chan->_pSrc; + } + break; + + case 2: + // Loop sound data + chan->_field1 = 0; + chan->_field2 = chan->_field3 = 0; + chan->_volume = chan->_field7 = 0; + chan->_field1D = chan->_field1E = 0; + chan->_field8 = 0; + chan->_field9 = 0; + chan->_fieldB = 0; + chan->_field17 = 0; + chan->_field19 = 0; + chan->_fieldD = 0x40; + chan->_ptr1 = chan->_soundData; + chan->_pSrc = chan->_soundData; + chan->_ptr3 = chan->_soundData; + chan->_ptr4 = chan->_soundData; + + chan->_pSrc += 2; + break; + + case 3: + chan->_sampleIndex = *++pSrc; + chan->_pSrc += 2; + loadSample(chan->_sampleIndex); + break; + + case 4: + chan->_field7 = *++pSrc; + chan->_pSrc += 2; + break; + + case 5: + chan->_field1 = *++pSrc; + chan->_pSrc += 2; + break; + + case 6: + ++pSrc; + if (chan->_fieldE) { + chan->_pSrc += 2; + } else { + chan->_volume = *pSrc >> 1; + updateFlag = true; + chan->_pSrc += 2; + } + break; + + case 7: + ++pSrc; + if (!chan->_fieldE) { + chan->_fieldA = *pSrc; + chan->_field2 = *++pSrc; + chan->_field9 = 1; + } + + chan->_pSrc += 3; + break; + + case 8: + chan->_field1D = *++pSrc; + chan->_pSrc += 2; + break; + + case 9: { + int v1 = *++pSrc; + ++pSrc; + int v2 = (v1 - 1) & getRandomNumber(); + int v3 = pSrc[v2]; + int v4 = pSrc[v1]; + + pSrc[v4 + v1 + 1] = v3; + chan->_pSrc += v1 + 3; + break; + } + + case 10: + ++pSrc; + if (chan->_fieldE) { + chan->_pSrc += 2; + } else { + chan->_field1E = *pSrc >> 1; + updateFlag = true; + chan->_pSrc += 2; + } + break; + + case 11: + chan->_fieldD = *++pSrc; + updateFlag = true; + chan->_pSrc += 2; + break; + + case 12: + chan->_fieldC = *++pSrc; + chan->_field3 = *++pSrc; + chan->_fieldB = 1; + chan->_pSrc += 2; + break; + + case 13: + ++pSrc; + chan->_pSrc += 2; + break; + + case 14: + chan->_field1F = *++pSrc; + chan->_pSrc += 2; + break; + + default: + break; + } + } + } + } + + if (chan->_field1) + updateFNumber(); + + updateFlag = false; + if (chan->_field9 || chan->_fieldB) { + if (!--chan->_field9) { + chan->_field9 = chan->_fieldA; + if (chan->_field2) { + int8 newVal = (int8)chan->_field2 + (int8)chan->_field1E; + if (newVal < 0) { + chan->_field9 = 0; + newVal = 0; + } else if (newVal > 63) { + chan->_field9 = 0; + newVal = 63; + } + + chan->_field1E = newVal; + updateFlag = true; + } + } + + if (!--chan->_fieldB) { + chan->_fieldB = chan->_fieldC; + if (chan->_field3) { + chan->_fieldD = chan->_field3; + updateFlag = true; + } + } + + if (updateFlag) + updateActiveChannel(); + } + } + + ++_activeChannelNumber; +} + +void ASound::updateOctave() { + int reg = 0xB0 + _activeChannelNumber; + write2(8, reg, _ports[reg] & 0xDF); +} + +static int _vList1[] = { + 0x200, 0x21E, 0x23F, 0x261, 0x285, 0x2AB, + 0x2D4, 0x2FF, 0x32D, 0x35D, 0x390, 0x3C7 +}; + +void ASound::updateChannelState() { + updateActiveChannel(); + + if (_channelData[_activeChannelNumber]._field0) { + if (_channelNum1 == _activeChannelNumber) + _stateFlag = 0; + if (_channelNum2 == _activeChannelNumber) + _stateFlag = 1; + + if (!_stateFlag) { + _stateFlag = 1; + if (_v1) + write2(8, 0xB0 + _channelNum1, _ports[0xB0 + _channelNum1] & 0xDF); + + _channelNum1 = _activeChannelNumber; + _v1 = _channelData[_channelNum1]._field0; + _freqMask1 = _channelData[_channelNum1]._freqMask; + _freqBase1 = _channelData[_channelNum1]._freqBase; + _v7 = _channelData[_channelNum1]._field6; + } else { + _stateFlag = 0; + if (_v2) + write2(8, 0xB0 + _channelNum2, _ports[0xB0 + _channelNum2] & 0xDF); + + _channelNum2 = _activeChannelNumber; + _v2 = _channelData[_channelNum2]._field0; + _freqMask2 = _channelData[_channelNum2]._freqMask; + _freqBase2 = _channelData[_channelNum2]._freqBase; + _v8 = _channelData[_channelNum2]._field6; + } + + resultCheck(); + } else { + int reg = 0xA0 + _activeChannelNumber; + int vTimes = (_activeChannelPtr->_field4 + _activeChannelPtr->_field1F) / 12; + int vOffset = (_activeChannelPtr->_field4 + _activeChannelPtr->_field1F) % 12; + int val = _vList1[vOffset] + _activeChannelPtr->_field1D; + write2(8, reg, val & 0xFF); + + reg += 0x10; + write2(8, reg, (_ports[reg] & 0x20) | (vTimes << 2) | (val >> 8)); + + write2(8, reg, _ports[reg] | 0x20); + } +} + +static const int outputIndexes[] = { + 0, 3, 1, 4, 2, 5, 6, 9, 7, 10, 8, 11, 12, 15, 13, 16, 14, 17 +}; +static const int outputChannels[] = { + 0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21, 0 +}; +static const int volumeList[] = { + 0x3F, 0x3F, 0x36, 0x31, 0x2D, 0x2A, 0x28, 0x26, 0x24, 0x22, 0x21, 0x20, 0x1F, 0x1E, 0x1D, 0x1C, + 0x1B, 0x1A, 0x19, 0x19, 0x18, 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14, 0x14, 0x13, 0x12, 0x12, + 0x11, 0x11, 0x10, 0x10, 0x0F, 0x0F, 0x0E, 0x0E, 0x0D, 0x0D, 0x0C, 0x0C, 0x0B, 0x0B, 0x0A, 0x0A, + 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +void ASound::updateActiveChannel() { + int reg = 0x40 + outputChannels[outputIndexes[_activeChannelNumber * 2 + 1]]; + int portVal = _ports[reg] & 0xFFC0; + int newVolume = CLIP(_activeChannelPtr->_volume + _activeChannelPtr->_field1E, 0, 63); + + // Note: Original had a whole block not seeming to be used, since the initialisation + // sets a variable to 5660h, and doesn't change it, so the branch is never taken + int val = CLIP(newVolume - volumeList[_activeChannelPtr->_fieldD], 0, 63); + val = (63 - val) | portVal; + + int val2 = CLIP(newVolume - volumeList[-(_activeChannelPtr->_fieldD - 127)], 0, 63); + val2 = (63 - val2) | portVal; + write2(0, reg, val); + write2(2, reg, val2); +} + +void ASound::loadSample(int sampleIndex) { + _activeChannelReg = 0xB0 + _activeChannelNumber; + write2(8, _activeChannelReg, _ports[_activeChannelReg] & 0xDF); + + _activeChannelReg = _activeChannelNumber; + _samplePtr = &_samples[sampleIndex * 2]; + _v11 = outputChannels[outputIndexes[_activeChannelReg * 2]]; + processSample(); + + AdlibChannelData &cd = _channelData[_activeChannelNumber]; + cd._field6 = _samplePtr->_field14; + cd._freqBase = _samplePtr->_freqBase; + cd._freqMask = _samplePtr->_freqMask; + cd._field0 = _samplePtr->_fieldE; + + _samplePtr = &_samples[sampleIndex * 2 + 1]; + _v11 = outputChannels[outputIndexes[_activeChannelReg * 2 + 1]]; + processSample(); +} + +void ASound::processSample() { + // Write out vib flags and split point + write2(8, 0x40 + _v11, 0x3F); + int depthRhythm = (_ports[0xBD] & 0x3F) | (_amDep ? 0x80 : 0) | + (_vibDep ? 0x40 : 0); + write2(8, 0xBD, depthRhythm); + write2(8, 8, _splitPoint ? 0x40 : 0); + + // Write out feedback & Alg + int val = (_samplePtr->_feedback << 1) | (1 - _samplePtr->_alg); + write2(8, 0xC0 + _activeChannelReg, val); + + // Write out attack/decay rate + val = (_samplePtr->_attackRate << 4) | (_samplePtr->_decayRate & 0xF); + write2(8, 0x60 + _v11, val); + + // Write out sustain level/release rate + val = (_samplePtr->_sustainLevel << 4) | (_samplePtr->_releaseRate & 0xF); + write2(8, 0x80 + _v11, val); + + // Write out misc flags + val = (_samplePtr->_ampMod ? 0x80 : 0) | (_samplePtr->_vib ? 0x40 : 0) + | (_samplePtr->_egTyp ? 0x20 : 0) | (_samplePtr->_ksr ? 0x10 : 0) + | (_samplePtr->_freqMultiple & 0xF); + write2(8, 0x20 + _v11, val); + + // Write out waveform select + write2(8, 0xE0 + _v11, _samplePtr->_waveformSelect & 3); + + // Write out total level & scaling level + val = -((_samplePtr->_totalLevel & 0x3F) - 0x3F) | (_samplePtr->_scalingLevel << 6); + write2(8, 0x40 + _v11, val); +} + +void ASound::updateFNumber() { + int loReg = 0xA0 + _activeChannelNumber; + int hiReg = 0xB0 + _activeChannelNumber; + int val1 = (_ports[hiReg] & 0x1F) << 8; + val1 += _ports[loReg] + _activeChannelPtr->_field1; + write2(8, loReg, val1); + + int val2 = (_ports[hiReg] & 0x20) | (val1 >> 8); + write2(8, hiReg, val2); +} + +int ASound::readBuffer(int16 *buffer, const int numSamples) { + Common::StackLock slock(_driverMutex); + + int32 samplesLeft = numSamples; + memset(buffer, 0, sizeof(int16) * numSamples); + while (samplesLeft) { + if (!_samplesTillCallback) { + poll(); + flush(); + + _samplesTillCallback = _samplesPerCallback; + _samplesTillCallbackRemainder += _samplesPerCallbackRemainder; + if (_samplesTillCallbackRemainder >= CALLBACKS_PER_SECOND) { + _samplesTillCallback++; + _samplesTillCallbackRemainder -= CALLBACKS_PER_SECOND; + } + } + + int32 render = MIN<int>(samplesLeft, _samplesTillCallback); + samplesLeft -= render; + _samplesTillCallback -= render; + + _opl->readBuffer(buffer, render); + buffer += render; + } + return numSamples; +} + +int ASound::command0() { + bool isDisabled = _isDisabled; + _isDisabled = true; + + for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i) + _channels[i].reset(); + + _v1 = 0; + _v2 = 0; + _freqMask1 = _freqMask2 = 0; + _freqBase1 = _freqBase2 = 0; + _v7 = 0; + _v8 = 0; + + // Reset Adlib port registers + for (int reg = 0x4F; reg >= 0x40; --reg) + write2(8, reg, 0x3F); + for (int reg = 0xFF; reg >= 0x60; --reg) + write2(8, reg, 0); + for (int reg = 0x3F; reg > 0; --reg) + write2(8, reg, 0); + write2(8, 1, 0x20); + + _isDisabled = isDisabled; + return 0; +} + +int ASound::command1() { + for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i) + _channels[i].enable(0xFF); + return 0; +} + +int ASound::command2() { + for (int i = 0; i < ADLIB_CHANNEL_MIDWAY; ++i) + _channels[i].setPtr2(_nullData); + return 0; +} + +int ASound::command3() { + for (int i = 0; i < ADLIB_CHANNEL_MIDWAY; ++i) + _channels[i].enable(0xFF); + return 0; +} + +int ASound::command4() { + for (int i = ADLIB_CHANNEL_MIDWAY; i < ADLIB_CHANNEL_COUNT; ++i) + _channels[i].setPtr2(_nullData); + return 0; +} + +int ASound::command5() { + for (int i = 5; i < ADLIB_CHANNEL_COUNT; ++i) + _channels[i].enable(0xFF); + return 0; +} + +int ASound::command6() { + _v9 = _v1; + _v1 = 0; + _v10 = _v2; + _v2 = 0; + + channelOff(0x43); + channelOff(0x44); + channelOff(0x45); + channelOff(0x4B); + channelOff(0x4C); + channelOff(0x4D); + channelOff(0x53); + channelOff(0x54); + channelOff(0x55); + + return 0; +} + +int ASound::command7() { + channelOn(0x43, _channels[0]._volume); + channelOn(0x44, _channels[1]._volume); + channelOn(0x45, _channels[2]._volume); + channelOn(0x4B, _channels[3]._volume); + channelOn(0x4C, _channels[4]._volume); + channelOn(0x4D, _channels[5]._volume); + + _v1 = _v9; + _v2 = _v10; + + if (_v9 != _v10) + resultCheck(); + + _isDisabled = 0; + return _v10; +} + +int ASound::command8() { + int result = 0; + for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i) + result |= _channels[i]._activeCount; + + return result; +} + +/*-----------------------------------------------------------------------*/ + +const ASound1::CommandPtr ASound1::_commandList[42] = { + &ASound1::command0, &ASound1::command1, &ASound1::command2, &ASound1::command3, + &ASound1::command4, &ASound1::command5, &ASound1::command6, &ASound1::command7, + &ASound1::command8, &ASound1::command9, &ASound1::command10, &ASound1::command11, + &ASound1::command12, &ASound1::command13, &ASound1::command14, &ASound1::command15, + &ASound1::command16, &ASound1::command17, &ASound1::command18, &ASound1::command19, + &ASound1::command20, &ASound1::command21, &ASound1::command22, &ASound1::command23, + &ASound1::command24, &ASound1::command25, &ASound1::command26, &ASound1::command27, + &ASound1::command28, &ASound1::command29, &ASound1::command30, &ASound1::command31, + &ASound1::command32, &ASound1::command33, &ASound1::command34, &ASound1::command35, + &ASound1::command36, &ASound1::command37, &ASound1::command38, &ASound1::command39, + &ASound1::command40, &ASound1::command41 +}; + +ASound1::ASound1(Audio::Mixer *mixer) + : ASound(mixer, "asound.001", 0x1520) { + _cmd23Toggle = false; + + // Load sound samples + _soundFile.seek(_dataOffset + 0x12C); + for (int i = 0; i < 98; ++i) + _samples.push_back(AdlibSample(_soundFile)); +} + +int ASound1::command(int commandId, int param) { + if (commandId > 41) + return 0; + + _commandParam = param; + _frameCounter = 0; + return (this->*_commandList[commandId])(); +} + +int ASound1::command9() { + playSound(0xC68, 12); + return 0; +} + +int ASound1::command10() { + byte *pData1 = loadData(0x130E, 48); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x133E, 392)); + _channels[2].load(loadData(0x14C6, 46)); + _channels[3].load(loadData(0x14F4, 48)); + } + + return 0; +} + +int ASound1::command11() { + command111213(); + _channels[0]._field1E = 0; + _channels[1]._field1E = 0; + return 0; +} + +int ASound1::command12() { + command111213(); + _channels[0]._field1E = 40; + _channels[1]._field1E = 0; + return 0; +} + +int ASound1::command13() { + command111213(); + _channels[0]._field1E = 40; + _channels[1]._field1E = 50; + return 0; +} + +int ASound1::command14() { + playSound(0x1216, 248); + return 0; +} + +int ASound1::command15() { + byte *pData1 = loadData(0x1524, 152); + if (!isSoundActive(pData1)) { + command1(); + _channels[4].load(pData1); + _channels[5].load(loadData(0x15BC, 94)); + _channels[6].load(loadData(0x161A, 94)); + _channels[7].load(loadData(0x1678, 42)); + _channels[8].load(loadData(0x16A2, 42)); + } + + return 0; +} + +int ASound1::command16() { + playSound(0xC74, 14); + return 0; +} + +int ASound1::command17() { + playSound(0xE9A, 10); + return 0; +} + +int ASound1::command18() { + command1(); + playSound(0xCA6, 20); + return 0; +} + +int ASound1::command19() { + command1(); + playSound(0xCBA, 74); + return 0; +} + +int ASound1::command20() { + byte *pData = loadData(0xD18, 28); + if (!isSoundActive(pData)) + playSoundData(pData); + return 0; +} + +int ASound1::command21() { + playSound(0xD04, 20); + return 0; +} + +int ASound1::command22() { + byte *pData = loadData(0xD34, 10); + pData[6] = (getRandomNumber() & 7) + 85; + + if (!isSoundActive(pData)) + playSoundData(pData); + + return 0; +} + +int ASound1::command23() { + _cmd23Toggle = !_cmd23Toggle; + playSound(_cmd23Toggle ? 0xD3E : 0xD46, 8); + return 0; +} + +int ASound1::command24() { + playSound(0xD4E, 18); + playSound(0xD60, 20); + playSound(0xD74, 14); + return 0; +} + +int ASound1::command25() { + byte *pData = loadData(0xD82, 16); + if (!isSoundActive(pData)) + playSoundData(pData); + + return 0; +} + +int ASound1::command26() { + byte *pData = loadData(0xEEC, 10); + pData[5] = (command2627293032() + 0x7F) & 0xFF; + + if (!isSoundActive(pData)) + _channels[6].load(pData); + + return 0; +} + +int ASound1::command27() { + byte *pData = loadData(0xEE2, 10); + pData[5] = (command2627293032() + 0x40) & 0xFF; + + if (!isSoundActive(pData)) + _channels[7].load(pData); + + return 0; +} + +int ASound1::command28() { + playSound(0xD92, 28); + return 0; +} + +int ASound1::command29() { + byte *pData = loadData(0xC82, 36); + byte v = (command2627293032() + 0x40) & 0xFF; + pData[7] = pData[13] = pData[21] = pData[27] = v; + + if (!isSoundActive(pData)) + playSoundData(pData, 0); + + return 0; +} + +int ASound1::command30() { + byte *pData = loadData(0xEA6, 16); + pData[7] = (command2627293032() + 0x40) & 0xFF; + + if (!isSoundActive(pData)) + playSoundData(pData, 0); + + return 0; +} + +int ASound1::command31() { + byte *pData = loadData(0xDAE, 14); + if (!isSoundActive(pData)) + playSoundData(pData); + + return 0; +} + +int ASound1::command32() { + byte *pData = loadData(0xEB4, 46); + int v = command2627293032() + 0x40; + pData[9] = pData[17] = pData[25] = pData[33] = v & 0xFF; + pData[11] = pData[19] = pData[27] = pData[35] = v >> 8; + + if (!isSoundActive(pData)) + playSoundData(pData, 0); + + return 0; +} + +int ASound1::command33() { + playSound(0xDBC, 10); + playSound(0xDC6, 10); + return 0; +} + +int ASound1::command34() { + int v = getRandomNumber() & 0x20; + if (!v) + v = 0x60; + + byte *pData = loadData(0xDD0, 22); + pData[8] = pData[15] = v; + playSoundData(pData); + return 0; +} + +int ASound1::command35() { + playSound(0xDE6, 16); + return 0; +} + +int ASound1::command36() { + playSound(0xE10, 10); + command34(); + + return 0; +} + +int ASound1::command37() { + playSound(0xE1A, 14); + return 0; +} + +int ASound1::command38() { + playSound(0xE28, 114); + return 0; +} + +int ASound1::command39() { + byte *pData1 = loadData(0x16CC, 82); + if (!isSoundActive(pData1)) { + _channels[5].load(pData1); + _channels[6].load(loadData(0x171E, 30)); + _channels[7].load(loadData(0x173C, 40)); + _channels[8].load(loadData(0x1764, 64)); + } + return 0; +} + +int ASound1::command40() { + playSound(0xDF6, 26); + return 0; +} + +int ASound1::command41() { + playSound(0xC32, 34); + playSound(0xC54, 20); + return 0; +} + +void ASound1::command111213() { + byte *pData1 = loadData(0xEF6, 408); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x108E, 266)); + _channels[2].load(loadData(0x1198, 66)); + _channels[2].load(loadData(0x11DA, 60)); + } +} + +int ASound1::command2627293032() { + return (_commandParam > 0x40) ? _commandParam - 0x40 : _commandParam & 0xff00; +} + + +/*-----------------------------------------------------------------------*/ + +const ASound2::CommandPtr ASound2::_commandList[44] = { + &ASound2::command0, &ASound2::command1, &ASound2::command2, &ASound2::command3, + &ASound2::command4, &ASound2::command5, &ASound2::command6, &ASound2::command7, + &ASound2::command8, &ASound2::command9, &ASound2::command10, &ASound2::command11, + &ASound2::command12, &ASound2::command13, &ASound2::command14, &ASound2::command15, + &ASound2::command16, &ASound2::command17, &ASound2::command18, &ASound2::command19, + &ASound2::command20, &ASound2::command21, &ASound2::command22, &ASound2::command23, + &ASound2::command24, &ASound2::command25, &ASound2::command26, &ASound2::command27, + &ASound2::command28, &ASound2::command29, &ASound2::command30, &ASound2::command31, + &ASound2::command32, &ASound2::command33, &ASound2::command34, &ASound2::command35, + &ASound2::command36, &ASound2::command37, &ASound2::command38, &ASound2::command39, + &ASound2::command40, &ASound2::command41, &ASound2::command42, &ASound2::command43 +}; + +ASound2::ASound2(Audio::Mixer *mixer) : ASound(mixer, "asound.002", 0x15E0) { + _command12Param = 0xFD; + + // Load sound samples + _soundFile.seek(_dataOffset + 0x144); + for (int i = 0; i < 164; ++i) + _samples.push_back(AdlibSample(_soundFile)); +} + +int ASound2::command(int commandId, int param) { + if (commandId > 43) + return 0; + + _frameCounter = 0; + return (this->*_commandList[commandId])(); +} + +int ASound2::command0() { + _command12Param = 0xFD; + return ASound::command0(); +} + +int ASound2::command9() { + byte *pData1 = loadData(0x1094, 376); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[2].load(loadData(0x123E, 130)); + + command9Randomize(); + _channels[1].load(loadData(0x120C, 50)); + } + return 0; +} + +void ASound2::command9Randomize() { + // Randomization + int v; + while (((v = getRandomNumber()) & 0x3F) > 36) + ; + + byte *pData = loadData(0x120C, 50); + command9Apply(pData, v + 20, -1); + command9Apply(pData + 1, 10 - ((v + 1) / 6), 1); +} + +void ASound2::command9Apply(byte *data, int val, int incr) { + data += 8; + for (int ctr = 0; ctr < 10; ++ctr, data += 4, val += incr) { + *data = val; + } +} + +int ASound2::command10() { + byte *pData1 = loadData(0x12C0, 60); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x12FC, 318)); + _channels[2].load(loadData(0x143A, 110)); + } + + return 0; +} + +int ASound2::command11() { + byte *pData = loadData(0x14A8, 170); + if (!isSoundActive(pData)) { + playSoundData(pData); + playSoundData(loadData(0x1552, 1802)); + playSoundData(loadData(0x1C5C, 716)); + playSoundData(loadData(0x1F28, 106)); + } + + return 0; +} + +int ASound2::command12() { + _command12Param += 26; + byte v = _command12Param & 0x7f; + + byte *pData = loadData(0x4A5E, 38); + pData[5] = pData[20] = v; + playSoundData(pData); + + pData = loadData(0x4A84, 30); + pData[5] = pData[18] = v; + playSoundData(pData); + + return 0; +} + +int ASound2::command13() { + playSoundData(loadData(0x4AA2, 20)); + playSoundData(loadData(0x4AB6, 20)); + + return 0; +} + +int ASound2::command14() { + playSound(0x4ACA, 40); + playSound(0x4AF2, 42); + + return 0; +} + +int ASound2::command15() { + byte *pData1 = loadData(0x1F92, 1074); + if (!isSoundActive(pData1)) { + command1(); + playSoundData(pData1); + playSound(0x23C4, 1050); + playSound(0x27DE, 58); + playSound(0x2818, 712); + playSound(0x2AE0, 256); + } + + return 0; +} + +int ASound2::command16() { + byte *pData1 = loadData(0x3960, 280); + if (!isSoundActive(pData1)) { + command1(); + playSoundData(pData1); + playSound(0x3A78, 266); + playSound(0x3B72, 322); + playSound(0x3CC4, 488); + playSound(0x3EAC, 104); + playSound(0x3F14, 104); + } + + return 0; +} + +int ASound2::command17() { + byte *pData1 = loadData(0x3F7C, 432); + if (!isSoundActive(pData1)) { + command1(); + playSoundData(pData1); + playSound(0x412C, 422); + playSound(0x42D2, 424); + playSound(0x447A, 418); + } + + return 0; +} + +static const int command18_list[16][2] = { + { 0x337C, 28 }, { 0x3398, 26 }, { 0x33B2, 26 }, { 0x33CC, 26 }, + { 0x33E6, 56 }, { 0x341E, 46 }, { 0x344C, 56 }, { 0x3484, 22 }, + { 0x349A, 38 }, { 0x34C0, 62 }, { 0x34FE, 26 }, { 0x3518, 26 }, + { 0x3532, 26 }, { 0x354C, 26 }, { 0x3566, 32 }, { 0x3586, 24 } +}; + +int ASound2::command18() { + if (_channels[3]._activeCount == 0) { + int idx = (getRandomNumber() & 0x1E) >> 1; + byte *pData = loadData(command18_list[idx][0], command18_list[idx][1]); + _channels[3].load(pData); + } + + return 0; +} + +int ASound2::command19() { + byte *pData1 = loadData(0x2BE0, 366); + if (!isSoundActive(pData1)) { + command1(); + playSoundData(pData1); + playSound(0x2D4E, 460); + playSound(0x2F1A, 266); + playSound(0x3024, 328); + playSound(0x316C, 162); + playSound(0x320E, 366); + } + + return 0; +} + +int ASound2::command20() { + playSound(0x4A36, 40); + + return 0; +} + +int ASound2::command21() { + playSound(0x49DE, 16); + playSound(0x49EE, 16); + playSound(0x49FF, 16); + + return 0; +} + +int ASound2::command22() { + playSound(0x4A0E, 24); + playSound(0x4A26, 16); + + return 0; +} + +int ASound2::command23() { + playSound(0x49B6, 16); + + return 0; +} + +int ASound2::command24() { + playSound(0x49C6, 24); + + return 0; +} + +int ASound2::command25() { + playSound(0x49AC, 10); + + return 0; +} + +int ASound2::command26() { + playSound(0x498A, 14); + playSound(0x4998, 20); + + return 0; +} + +int ASound2::command27() { + playSound(0x4912, 80); + playSound(0x4962, 40); + + return 0; +} + +int ASound2::command28() { + playSound(0x48E8, 28); + playSound(0x4904, 14); + + return 0; +} + +int ASound2::command29() { + playSound(0x48B2, 22); + + return 0; +} + +int ASound2::command30() { + playSound(0x4870, 22); + playSound(0x4886, 22); + playSound(0x489C, 22); + + return 0; +} + +int ASound2::command31() { + playSound(0x482E, 22); + playSound(0x4844, 22); + playSound(0x489C, 22); + + return 0; +} + +int ASound2::command32() { + playSound(0x46E8, 10); + + return 0; +} + +int ASound2::command33() { + playSound(0x46D8, 16); + + return 0; +} + +int ASound2::command34() { + playSound(0x46C8, 16); + + return 0; +} + +int ASound2::command35() { + playSound(0x46B2, 22); + + return 0; +} + +int ASound2::command36() { + playSound(0x4624, 16); + + return 0; +} + +int ASound2::command37() { + playSound(0x4674, 20); + playSound(0x4688, 32); + playSound(0x46A8, 10); + + return 0; +} + +int ASound2::command38() { + byte *pData1 = loadData(0x359E, 202); + if (!isSoundActive(pData1)) { + command1(); + playSoundData(pData1); + playSound(0x3668, 220); + playSound(0x3744, 124); + playSound(0x37C0, 162); + playSound(0x3862, 78); + playSound(0x38B0, 176); + } + + return 0; +} + +int ASound2::command39() { + byte *pData = loadData(0x466A, 10); + pData[6] = (getRandomNumber() & 7) + 85; + playSoundData(pData); + + return 0; +} + +int ASound2::command40() { + playSound(0x4634, 34); + playSound(0x4656, 20); + + return 0; +} + +int ASound2::command41() { + playSound(0x48C8, 32); + + return 0; +} + +int ASound2::command42() { + playSound(0x46F2, 156); + playSound(0x478E, 160); + + return 0; +} + +int ASound2::command43() { + playSound(0x4B1C, 40); + playSound(0x4B44, 41); + + return 0; +} + +/*-----------------------------------------------------------------------*/ + +const ASound3::CommandPtr ASound3::_commandList[61] = { + &ASound3::command0, &ASound3::command1, &ASound3::command2, &ASound3::command3, + &ASound3::command4, &ASound3::command5, &ASound3::command6, &ASound3::command7, + &ASound3::command8, &ASound3::command9, &ASound3::command10, &ASound3::command11, + &ASound3::nullCommand, &ASound3::command13, &ASound3::command14, &ASound3::command15, + &ASound3::command16, &ASound3::command17, &ASound3::command18, &ASound3::command19, + &ASound3::command20, &ASound3::command21, &ASound3::command22, &ASound3::command23, + &ASound3::command24, &ASound3::command25, &ASound3::command26, &ASound3::command27, + &ASound3::command28, &ASound3::command29, &ASound3::command30, &ASound3::command31, + &ASound3::command32, &ASound3::command33, &ASound3::command34, &ASound3::command35, + &ASound3::command36, &ASound3::command37, &ASound3::command38, &ASound3::command39, + &ASound3::command40, &ASound3::command41, &ASound3::command42, &ASound3::command43, + &ASound3::command44, &ASound3::command45, &ASound3::command46, &ASound3::command47, + &ASound3::nullCommand, &ASound3::command49, &ASound3::command50, &ASound3::command51, + &ASound3::nullCommand, &ASound3::nullCommand, &ASound3::nullCommand, &ASound3::nullCommand, + &ASound3::nullCommand, &ASound3::command57, &ASound3::nullCommand, &ASound3::command59, + &ASound3::command60 +}; + +ASound3::ASound3(Audio::Mixer *mixer) : ASound(mixer, "asound.003", 0x15B0) { + _command39Flag = false; + + // Load sound samples + _soundFile.seek(_dataOffset + 0x122); + for (int i = 0; i < 192; ++i) + _samples.push_back(AdlibSample(_soundFile)); +} + +int ASound3::command(int commandId, int param) { + if (commandId > 60) + return 0; + + _commandParam = param; + _frameCounter = 0; + return (this->*_commandList[commandId])(); +} + +int ASound3::command9() { + AdlibChannel::_channelsEnabled = _commandParam != 0; + + return 0; +} + +int ASound3::command10() { + byte *pData1 = loadData(0x13EA, 254); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0X14E8, 452)); + _channels[2].load(loadData(0x16AC, 396)); + _channels[3].load(loadData(0x1838, 118)); + _channels[4].load(loadData(0x18AE, 74)); + } + + return 0; +} + +int ASound3::command11() { + byte *pData1 = loadData(0x2B84, 596); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x2DD8, 562)); + _channels[2].load(loadData(0x300A, 1694)); + _channels[3].load(loadData(0x36A8, 1100)); + _channels[4].load(loadData(0x3AF4, 420)); + _channels[5].load(loadData(0x3C98, 1516)); + } + + return 0; +} + +int ASound3::command13() { + byte *pData1 = loadData(0x4470, 64); + if (!isSoundActive(pData1)) { + command1(); + playSoundData(pData1); + playSound(0x44B0, 64); + playSound(0x44F0, 64); + playSound(0x4530, 64); + playSound(0x4570, 64); + playSound(0X45b0, 64); + } + + return 0; +} + +int ASound3::command14() { + byte *pData1 = loadData(0X45F0, 36); + if (!isSoundActive(pData1)) { + command1(); + playSoundData(pData1); + playSound(0x4614, 36); + playSound(0x4638, 36); + playSound(0x465C, 32); + playSound(0x467C, 76); + playSound(0x46C8, 74); + } + + return 0; +} + +int ASound3::command15() { + _channels[3].load(loadData(0x36A8, 1100)); + _channels[4].load(loadData(0x3AF4, 420)); + _channels[5].load(loadData(0x3C98, 1516)); + + _channels[3]._field20 = 0xDD; + _channels[4]._field20 = 0xDD; + _channels[5]._field20 = 0xDD; + + return 0; +} + +int ASound3::command16() { + byte *pData1 = loadData(0x4712, 398); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x48A0, 354)); + _channels[2].load(loadData(0x4A02, 410)); + _channels[3].load(loadData(0x4B9C, 392)); + } + + return 0; +} + +int ASound3::command17() { + byte *pData1 = loadData(0x18F8, 400); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x1A88, 680)); + _channels[2].load(loadData(0x1D30, 478)); + _channels[3].load(loadData(0x1F0E, 1146)); + _channels[4].load(loadData(0x2388, 1006)); + _channels[5].load(loadData(0x2776, 1038)); + } + + return 0; +} + +int ASound3::command18() { + byte *pData1 = loadData(0x4284, 142); + if (!isSoundActive(pData1)) { + command1(); + playSoundData(pData1); + playSound(0x4312, 172); + playSound(0x43BE, 88); + playSound(0x4416, 90); + } + + return 0; +} + +int ASound3::command19() { + playSound(0x4F6, 8); + + return 0; +} + +int ASound3::command20() { + playSound(0x4F1C, 10); + + return 0; +} + +int ASound3::command21() { + playSound(0x4F2E, 8); + + return 0; +} + +int ASound3::command22() { + playSound(0x4F36, 16); + + return 0; +} + +int ASound3::command23() { + playSound(0x4F50, 10); + playSound(0x4F46, 10); + + return 0; +} + +int ASound3::command24() { + // WORKAROUND: Original calls isSoundActive without loading data pointer + byte *pData = loadData(0x4EFC, 12); + if (!isSoundActive(pData)) { + int v; + while ((v = (getRandomNumber() & 0x3F)) > 45) + ; + + pData[6] = v + 19; + playSoundData(pData); + } + + return 0; +} + +int ASound3::command25() { + playSound(0x4EE6, 22); + + return 0; +} + +int ASound3::command26() { + playSound(0x4F5A, 8); + + return 0; +} + +int ASound3::command27() { + playSound(0x4DA2, 34); + playSound(0x4DC4, 20); + + return 0; +} + +int ASound3::command28() { + playSound(0x4F72, 10); + playSound(0x4F72, 10); + + return 0; +} + +int ASound3::command29() { + playSound(0x4F72, 10); + playSound(0x4F72, 10); + + return 0; +} + +int ASound3::command30() { + playSound(0x4E5A, 22); + playSound(0x4E70, 22); + playSound(0x4E86, 22); + + return 0; +} + +int ASound3::command31() { + playSound(0x4F7C, 40); + + return 0; +} + +int ASound3::command32() { + playSound(0x4ED2, 10); + + return 0; +} + +int ASound3::command33() { + playSound(0x4EC2, 16); + + return 0; +} + +int ASound3::command34() { + playSound(0x4EB2, 16); + + return 0; +} + +int ASound3::command35() { + playSound(0x4E9C, 22); + + return 0; +} + +int ASound3::command36() { + playSound(0x4D2C, 16); + + return 0; +} + +int ASound3::command37() { + playSound(0x4E1E, 20); + playSound(0x4E32, 30); + playSound(0x4E50, 10); + + return 0; +} + +int ASound3::command38() { + playSound(0x4FAC, 10); + + return 0; +} + +int ASound3::command39() { + _command39Flag = !_command39Flag; + if (_command39Flag) { + playSound(0x4FD0, 8); + } else { + playSound(0x4FD8, 8); + } + + return 0; +} + +int ASound3::command40() { + _command39Flag = !_command39Flag; + if (_command39Flag) { + playSound(0x4EE0, 8); + } else { + playSound(0x4EE8, 8); + } + + return 0; +} + +int ASound3::command41() { + playSound(0x4F08, 20); + + return 0; +} + +int ASound3::command42() { + playSound(0x4DD8, 28); + playSound(0x4DF4, 42); + + return 0; +} + +int ASound3::command43() { + playSound(0x4FB6, 12); + playSound(0x4FC2, 14); + + return 0; +} + +int ASound3::command44() { + playSound(0x4FFE, 14); + + return 0; +} + +int ASound3::command45() { + playSound(0x500C, 14); + + return 0; +} + +int ASound3::command46() { + playSound(0x4D78, 14); + playSound(0x4D86, 14); + playSound(0x4D94, 14); + + return 0; +} + +int ASound3::command47() { + playSound(0x4D62, 8); + playSound(0x4D6A, 14); + + return 0; +} + +int ASound3::command49() { + playSound(0x4D62, 8); + playSound(0x4D6A, 14); + + return 0; +} + +int ASound3::command50() { + playSound(0x4D3C, 14); + playSound(0x4D4A, 14); + playSound(0x4D58, 10); + + return 0; +} + +int ASound3::command51() { + playSound(0x4FF0, 14); + + return 0; +} + +int ASound3::command57() { + byte *pData = loadData(0x4EDC, 10); + pData[6] = (getRandomNumber() & 7) + 85; + playSoundData(pData); + + return 0; +} + +int ASound3::command59() { + playSound(0x4F62, 16); + + return 0; +} + +int ASound3::command60() { + playSound(0x4FA4, 8); + + return 0; +} + +/*-----------------------------------------------------------------------*/ + +const ASound4::CommandPtr ASound4::_commandList[61] = { + &ASound4::command0, &ASound4::command1, &ASound4::command2, &ASound4::command3, + &ASound4::command4, &ASound4::command5, &ASound4::command6, &ASound4::command7, + &ASound4::command8, &ASound4::nullCommand, &ASound4::command10, &ASound4::nullCommand, + &ASound4::command12, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, + &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::command19, + &ASound4::command20, &ASound4::command21, &ASound4::nullCommand, &ASound4::nullCommand, + &ASound4::command24, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::command27, + &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::command30, &ASound4::nullCommand, + &ASound4::command32, &ASound4::command33, &ASound4::command34, &ASound4::command35, + &ASound4::command36, &ASound4::command37, &ASound4::command38, &ASound4::nullCommand, + &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::command43, + &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, + &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, + &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, + &ASound4::nullCommand, &ASound4::command57, &ASound4::nullCommand, &ASound4::command59, + &ASound4::command60 +}; + +ASound4::ASound4(Audio::Mixer *mixer) : ASound(mixer, "asound.004", 0x14F0) { + // Load sound samples + _soundFile.seek(_dataOffset + 0x122); + for (int i = 0; i < 210; ++i) + _samples.push_back(AdlibSample(_soundFile)); +} + +int ASound4::command(int commandId, int param) { + if (commandId > 60) + return 0; + + _commandParam = param; + _frameCounter = 0; + return (this->*_commandList[commandId])(); +} + +int ASound4::command10() { + byte *pData = loadData(0x22AA, 254); + if (!isSoundActive(pData)) { + command1(); + _channels[0].load(pData); + _channels[1].load(loadData(0x23A8, 452)); + _channels[2].load(loadData(0x256C, 396)); + _channels[3].load(loadData(0x26F8, 118)); + _channels[4].load(loadData(0x276E, 74)); + } + + return 0; +} + +int ASound4::command12() { + byte *pData = loadData(0x16A8, 550); + if (!isSoundActive(pData)) { + command1(); + _channels[0].load(pData); + _channels[1].load(loadData(0x18CE, 442)); + _channels[2].load(loadData(0x1A88, 298)); + _channels[3].load(loadData(0x1BB2, 354)); + _channels[4].load(loadData(0x1D14, 572)); + _channels[4].load(loadData(0x1F50, 560)); + } + + int v = (_commandParam > 0x40) ? _commandParam - 0x40 : 0; + v += 0xB5; + for (int channelNum = 0; channelNum < 6; ++channelNum) + _channels[channelNum]._field20 = v; + + return 0; +} + +int ASound4::command19() { + playSound(0x28EC, 8); + + return 0; +} + +int ASound4::command20() { + playSound(0x28E2, 10); + + return 0; +} + +int ASound4::command21() { + playSound(0x27C0, 8); + + return 0; +} + +int ASound4::command24() { + int v; + while ((v = (getRandomNumber() & 0x3F)) > 45) + ; + + byte *pData = loadData(0x28D6, 12); + pData[6] = v + 19; + playSoundData(pData); + + return 0; +} + +int ASound4::command27() { + playSound(0x27D8, 34); + playSound(0x27FA, 20); + + return 0; +} + +int ASound4::command30() { + playSound(0x284A, 22); + playSound(0x2860, 22); + playSound(0x2876, 22); + + return 0; +} + +int ASound4::command32() { + playSound(0x28C2, 10); + + return 0; +} + +int ASound4::command33() { + playSound(0x28B2, 16); + + return 0; +} + +int ASound4::command34() { + playSound(0x28A2, 16); + + return 0; +} + +int ASound4::command35() { + playSound(0x288C, 22); + + return 0; +} + +int ASound4::command36() { + playSound(0x27C8, 16); + + return 0; +} + +int ASound4::command37() { + playSound(0x280E, 20); + playSound(0x2822, 30); + playSound(0x2840, 10); + + return 0; +} + +int ASound4::command38() { + playSound(0x2904, 10); + + return 0; +} + +int ASound4::command43() { + playSound(0x290E, 12); + playSound(0x291A, 14); + + return 0; +} + +int ASound4::command52() { + byte *pData = loadData(0x23A8, 452); + if (_channels[1]._ptr1 == pData) { + pData = loadData(0x146E, 570); + if (!isSoundActive(pData)) { + _channels[0].load(pData); + _channels[1]._field20 = 0xD8; + _channels[2]._field20 = 0xD8; + } + } + + return 0; +} + +int ASound4::command53() { + method1(); + _channels[0]._field20 = 0; + + return 0; +} + +int ASound4::command54() { + method1(); + _channels[1]._field20 = 0; + _channels[2]._field20 = 0; + + return 0; +} + +int ASound4::command55() { + method1(); + _channels[3]._field20 = 0; + _channels[4]._field20 = 0; + + return 0; +} + +int ASound4::command56() { + method1(); + _channels[5]._field20 = 0; + + return 0; +} + +int ASound4::command57() { + int v = (getRandomNumber() & 7) + 85; + byte *pData = loadData(0x28CC, 10); + pData[6] = v; + playSoundData(pData); + + return 0; +} + +int ASound4::command58() { + byte *pData = loadData(0x146E, 570); + if (_channels[1]._ptr1 == pData) { + _channels[0].load(loadData(0x22AA, 254)); + _channels[1]._field20 = 0; + _channels[2]._field20 = 0; + } + + return 0; +} + +int ASound4::command59() { + playSound(0x28F4, 8); + + return 0; +} + +int ASound4::command60() { + playSound(0x28FC, 8); + + return 0; +} + +void ASound4::method1() { + byte *pData = loadData(0x2180, 58); + if (!isSoundActive(pData)) { + command1(); + + _channels[0].load(pData); + _channels[1].load(loadData(0x21BA, 48)); + _channels[2].load(loadData(0x21EA, 50)); + _channels[3].load(loadData(0x221C, 40)); + _channels[4].load(loadData(0x2244, 28)); + _channels[5].load(loadData(0x2260, 74)); + + for (int channel = 0; channel < 6; ++channel) + _channels[channel]._field20 = 0xB5; + } +} + + +/*-----------------------------------------------------------------------*/ + +const ASound5::CommandPtr ASound5::_commandList[42] = { + &ASound5::command0, &ASound5::command1, &ASound5::command2, &ASound5::command3, + &ASound5::command4, &ASound5::command5, &ASound5::command6, &ASound5::command7, + &ASound5::command8, &ASound5::command9, &ASound5::command10, &ASound5::command11, + &ASound5::command11, &ASound5::command13, &ASound5::command14, &ASound5::command15, + &ASound5::command16, &ASound5::command17, &ASound5::command18, &ASound5::command19, + &ASound5::command20, &ASound5::command21, &ASound5::command22, &ASound5::command23, + &ASound5::command11, &ASound5::command11, &ASound5::command26, &ASound5::command27, + &ASound5::command28, &ASound5::command29, &ASound5::command30, &ASound5::command31, + &ASound5::command32, &ASound5::command33, &ASound5::command34, &ASound5::command35, + &ASound5::command36, &ASound5::command37, &ASound5::command38, &ASound5::command39, + &ASound5::command40, &ASound5::command41 +}; + +ASound5::ASound5(Audio::Mixer *mixer) : ASound(mixer, "asound.002", 0x15E0) { + // Load sound samples + _soundFile.seek(_dataOffset + 0x144); + for (int i = 0; i < 164; ++i) + _samples.push_back(AdlibSample(_soundFile)); +} + +int ASound5::command(int commandId, int param) { + if (commandId > 41) + return 0; + + _frameCounter = 0; + return (this->*_commandList[commandId])(); +} + +int ASound5::command9() { + byte *pData = loadData(0x2114, 10); + pData[6] = (getRandomNumber() & 7) + 85; + playSoundData(pData); + + return 0; +} + +int ASound5::command10() { + playSound(0x211E, 10); + + return 0; +} + +int ASound5::command11() { + playSound(0x2016, 10); + + return 0; +} + +int ASound5::command13() { + playSound(0x2154, 10); + + return 0; +} + +int ASound5::command14() { + playSound(0x21DC, 22); + + return 0; +} + +int ASound5::command15() { + byte *pData = loadData(0x21DC, 22); + if (_channels[0]._ptr1 == pData) { + pData = loadData(0x1F2, 12); + _channels[0]._soundData = pData; + _channels[0]._field17 = 1; + _channels[0]._field19 = 1; + } + + return 0; +} + +int ASound5::command16() { + playSound(0x214C, 8); + + return 0; +} + +int ASound5::command17() { + playSound(0x2142, 10); + + return 0; +} + +int ASound5::command18() { + playSound(0x21A2, 22); + + return 0; +} + +int ASound5::command19() { + playSound(0x2190, 18); + + return 0; +} + +int ASound5::command20() { + playSound(0x2170, 16); + + return 0; +} + +int ASound5::command21() { + playSound(0x2180, 16); + + return 0; +} + +int ASound5::command22() { + playSound(0x2168, 8); + + return 0; +} + +int ASound5::command23() { + playSound(0x215E, 10); + + return 0; +} + +int ASound5::command26() { + playSound(0x21B8, 12); + + return 0; +} + +int ASound5::command27() { + playSound(0x21C4, 24); + + return 0; +} + +int ASound5::command28() { + playSound(0x2020, 34); + playSound(0x4904, 20); + + return 0; +} + +int ASound5::command29() { + byte *pData = loadData(0x17C, 312); + if (!isSoundActive(pData)) { + command1(); + _channels[0].load(pData); + _channels[1].load(loadData(0x1864, 304)); + _channels[2].load(loadData(0x1994, 222)); + _channels[3].load(loadData(0x1864, 304)); + _channels[4].load(loadData(0x1994, 222)); + } + + return 0; +} + +int ASound5::command30() { + playSound(0x2092, 22); + playSound(0x20A8, 22); + playSound(0x20BE, 22); + + return 0; +} + +int ASound5::command31() { + playSound(0x2128, 22); + playSound(0x2134, 14); + + return 0; +} + +int ASound5::command32() { + playSound(0x210A, 10); + + return 0; +} + +int ASound5::command33() { + playSound(0x20FA, 16); + + return 0; +} + +int ASound5::command34() { + playSound(0x20EA, 16); + + return 0; +} + +int ASound5::command35() { + playSound(0x20D4, 22); + + return 0; +} + +int ASound5::command36() { + playSound(0x2006, 16); + + return 0; +} + +int ASound5::command37() { + playSound(0x2056, 20); + playSound(0x206A, 30); + playSound(0x2088, 10); + + return 0; +} + +int ASound5::command38() { + byte *pData1 = loadData(0x14F2, 570); + if (_channels[3]._ptr1 == pData1) { + _channels[3].load(loadData(0x1A72, 522)); + _channels[3].load(loadData(0x1C7C, 874)); + } + + return 0; +} + +int ASound5::command39() { + playSound(0x1FEE, 8); + + return 0; +} + +int ASound5::command40() { + playSound(0x1FF6, 16); + + return 0; +} + +int ASound5::command41() { + byte *pData1 = loadData(0x14F2, 570); + if (!isSoundActive(pData1)) { + byte *pData2 = loadData(0x1A72, 522); + if (_channels[3]._ptr1 == pData2) { + _channels[3].load(pData1); + _channels[4].load(loadData(0x1FE6, 8)); + } + } + + return 0; +} + +/*-----------------------------------------------------------------------*/ + +const ASound6::CommandPtr ASound6::_commandList[30] = { + &ASound6::command0, &ASound6::command1, &ASound6::command2, &ASound6::command3, + &ASound6::command4, &ASound6::command5, &ASound6::command6, &ASound6::command7, + &ASound6::command8, &ASound6::command9, &ASound6::command10, &ASound6::command11, + &ASound6::command11, &ASound6::command13, &ASound6::command14, &ASound6::command15, + &ASound6::command16, &ASound6::command17, &ASound6::command18, &ASound6::command19, + &ASound6::command20, &ASound6::command21, &ASound6::command22, &ASound6::command23, + &ASound6::command11, &ASound6::command11, &ASound6::nullCommand, &ASound6::nullCommand, + &ASound6::nullCommand, &ASound6::command29 +}; + +ASound6::ASound6(Audio::Mixer *mixer) : ASound(mixer, "asound.006", 0x1390) { + // Load sound samples + _soundFile.seek(_dataOffset + 0x122); + for (int i = 0; i < 200; ++i) + _samples.push_back(AdlibSample(_soundFile)); +} + +int ASound6::command(int commandId, int param) { + if (commandId > 29) + return 0; + + _frameCounter = 0; + return (this->*_commandList[commandId])(); +} + +int ASound6::command9() { + byte *pData = loadData(0x2194, 10); + pData[6] = (getRandomNumber() & 7) + 85; + playSoundData(pData); + + return 0; +} + +int ASound6::command10() { + playSound(0x2224, 24); + + return 0; +} + +int ASound6::command11() { + playSound(0x2202, 34); + + return 0; +} + +int ASound6::command12() { + playSound(0x2246, 8); + + return 0; +} + +int ASound6::command13() { + playSound(0x2298, 28); + + return 0; +} + +int ASound6::command14() { + playSound(0x22B4, 27); + + return 0; +} + +int ASound6::command15() { + playSound(0x219E, 12); + + return 0; +} + +int ASound6::command16() { + playSound(0x21AA, 22); + playSound(0x21C0, 12); + + return 0; +} + +int ASound6::command17() { + playSound(0x21CC, 54); + + return 0; +} + +int ASound6::command18() { + playSound(0x2270, 16); + + return 0; +} + +int ASound6::command19() { + playSound(0x2280, 16); + + return 0; +} + +int ASound6::command20() { + playSound(0x223C, 10); + + return 0; +} + +int ASound6::command21() { + playSound(0x224E, 34); + + return 0; +} + +int ASound6::command22() { + playSound(0x2290, 8); + + return 0; +} + +int ASound6::command23() { + playSound(0x215E, 34); + playSound(0x2180, 20); + + return 0; +} + +int ASound6::command24() { + byte *pData1 = loadData(0x1D54, 540); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x1F70, 52)); + _channels[2].load(loadData(0x1FA4, 430)); + } + + return 0; +} + +int ASound6::command25() { + playSound(0x2152, 12); + + return 0; +} + +int ASound6::command29() { + byte *pData1 = loadData(0x149A, 312); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x15D2, 304)); + _channels[2].load(loadData(0x1702, 222)); + _channels[3].load(loadData(0x17E0, 522)); + _channels[4].load(loadData(0x19EA, 874)); + } + + return 0; +} + +/*-----------------------------------------------------------------------*/ + +const ASound7::CommandPtr ASound7::_commandList[38] = { + &ASound7::command0, &ASound7::command1, &ASound7::command2, &ASound7::command3, + &ASound7::command4, &ASound7::command5, &ASound7::command6, &ASound7::command7, + &ASound7::command8, &ASound7::command9, &ASound7::nullCommand, &ASound7::nullCommand, + &ASound7::nullCommand, &ASound7::nullCommand, &ASound7::nullCommand, &ASound7::command15, + &ASound7::command16, &ASound7::command16, &ASound7::command18, &ASound7::command19, + &ASound7::command20, &ASound7::command21, &ASound7::command22, &ASound7::command23, + &ASound7::command24, &ASound7::command25, &ASound7::command26, &ASound7::command27, + &ASound7::command28, &ASound7::nullCommand, &ASound7::command30, &ASound7::nullCommand, + &ASound7::command32, &ASound7::command33, &ASound7::command34, &ASound7::command35, + &ASound7::command36, &ASound7::command37 +}; + +ASound7::ASound7(Audio::Mixer *mixer) : ASound(mixer, "asound.007", 0x1460) { + // Load sound samples + _soundFile.seek(_dataOffset + 0x122); + for (int i = 0; i < 214; ++i) + _samples.push_back(AdlibSample(_soundFile)); +} + +int ASound7::command(int commandId, int param) { + if (commandId > 37) + return 0; + + _frameCounter = 0; + return (this->*_commandList[commandId])(); +} + +int ASound7::command9() { + byte *pData1 = loadData(0x2992, 122); + if (!isSoundActive(pData1)) { + _channels[0].load(pData1); + _channels[1].load(loadData(0x2A0C, 76)); + _channels[2].load(loadData(0x2A58, 122)); + _channels[3].load(loadData(0x2AD2, 38)); + } + + return 0; +} + +int ASound7::command15() { + byte *pData = loadData(0x2B3E, 10); + pData[6] = (getRandomNumber() & 7) + 85; + + return 0; +} + +int ASound7::command16() { + playSound(0x2CE2, 8); + + return 0; +} + +int ASound7::command18() { + playSound(0x2C94, 22); + + return 0; +} + +int ASound7::command19() { + byte *pData1 = loadData(0x2C94, 22); + byte *pData2 = loadData(0x2CAA, 16); + if (_channels[8]._ptr1 == pData1 || _channels[8]._ptr1 == pData2) { + _channels[8]._soundData = loadData(0x2CBA, 12); + _channels[8]._field17 = 1; + _channels[8]._field19 = 1; + } + + return 0; +} + +int ASound7::command20() { + playSound(0x2CD0, 18); + + return 0; +} + +int ASound7::command21() { + playSound(0x2CC6, 10); + + return 0; +} + +int ASound7::command22() { + playSound(0x2C08, 140); + + return 0; +} + +int ASound7::command23() { + playSound(0x2B08, 34); + playSound(0x2B2A, 20); + + return 0; +} + +int ASound7::command24() { + byte *pData1 = loadData(0x14C6, 144); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x1556, 146)); + _channels[2].load(loadData(0x15E8, 138)); + _channels[3].load(loadData(0x1672, 122)); + _channels[4].load(loadData(0x16EC, 74)); + } + + return 0; +} + +int ASound7::command25() { + byte *pData1 = loadData(0x1DBE, 182); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x1E74, 182)); + _channels[2].load(loadData(0x1F2A, 186)); + _channels[3].load(loadData(0x1FE4, 244)); + } + + return 0; +} + +int ASound7::command26() { + byte *pData1 = loadData(0x20D8, 312); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x2210, 304)); + _channels[2].load(loadData(0x2340, 222)); + _channels[3].load(loadData(0x241E, 522)); + _channels[4].load(loadData(0x2628, 874)); + } + + return 0; +} + +int ASound7::command27() { + byte *pData1 = loadData(0x1736, 158); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x17D4, 288)); + _channels[2].load(loadData(0x18F4, 290)); + _channels[3].load(loadData(0x1A16, 396)); + _channels[4].load(loadData(0x1BA2, 380)); + _channels[5].load(loadData(0x1D1E, 160)); + } + + return 0; +} + +int ASound7::command28() { + playSound(0x2CAA, 16); + + return 0; +} + +int ASound7::command30() { + playSound(0x2B86, 22); + playSound(0x2B9C, 22); + playSound(0x2BB2, 22); + + return 0; +} + +int ASound7::command32() { + playSound(0x2BFE, 10); + + return 0; +} + +int ASound7::command33() { + playSound(0x2BEE, 16); + + return 0; +} + +int ASound7::command34() { + playSound(0x2BDE, 16); + + return 0; +} + +int ASound7::command35() { + playSound(0x2BC8, 22); + + return 0; +} + +int ASound7::command36() { + playSound(0x2AF8, 16); + + return 0; +} + +int ASound7::command37() { + playSound(0x2B48, 20); + playSound(0x2B5C, 32); + playSound(0x2B7C, 10); + + return 0; +} + +/*-----------------------------------------------------------------------*/ + +const ASound8::CommandPtr ASound8::_commandList[38] = { + &ASound8::command0, &ASound8::command1, &ASound8::command2, &ASound8::command3, + &ASound8::command4, &ASound8::command5, &ASound8::command6, &ASound8::command7, + &ASound8::command8, &ASound8::command9, &ASound8::command10, &ASound8::command11, + &ASound8::command12, &ASound8::command13, &ASound8::command14, &ASound8::command15, + &ASound8::command16, &ASound8::command16, &ASound8::command18, &ASound8::command19, + &ASound8::command20, &ASound8::command21, &ASound8::command22, &ASound8::command23, + &ASound8::command24, &ASound8::command25, &ASound8::command26, &ASound8::command27, + &ASound8::command28, &ASound8::command29, &ASound8::command30, &ASound8::command31, + &ASound8::command32, &ASound8::command33, &ASound8::command34, &ASound8::command35, + &ASound8::command36, &ASound8::command37 +}; + +ASound8::ASound8(Audio::Mixer *mixer) : ASound(mixer, "asound.008", 0x1490) { + // Load sound samples + _soundFile.seek(_dataOffset + 0x122); + for (int i = 0; i < 174; ++i) + _samples.push_back(AdlibSample(_soundFile)); +} + +int ASound8::command(int commandId, int param) { + if (commandId > 37) + return 0; + + _frameCounter = 0; + return (this->*_commandList[commandId])(); +} + +int ASound8::command9() { + byte *pData = loadData(0x15BE, 10); + pData[6] = (getRandomNumber() & 7) + 85; + playSoundData(pData); + + return 0; +} + +int ASound8::command10() { + byte *pData = loadData(0x2B3E, 10); + pData[6] = (getRandomNumber() & 7) + 85; + playSoundData(pData); + + return 0; +} + +int ASound8::command11() { + playSound(0x17CA, 12); + + return 0; +} + +int ASound8::command12() { + playSound(0x17D6, 12); + + return 0; +} + +int ASound8::command13() { + playSound(0x1694, 10); + + return 0; +} + +int ASound8::command14() { + playSound(0x169E, 24); + + return 0; +} + +int ASound8::command15() { + byte *pData = loadData(0x169E, 24); + if (_channels[8]._ptr1 == pData) { + _channels[8]._soundData = loadData(0x16B6, 12); + _channels[8]._field17 = 1; + _channels[8]._field19 = 1; + } + + return 0; +} + +int ASound8::command16() { + playSound(0x1686, 14); + + return 0; +} + +int ASound8::command17() { + playSound(0x17EC, 12); + + return 0; +} + +int ASound8::command18() { + playSound(0x17F8, 12); + + return 0; +} + +int ASound8::command19() { + playSound(0x16D8, 8); + + return 0; +} + +int ASound8::command20() { + playSound(0x16E0, 8); + + return 0; +} + +int ASound8::command21() { + playSound(0x17E2, 10); + + return 0; +} + +int ASound8::command22() { + playSound(0x178C, 14); + playSound(0x179A, 14); + playSound(0x17A8, 14); + + return 0; +} + +int ASound8::command23() { + playSound(0x2B08, 34); + playSound(0x2B2A, 20); + + return 0; +} + +int ASound8::command24() { + playSound(0x17B6, 8); + + return 0; +} + +int ASound8::command25() { + playSound(0x17BE, 12); + + return 0; +} + +int ASound8::command26() { + playSound(0x16C2, 22); + + return 0; +} + +int ASound8::command27() { + playSound(0x1588, 34); + playSound(0x15AA, 20); + + return 0; +} + +int ASound8::command28() { + byte *pData1 = loadData(0x114E, 376); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[2].load(loadData(0x12F8, 130)); + + byte *pData = loadData(0x12C6, 50); + method1(pData); + _channels[1].load(pData); + } + + return 0; +} + +void ASound8::method1(byte *pData) { + int v; + while ((v = (getRandomNumber() & 0x3F)) > 36) + ; + + adjustRange(pData, v + 20, -1); + adjustRange(pData + 1, 10 - ((v + 1) / 6), 1); +} + +void ASound8::adjustRange(byte *pData, byte v, int incr) { + pData += 8; + + for (int i = 0; i < 10; ++i, pData += 4, v += incr) { + *pData = v; + } +} + +int ASound8::command29() { + byte *pData1 = loadData(0x137A, 60); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x13B6, 318)); + _channels[2].load(loadData(0x14F4, 118)); + } + + return 0; +} + +int ASound8::command30() { + playSound(0x1644, 22); + playSound(0x165A, 22); + playSound(0x1670, 22); + + return 0; +} + +int ASound8::command31() { + playSound(0x156A, 14); + + return 0; +} + +int ASound8::command32() { + playSound(0x163A, 10); + + return 0; +} + +int ASound8::command33() { + playSound(0x162A, 16); + + return 0; +} + +int ASound8::command34() { + playSound(0x161A, 16); + + return 0; +} + +int ASound8::command35() { + playSound(0x1604, 22); + + return 0; +} + +int ASound8::command36() { + playSound(0x1578, 16); + + return 0; +} + +int ASound8::command37() { + playSound(0x15C8, 20); + playSound(0x15DC, 30); + playSound(0X15FA, 10); + + return 0; +} + +} // End of namespace Nebular + +} // End of namespace MADS diff --git a/engines/mads/nebular/sound_nebular.h b/engines/mads/nebular/sound_nebular.h new file mode 100644 index 0000000000..c485bd7955 --- /dev/null +++ b/engines/mads/nebular/sound_nebular.h @@ -0,0 +1,720 @@ +/* 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. + * + */ + +#ifndef MADS_SOUND_NEBULAR_H +#define MADS_SOUND_NEBULAR_H + +#include "common/scummsys.h" +#include "common/file.h" +#include "common/mutex.h" +#include "common/queue.h" +#include "audio/audiostream.h" +#include "audio/fmopl.h" +#include "audio/mixer.h" + +namespace MADS { + +class SoundManager; + +namespace Nebular { + +/** + * Represents the data for a channel on the Adlib + */ +class AdlibChannel { +public: + int _activeCount; + int _field1; + int _field2; + int _field3; + int _field4; + int _sampleIndex; + int _volume; + int _field7; + int _field8; + int _field9; + int _fieldA; + uint8 _fieldB; + int _fieldC; + int _fieldD; + int _fieldE; + byte *_ptr1; + byte *_pSrc; + byte *_ptr3; + byte *_ptr4; + int _field17; + int _field19; + byte *_soundData; + int _field1D; + int _field1E; + int _field1F; + + // TODO: Only used by asound.003. Figure out usage + byte _field20; +public: + static bool _channelsEnabled; +public: + AdlibChannel(); + + void reset(); + void enable(int flag); + void setPtr2(byte *pData); + void load(byte *pData); + void check(byte *nullPtr); +}; + +class AdlibChannelData { +public: + int _field0; + int _freqMask; + int _freqBase; + int _field6; +}; + +class AdlibSample { +public: + int _attackRate; + int _decayRate; + int _sustainLevel; + int _releaseRate; + bool _egTyp; + bool _ksr; + int _totalLevel; + int _scalingLevel; + int _waveformSelect; + int _freqMultiple; + int _feedback; + bool _ampMod; + int _vib; + int _alg; + int _fieldE; + int _freqMask; + int _freqBase; + int _field14; + + AdlibSample() {} + AdlibSample(Common::SeekableReadStream &s); +}; + +struct RegisterValue { + uint8 _regNum; + uint8 _value; + + RegisterValue(int regNum, int value) { + _regNum = regNum; _value = value; + } +}; + +#define ADLIB_CHANNEL_COUNT 9 +#define ADLIB_CHANNEL_MIDWAY 5 +#define CALLBACKS_PER_SECOND 60 + +/** + * Base class for the sound player resource files + */ +class ASound : public Audio::AudioStream { +private: + struct CachedDataEntry { + int _offset; + byte *_data; + }; + Common::List<CachedDataEntry> _dataCache; + uint16 _randomSeed; + + /** + * Does the initial Adlib initialisation + */ + void adlibInit(); + + /** + * Does on-going processing for the Adlib sounds being played + */ + void update(); + + /** + * Polls each of the channels for updates + */ + void pollChannels(); + + /** + * Checks the status of the channels + */ + void checkChannels(); + + /** + * Polls the currently active channel + */ + void pollActiveChannel(); + + /** + * Updates the octave of the currently active channel + */ + void updateOctave(); + + void updateChannelState(); + void updateActiveChannel(); + + /** + * Loads up the specified sample + */ + void loadSample(int sampleIndex); + + /** + * Writes out the data of the selected sample to the Adlib + */ + void processSample(); + + void updateFNumber(); +protected: + int _commandParam; + + /** + * Queue a byte for an Adlib register + */ + void write(int reg, int val); + + /** + * Queue a byte for an Adlib register, and store it in the _ports array + */ + int write2(int state, int reg, int val); + + /** + * Flush any pending Adlib register values to the OPL driver + */ + void flush(); + + /** + * Turn a channel on + */ + void channelOn(int reg, int volume); + + /** + * Turn a channel off + */ + void channelOff(int reg); + + /** + * Checks for whether a poll result needs to be set + */ + void resultCheck(); + + /** + * Loads a data block from the sound file, caching the result for any future + * calls for the same data + */ + byte *loadData(int offset, int size); + + /** + * Play the specified sound + * @param offset Offset of sound data within sound player data segment + * @param size Size of sound data block + */ + void playSound(int offset, int size); + + /** + * Play the specified raw sound data + * @param pData Pointer to data block containing sound data + * @param startingChannel Channel to start scan from + */ + void playSoundData(byte *pData, int startingChannel = ADLIB_CHANNEL_MIDWAY); + + /** + * Checks to see whether the given block of data is already loaded into a channel. + */ + bool isSoundActive(byte *pData); + + /** + * Sets the frequency for a given channel. + */ + void setFrequency(int channel, int freq); + + /** + * Returns a 16-bit random number + */ + int getRandomNumber(); + + virtual int command0(); + int command1(); + int command2(); + int command3(); + int command4(); + int command5(); + int command6(); + int command7(); + int command8(); + + int nullCommand() { return 0; } +public: + Audio::Mixer *_mixer; + FM_OPL *_opl; + Audio::SoundHandle _soundHandle; + AdlibChannel _channels[ADLIB_CHANNEL_COUNT]; + AdlibChannel *_activeChannelPtr; + AdlibChannelData _channelData[11]; + Common::Array<AdlibSample> _samples; + AdlibSample *_samplePtr; + Common::File _soundFile; + Common::Queue<RegisterValue> _queue; + Common::Mutex _driverMutex; + int _dataOffset; + int _frameCounter; + bool _isDisabled; + int _v1; + int _v2; + int _activeChannelNumber; + int _freqMask1; + int _freqMask2; + int _freqBase1; + int _freqBase2; + int _channelNum1, _channelNum2; + int _v7; + int _v8; + int _v9; + int _v10; + int _pollResult; + int _resultFlag; + byte _nullData[2]; + int _ports[256]; + bool _stateFlag; + int _activeChannelReg; + int _v11; + bool _amDep, _vibDep, _splitPoint; + int _samplesPerCallback; + int _samplesPerCallbackRemainder; + int _samplesTillCallback; + int _samplesTillCallbackRemainder; +public: + /** + * Constructor + * @param filename Specifies the adlib sound player file to use + * @param dataOffset Offset in the file of the data segment + */ + ASound(Audio::Mixer *mixer, const Common::String &filename, int dataOffset); + + /** + * Destructor + */ + virtual ~ASound(); + + /** + * Execute a player command. Most commands represent sounds to play, but some + * low number commands also provide control operations. + * @param commandId Player ommand to execute. + * @param param Optional parameter used by a few commands + */ + virtual int command(int commandId, int param) = 0; + + /** + * Stop all currently playing sounds + */ + int stop(); + + /** + * Main poll method to allow sounds to progress + */ + int poll(); + + /** + * General noise/note output + */ + void noise(); + + /** + * Return the current frame counter + */ + int getFrameCounter() { return _frameCounter; } + + // AudioStream interface + /** + * Main buffer read + */ + virtual int readBuffer(int16 *buffer, const int numSamples); + + /** + * Mono sound only + */ + virtual bool isStereo() const { return false; } + + /** + * Data is continuously pushed, so definitive end + */ + virtual bool endOfData() const { return false; } + + /** + * Return sample rate + */ + virtual int getRate() const { return 11025; } +}; + +class ASound1 : public ASound { +private: + typedef int (ASound1::*CommandPtr)(); + static const CommandPtr _commandList[42]; + bool _cmd23Toggle; + + int command9(); + int command10(); + int command11(); + int command12(); + int command13(); + int command14(); + int command15(); + int command16(); + int command17(); + int command18(); + int command19(); + int command20(); + int command21(); + int command22(); + int command23(); + int command24(); + int command25(); + int command26(); + int command27(); + int command28(); + int command29(); + int command30(); + int command31(); + int command32(); + int command33(); + int command34(); + int command35(); + int command36(); + int command37(); + int command38(); + int command39(); + int command40(); + int command41(); + + void command111213(); + int command2627293032(); +public: + ASound1(Audio::Mixer *mixer); + + virtual int command(int commandId, int param); +}; + +class ASound2 : public ASound { +private: + byte _command12Param; +private: + typedef int (ASound2::*CommandPtr)(); + static const CommandPtr _commandList[44]; + + virtual int command0(); + int command9(); + int command10(); + int command11(); + int command12(); + int command13(); + int command14(); + int command15(); + int command16(); + int command17(); + int command18(); + int command19(); + int command20(); + int command21(); + int command22(); + int command23(); + int command24(); + int command25(); + int command26(); + int command27(); + int command28(); + int command29(); + int command30(); + int command31(); + int command32(); + int command33(); + int command34(); + int command35(); + int command36(); + int command37(); + int command38(); + int command39(); + int command40(); + int command41(); + int command42(); + int command43(); + + void command9Randomize(); + void command9Apply(byte *data, int val, int incr); +public: + ASound2(Audio::Mixer *mixer); + + virtual int command(int commandId, int param); +}; + +class ASound3 : public ASound { +private: + bool _command39Flag; + + typedef int (ASound3::*CommandPtr)(); + static const CommandPtr _commandList[61]; + + int command9(); + int command10(); + int command11(); + int command13(); + int command14(); + int command15(); + int command16(); + int command17(); + int command18(); + int command19(); + int command20(); + int command21(); + int command22(); + int command23(); + int command24(); + int command25(); + int command26(); + int command27(); + int command28(); + int command29(); + int command30(); + int command31(); + int command32(); + int command33(); + int command34(); + int command35(); + int command36(); + int command37(); + int command38(); + int command39(); + int command40(); + int command41(); + int command42(); + int command43(); + int command44(); + int command45(); + int command46(); + int command47(); + int command49(); + int command50(); + int command51(); + int command57(); + int command59(); + int command60(); + + void command9Randomize(); + void command9Apply(byte *data, int val, int incr); +public: + ASound3(Audio::Mixer *mixer); + + virtual int command(int commandId, int param); +}; + +class ASound4 : public ASound { +private: + typedef int (ASound4::*CommandPtr)(); + static const CommandPtr _commandList[61]; + + int command10(); + int command12(); + int command19(); + int command20(); + int command21(); + int command24(); + int command27(); + int command30(); + int command32(); + int command33(); + int command34(); + int command35(); + int command36(); + int command37(); + int command38(); + int command43(); + int command52(); + int command53(); + int command54(); + int command55(); + int command56(); + int command57(); + int command58(); + int command59(); + int command60(); + + void method1(); +public: + ASound4(Audio::Mixer *mixer); + + virtual int command(int commandId, int param); +}; + +class ASound5 : public ASound { +private: + typedef int (ASound5::*CommandPtr)(); + static const CommandPtr _commandList[42]; + + int command9(); + int command10(); + int command11(); + int command12(); + int command13(); + int command14(); + int command15(); + int command16(); + int command17(); + int command18(); + int command19(); + int command20(); + int command21(); + int command22(); + int command23(); + int command24(); + int command25(); + int command26(); + int command27(); + int command28(); + int command29(); + int command30(); + int command31(); + int command32(); + int command33(); + int command34(); + int command35(); + int command36(); + int command37(); + int command38(); + int command39(); + int command40(); + int command41(); + int command42(); + int command43(); +public: + ASound5(Audio::Mixer *mixer); + + virtual int command(int commandId, int param); +}; + +class ASound6 : public ASound { +private: + typedef int (ASound6::*CommandPtr)(); + static const CommandPtr _commandList[30]; + + int command9(); + int command10(); + int command11(); + int command12(); + int command13(); + int command14(); + int command15(); + int command16(); + int command17(); + int command18(); + int command19(); + int command20(); + int command21(); + int command22(); + int command23(); + int command24(); + int command25(); + int command29(); +public: + ASound6(Audio::Mixer *mixer); + + virtual int command(int commandId, int param); +}; + +class ASound7 : public ASound { +private: + typedef int (ASound7::*CommandPtr)(); + static const CommandPtr _commandList[38]; + + int command9(); + int command15(); + int command16(); + int command18(); + int command19(); + int command20(); + int command21(); + int command22(); + int command23(); + int command24(); + int command25(); + int command26(); + int command27(); + int command28(); + int command30(); + int command32(); + int command33(); + int command34(); + int command35(); + int command36(); + int command37(); +public: + ASound7(Audio::Mixer *mixer); + + virtual int command(int commandId, int param); +}; + +class ASound8 : public ASound { +private: + typedef int (ASound8::*CommandPtr)(); + static const CommandPtr _commandList[38]; + + int command9(); + int command10(); + int command11(); + int command12(); + int command13(); + int command14(); + int command15(); + int command16(); + int command17(); + int command18(); + int command19(); + int command20(); + int command21(); + int command22(); + int command23(); + int command24(); + int command25(); + int command26(); + int command27(); + int command28(); + int command29(); + int command30(); + int command31(); + int command32(); + int command33(); + int command34(); + int command35(); + int command36(); + int command37(); + + void method1(byte *pData); + void adjustRange(byte *pData, byte v, int incr); +public: + ASound8(Audio::Mixer *mixer); + + virtual int command(int commandId, int param); +}; + +} // End of namespace Nebular + +} // End of namespace MADS + +#endif /* MADS_SOUND_NEBULAR_H */ diff --git a/engines/mads/palette.cpp b/engines/mads/palette.cpp new file mode 100644 index 0000000000..755f7bcf5c --- /dev/null +++ b/engines/mads/palette.cpp @@ -0,0 +1,830 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "engines/util.h" +#include "graphics/palette.h" +#include "mads/mads.h" +#include "mads/msurface.h" +#include "mads/staticres.h" + +namespace MADS { + +#define VGA_COLOR_TRANS(x) ((x) * 255 / 63) + +void RGB6::load(Common::SeekableReadStream *f) { + r = VGA_COLOR_TRANS(f->readByte()); + g = VGA_COLOR_TRANS(f->readByte()); + b = VGA_COLOR_TRANS(f->readByte()); + _palIndex = f->readByte(); + _u2 = f->readByte(); + _flags = f->readByte(); +} + +/*------------------------------------------------------------------------*/ + +PaletteUsage::PaletteUsage(MADSEngine *vm) { + _vm = vm; + _data = nullptr; +} + +void PaletteUsage::load(Common::Array<UsageEntry> *data) { + _data = data; +} + +void PaletteUsage::getKeyEntries(Common::Array<RGB6> &palette) { + _data->clear(); + + for (uint i = 0; i < palette.size(); ++i) { + byte *uPtr = &palette[i]._flags; + if ((*uPtr & 0x10) && _data->size() < 3) { + _data->push_back(UsageEntry(i)); + } + } +} + +static bool sortHelper(const PaletteUsage::UsageEntry &ue1, const PaletteUsage::UsageEntry &ue2) { + return ue1._sortValue < ue2._sortValue; +} + +void PaletteUsage::prioritize(Common::Array<RGB6> &palette) { + for (uint i = 0; i < _data->size(); ++i) { + RGB6 &palEntry = palette[(*_data)[i]._palIndex]; + (*_data)[i]._sortValue = _vm->_palette->rgbMerge(palEntry); + } + + Common::sort(_data->begin(), _data->end(), sortHelper); +} + +static bool rangeSorter(const PaletteUsage::UsageRange &ur1, const PaletteUsage::UsageRange &ur2) { + return ur1._v2 < ur2._v2; +} + +int PaletteUsage::process(Common::Array<RGB6> &palette, uint flags) { + int palLow; + int palHigh = (flags & 0x800) ? 0x100 : 0xFC; + int palIdx; + + PaletteUsage tempUsage(_vm); + Common::Array<UsageEntry> tempUsageData; + tempUsage.load(&tempUsageData); + + if (flags & 0x4000) { + palLow = 0; + palIdx = palHigh; + } else { + palLow = _vm->_palette->_lowRange; + if ((PALETTE_COUNT - _vm->_palette->_highRange) > palHigh) { + palIdx = palHigh; + } else { + palIdx = PALETTE_COUNT - _vm->_palette->_highRange; + } + } + + int rgbIndex = _vm->_palette->_rgbList.scan(); + uint32 rgbMask = 1 << rgbIndex; + bool noUsageFlag = flags & 0x8000; + bool hasUsage = _data != nullptr; + bool flag1 = false; + + if (hasUsage) { + if (noUsageFlag || _data->size() == 0) + hasUsage = false; + + if (noUsageFlag && _data->size() > 0) + flag1 = true; + } + + if (hasUsage) { + tempUsage.getKeyEntries(palette); + tempUsage.prioritize(palette); + } + + int freeIndex; + int palCount = getGamePalFreeIndex(&freeIndex); + Common::Array<UsageRange> palRange; + + for (uint palIndex = 0; palIndex < palette.size(); ++palIndex) { + byte pal2 = palIndex; + byte pal1 = 0; + + if (!(palette[palIndex]._flags & 0x80)) { + pal1 = 0x40; + } + if (palette[palIndex]._flags & 0x60) { + pal1 |= 0x20; + } + + palRange.push_back(UsageRange(pal1, pal2)); + } + + Common::sort(palRange.begin(), palRange.end(), rangeSorter); + + int var3A = (flags & 0x4000) ? 0xffff : 0xfffe; + + for (uint palIndex = 0; palIndex < palette.size(); ++palIndex) { + bool var48 = false; + int var4 = 0xffff; + int v1 = palRange[palIndex]._v2; + + if (palette[v1]._flags & 8) { + var48 = true; + var4 = 0xFD; + } + + if (hasUsage && palette[v1]._flags & 0x10) { + for (uint usageIndex = 0; usageIndex < tempUsage._data->size() && !var48; ++usageIndex) { + if ((*tempUsage._data)[usageIndex]._palIndex == palIndex) { + var48 = true; + int dataIndex = MIN(usageIndex, _data->size() - 1); + var4 = (*_data)[dataIndex]._palIndex; + } + } + } + + if (flag1 && palette[palIndex]._flags & 0x10) { + for (uint usageIndex = 0; usageIndex < _data->size() && !var48; ++usageIndex) { + if ((*_data)[usageIndex]._palIndex == palIndex) { + var48 = true; + var4 = 0xF0 + usageIndex; + + // Copy data into the high end of the main palette + RGB6 &pSrc = palette[palIndex]; + byte *pDest = &_vm->_palette->_mainPalette[var4 * 3]; + pDest[0] = pSrc.r; + pDest[1] = pSrc.g; + pDest[2] = pSrc.b; + } + } + } + + if (!var48 && !noUsageFlag) { + int var2 = (palette[palIndex]._flags & 0x20) || + (((flags & 0x2000) || (palette[palIndex]._flags & 0x4000)) && + ((flags & 0x1000) || (palCount == 0))) ? 0x7fff : 1; + int var36 = (palette[palIndex]._flags & 0x80) ? 0 : 2; + + for (int idx = palLow; idx < palIdx; ++idx) { + uint32 v = _vm->_palette->_palFlags[idx]; + if ((v & var3A) && !(v & var36)) { + int var10; + + if (var2 > 1) { + var10 = rgbFactor(&_vm->_palette->_mainPalette[idx * 3], palette[palIndex]); + } + else if (_vm->_palette->_mainPalette[idx * 3] != palette[palIndex].r || + _vm->_palette->_mainPalette[idx * 3 + 1] != palette[palIndex].g || + _vm->_palette->_mainPalette[idx * 3 + 2] != palette[palIndex].b) { + var10 = 1; + } else { + var10 = 0; + } + + if (var2 > var10) { + var48 = true; + var4 = idx; + var2 = var10; + } + } + } + } + + if (!var48 && (!(flags & 0x1000) || (!(palette[palIndex]._flags & 0x60) && !(flags & 0x2000)))) { + for (int idx = freeIndex; idx < palIdx && !var48; ++idx) { + if (!_vm->_palette->_palFlags[idx]) { + --palCount; + ++freeIndex; + var48 = true; + var4 = idx; + + RGB6 &pSrc = palette[palIndex]; + byte *pDest = &_vm->_palette->_mainPalette[idx * 3]; + pDest[0] = pSrc.r; + pDest[1] = pSrc.g; + pDest[2] = pSrc.b; + } + } + } + + assert(var48); + int var52 = (noUsageFlag && palette[palIndex]._u2) ? 2 : 0; + + _vm->_palette->_palFlags[var4] |= var52 | rgbMask; + palette[palIndex]._palIndex = var4; + } + + _vm->_palette->_rgbList[rgbIndex] = true; + + return rgbIndex; +} + +void PaletteUsage::transform(Common::Array<RGB6> &palette) { + if (!empty()) { + for (uint i = 0; i < _data->size(); ++i) { + int palIndex = (*_data)[i]._palIndex; + (*_data)[i]._palIndex = palette[palIndex]._palIndex; + } + } +} + +void PaletteUsage::updateUsage(Common::Array<int> &usageList, int sceneUsageIndex) { + uint32 mask1 = 0xFFFFFFFF; + uint32 mask2 = 0; + + for (uint idx = 0; idx < usageList.size(); ++idx) { + uint32 bitMask = 1 << usageList[idx]; + mask1 ^= bitMask; + mask2 |= bitMask; + _vm->_palette->_rgbList[usageList[idx]] = false; + } + + uint32 mask3 = 1 << sceneUsageIndex; + + for (uint idx = 0; idx < PALETTE_COUNT; ++idx) { + uint32 mask = mask2 & _vm->_palette->_palFlags[idx]; + if (mask) { + _vm->_palette->_palFlags[idx] = (_vm->_palette->_palFlags[idx] & + mask1) | mask3; + } + } + + _vm->_palette->_rgbList[sceneUsageIndex] = true; +} + +void PaletteUsage::resetPalFlags(int idx) { + if (idx >= 0 && idx < 32) { + uint32 rgbMask = ~(1 << idx); + + uint32 *flagP = _vm->_palette->_palFlags; + for (int i = 0; i < 256; ++i, ++flagP) { + *flagP &= rgbMask; + if (*flagP == 2) + *flagP = 0; + } + + _vm->_palette->_rgbList[idx] = 0; + } +} + +int PaletteUsage::getGamePalFreeIndex(int *palIndex) { + *palIndex = -1; + int count = 0; + + for (int i = 0; i < PALETTE_COUNT; ++i) { + if (!_vm->_palette->_palFlags[i]) { + ++count; + if (*palIndex < 0) + *palIndex = i; + } + } + + return count; +} + +int PaletteUsage::rgbFactor(byte *palEntry, RGB6 &pal6) { + int total = 0; + total += (palEntry[0] - pal6.r) * (palEntry[0] - pal6.r); + total += (palEntry[1] - pal6.g) * (palEntry[1] - pal6.g); + total += (palEntry[2] - pal6.b) * (palEntry[2] - pal6.b); + + return total; +} + +/*------------------------------------------------------------------------*/ + +void RGBList::clear() { + for (int i = 0; i < 32; i++) + _data[i] = false; +} + +void RGBList::reset() { + for (int i = 2; i < 32; i++) + _data[i] = false; +} + +int RGBList::scan() { + for (int i = 0; i < 32; ++i) { + if (!_data[i]) + return i; + } + + error("RGBList was full"); +} + +void RGBList::copy(RGBList &src) { + Common::copy(&src._data[0], &src._data[32], &_data[0]); +} + +/*------------------------------------------------------------------------*/ + +Fader::Fader(MADSEngine *vm) + : _vm(vm) { + _colorFlags[0] = _colorFlags[1] = _colorFlags[2] = true; + _colorFlags[3] = false; + _colorValues[0] = _colorValues[1] = 0; + _colorValues[2] = _colorValues[3] = 0; + + // TODO: It would be better if the fader routines could be refactored + // to work directly with 8-bit RGB values rather than 6-bit RGB values + Common::fill(&_rgb64Map[0], &_rgb64Map[PALETTE_COUNT], 0); + for (int i = 0; i < 64; ++i) + _rgb64Map[VGA_COLOR_TRANS(i)] = i; + byte v = 0; + for (int i = 0; i < PALETTE_COUNT; ++i) { + if (_rgb64Map[i]) + v = _rgb64Map[i]; + else + _rgb64Map[i] = v; + } +} + + +void Fader::setPalette(const byte *colors, uint start, uint num) { + g_system->getPaletteManager()->setPalette(colors, start, num); +} + +void Fader::grabPalette(byte *colors, uint start, uint num) { + g_system->getPaletteManager()->grabPalette(colors, start, num); +} + +void Fader::fadeOut(byte palette[PALETTE_SIZE], byte *paletteMap, + int baseColor, int numColors, int baseGrey, int numGreys, + int tickDelay, int steps) { + GreyEntry map[PALETTE_COUNT]; + int intensity; + byte palIndex[PALETTE_COUNT][3]; + int8 signs[PALETTE_COUNT][3]; + + mapToGreyRamp(palette, baseColor, numColors, baseGrey, numGreys, map); + + for (int palCtr = baseColor; palCtr < (baseColor + numColors); ++palCtr) { + int index = palCtr - baseColor; + for (int colorCtr = 0; colorCtr < 3; ++colorCtr) { + if (_colorFlags[colorCtr]) { + int shiftSign = _colorValues[colorCtr]; + if (shiftSign >= 0) { + intensity = map[index]._intensity << shiftSign; + } else { + intensity = map[index]._intensity >> ABS(shiftSign); + } + } else { + intensity = _colorValues[colorCtr]; + } + + int diff = intensity - _rgb64Map[palette[palCtr * 3 + colorCtr]]; + palIndex[palCtr][colorCtr] = (byte)ABS(diff); + signs[palCtr][colorCtr] = (diff == 0) ? 0 : (diff < 0 ? -1 : 1); + } + } + + for (int stepCtr = 0; stepCtr < steps; ++stepCtr) { + for (int palCtr = baseColor; palCtr < (baseColor + numColors); ++palCtr) { + int index = palCtr - baseColor; + for (int colorCtr = 0; colorCtr < 3; ++colorCtr) { + map[index]._accum[colorCtr] += palIndex[palCtr][colorCtr]; + while (map[index]._accum[colorCtr] >= steps) { + map[index]._accum[colorCtr] -= steps; + + byte rgb63 = _rgb64Map[palette[palCtr * 3 + colorCtr]] + + signs[palCtr][colorCtr]; + palette[palCtr * 3 + colorCtr] = VGA_COLOR_TRANS(rgb63); + } + } + } + + setFullPalette(palette); + + _vm->_events->waitForNextFrame(); + } + + if (paletteMap != nullptr) { + for (int palCtr = 0; palCtr < numColors; palCtr++) { + paletteMap[palCtr] = map[palCtr]._mapColor; + } + } +} + +void Fader::fadeIn(byte palette[PALETTE_SIZE], byte destPalette[PALETTE_SIZE], + int baseColor, int numColors, int baseGrey, int numGreys, + int tickDelay, int steps) { + GreyEntry map[PALETTE_COUNT]; + byte tempPal[PALETTE_SIZE];; + int8 signs[PALETTE_COUNT][3]; + byte palIndex[PALETTE_COUNT][3]; + int intensity; + + Common::copy(destPalette, destPalette + PALETTE_SIZE, tempPal); + + mapToGreyRamp(tempPal, baseColor, numColors, baseGrey, numGreys, map); + + for (int palCtr = baseColor; palCtr < (baseColor + numColors); ++palCtr) { + int index = palCtr - baseColor; + for (int colorCtr = 0; colorCtr < 3; ++colorCtr) { + if (_colorFlags[colorCtr]) { + int shiftSign = _colorValues[colorCtr]; + if (shiftSign >= 0) { + intensity = map[index]._intensity << shiftSign; + } + else { + intensity = map[index]._intensity >> abs(shiftSign); + } + } + else { + intensity = _colorValues[colorCtr]; + } + + int diff = _rgb64Map[destPalette[palCtr * 3 + colorCtr]] - intensity; + palIndex[palCtr][colorCtr] = (byte)ABS(diff); + signs[palCtr][colorCtr] = (diff == 0) ? 0 : (diff < 0 ? -1 : 1); + + map[index]._accum[colorCtr] = 0; + } + } + + for (int stepCtr = 0; stepCtr < steps; ++stepCtr) { + for (int palCtr = baseColor; palCtr < (baseColor + numColors); ++palCtr) { + int index = palCtr - baseColor; + for (int colorCtr = 0; colorCtr < 3; ++colorCtr) { + map[index]._accum[colorCtr] += palIndex[palCtr][colorCtr]; + while (map[index]._accum[colorCtr] >= steps) { + map[index]._accum[colorCtr] -= steps; + + byte rgb63 = _rgb64Map[palette[palCtr * 3 + colorCtr]] + + signs[palCtr][colorCtr]; + palette[palCtr * 3 + colorCtr] = VGA_COLOR_TRANS(rgb63); + } + } + } + + setFullPalette(palette); + + _vm->_events->waitForNextFrame(); + } +} + +void Fader::mapToGreyRamp(byte palette[PALETTE_SIZE], int baseColor, int numColors, + int baseGrey, int numGreys, GreyEntry *map) { + byte greyList[PALETTE_COUNT]; + byte greyMapping[PALETTE_COUNT]; + byte greyTable[64]; + byte greyIntensity[64]; + int intensity, shiftSign; + + getGreyValues(palette, greyList, baseColor, numColors); + greyPopularity(greyList, greyTable, numColors); + + for (int idx = 0; idx < numColors; ++idx) { + greyMapping[idx] = idx; + Common::fill(&map[idx]._accum[0], &map[idx]._accum[3], 0); + } + + for (int idx = 0; idx < PALETTE_COUNT; ++idx) { + map[idx]._mapColor = (byte)idx; + } + + // Sort the mapping lists + insertionSort(numColors, greyList, greyMapping); + + // Initialize state variables + int greySum = 0; + int greyScan = 0; + int greyMark = 0; + int greyColors = 0; + int greyAccum = 0; + int firstColor = 0; + + for (int greyCtr = 0; greyCtr < 64; ++greyCtr) { + for (int idx = 0; idx < greyTable[greyCtr]; ++idx) { + greySum += greyList[greyScan++]; + ++greyColors; + + greyAccum += numGreys; + while (greyAccum >= numColors) { + greyAccum -= numColors; + if (greyColors > 0) { + greyIntensity[greyMark] = (byte)(greySum / greyColors); + } + + for (int rescan = firstColor; rescan < greyScan; ++rescan) { + map[greyMapping[rescan]]._intensity = greyIntensity[greyMark]; + map[greyMapping[rescan]]._mapColor = (byte)(greyMark + baseGrey); + } + + firstColor = greyScan; + greySum = 0; + greyColors = 0; + ++greyMark; + } + } + } + + // Set the palette range of greyscale values to be used + byte *palP = &palette[baseGrey * 3]; + for (int greys = 0; greys < numGreys; ++greys) { + for (int color = 0; color < 3; ++color) { + if (_colorFlags[color]) { + shiftSign = (byte)_colorValues[color]; + if (shiftSign >= 0) { + intensity = greyIntensity[greys] << shiftSign; + } else { + intensity = greyIntensity[greys] >> abs(shiftSign); + } + } else { + intensity = _colorValues[color]; + } + *palP++ = VGA_COLOR_TRANS(intensity); + } + } +} + +void Fader::getGreyValues(const byte palette[PALETTE_SIZE], + byte greyList[PALETTE_COUNT], int baseColor, int numColors) { + const byte *palP = &palette[baseColor * 3]; + + for (int i = 0; i < numColors; ++i, palP += 3) { + int v = rgbMerge(palP[0], palP[1], palP[2]); + greyList[i] = v >> 7; + } +} + +void Fader::greyPopularity(const byte greyList[PALETTE_COUNT], + byte greyTable[64], int numColors) { + Common::fill(&greyTable[0], &greyTable[64], 0); + for (int i = 0; i < numColors; ++i) { + int idx = greyList[i]; + ++greyTable[idx]; + } +} + +void Fader::insertionSort(int size, byte *id, byte *value) { + bool restartFlag; + int endIndex = size - 1; + + do { + restartFlag = false; + if (endIndex <= 0) + break; + + for (int arrIndex = 0; arrIndex < endIndex && !restartFlag; ++arrIndex) { + byte *idP = id + arrIndex; + byte *valueP = value + arrIndex; + + // Check whether the next index is out of order with the one following it + if (*idP > *(idP + 1)) { + // Found an incorrect ordering + restartFlag = true; + + // Save id/value at current index + byte savedId = *idP; + byte savedValue = *valueP; + + int moveCount = size - arrIndex - 1; + if (moveCount > 0) { + Common::copy(idP + 1, idP + moveCount + 2, idP); + Common::copy(valueP + 1, valueP + moveCount + 2, valueP); + } + + // Scan for insert spot + int idx = 0; + if (endIndex > 0) { + bool breakFlag = false; + for (; idx <= endIndex && !breakFlag; ++idx) { + breakFlag = savedId < id[idx]; + } + } + + // Set up an insert point for entry + moveCount = size - idx - 1; + if (moveCount > 0) { + Common::copy_backward(id + idx, id + idx + moveCount, id + idx + moveCount + 1); + Common::copy_backward(value + idx, value + idx + moveCount, value + idx + moveCount + 1); + } + + // Set shifted values at the new position + id[idx] = savedId; + value[idx] = savedValue; + } + } + } while (restartFlag); +} + +int Fader::rgbMerge(RGB6 &palEntry) { + return rgbMerge(palEntry.r, palEntry.g, palEntry.b); +} + +int Fader::rgbMerge(byte r, byte g, byte b) { + return _rgb64Map[r] * 38 + _rgb64Map[g] * 76 + _rgb64Map[b] * 14; +} + +/*------------------------------------------------------------------------*/ + +Palette::Palette(MADSEngine *vm) : Fader(vm), _paletteUsage(vm) { + _lockFl = false; + _lowRange = 0; + _highRange = 0; + Common::fill(&_mainPalette[0], &_mainPalette[PALETTE_SIZE], 0); + Common::fill(&_palFlags[0], &_palFlags[PALETTE_COUNT], 0); +} + +void Palette::setEntry(byte palIndex, byte r, byte g, byte b) { + _mainPalette[palIndex * 3] = VGA_COLOR_TRANS(r); + _mainPalette[palIndex * 3 + 1] = VGA_COLOR_TRANS(g); + _mainPalette[palIndex * 3 + 2] = VGA_COLOR_TRANS(b); + + setPalette((const byte *)&_mainPalette[palIndex * 3], palIndex, 1); +} + +uint8 Palette::palIndexFromRgb(byte r, byte g, byte b, byte *paletteData) { + byte index = 0; + int32 minDist = 0x7fffffff; + byte palData[PALETTE_SIZE]; + + if (paletteData == NULL) { + g_system->getPaletteManager()->grabPalette(palData, 0, PALETTE_COUNT); + paletteData = &palData[0]; + } + + for (int palIndex = 0; palIndex < PALETTE_COUNT; ++palIndex) { + int Rdiff = r - paletteData[palIndex * 3]; + int Gdiff = g - paletteData[palIndex * 3 + 1]; + int Bdiff = b - paletteData[palIndex * 3 + 2]; + + if (Rdiff * Rdiff + Gdiff * Gdiff + Bdiff * Bdiff < minDist) { + minDist = Rdiff * Rdiff + Gdiff * Gdiff + Bdiff * Bdiff; + index = (uint8)palIndex; + } + } + + return (uint8)index; +} + +void Palette::setGradient(byte *palette, int start, int count, int rgbValue1, int rgbValue2) { + int rgbCurrent = rgbValue2; + int rgbDiff = -(rgbValue2 - rgbValue1); + + if (count > 0) { + byte *pDest = palette + start * 3; + int endVal = count - 1; + int numLeft = count; + + int rgbCtr = 0; + do { + pDest[0] = pDest[1] = pDest[2] = rgbCurrent; + + if (numLeft > 1) { + rgbCtr += rgbDiff; + if (rgbCtr >= endVal) { + do { + ++rgbCurrent; + rgbCtr += 1 - numLeft; + } while (rgbCtr >= endVal); + } + } + + pDest += 3; + } while (--numLeft > 0); + } +} + +void Palette::setSystemPalette() { + byte palData[4 * 3]; + palData[0 * 3] = palData[0 * 3 + 1] = palData[0 * 3 + 2] = 0; + palData[1 * 3] = palData[1 * 3 + 1] = palData[1 * 3 + 2] = 0x54; + palData[2 * 3] = palData[2 * 3 + 1] = palData[2 * 3 + 2] = 0xb4; + palData[3 * 3] = palData[3 * 3 + 1] = palData[3 * 3 + 2] = 0xff; + + setPalette(palData, 0, 4); +} + +void Palette::resetGamePalette(int lowRange, int highRange) { + Common::fill((byte *)&_palFlags[0], (byte *)&_palFlags[PALETTE_COUNT], 0); + initVGAPalette(_mainPalette); + + // Reserve the start of the palette for things like on-screen text + if (lowRange) { + Common::fill(&_palFlags[0], &_palFlags[lowRange], 1); + } + + // Reserve the high end of the palette for dialog display + if (highRange) { + Common::fill(&_palFlags[256 - highRange], &_palFlags[256], 1); + } + + _rgbList.clear(); + _rgbList[0] = _rgbList[1] = true; + + _lockFl = false; + _lowRange = lowRange; + _highRange = highRange; +} + +void Palette::initPalette() { + uint32 palMask = 1; + + if (_vm->_game->_player._spritesLoaded && _vm->_game->_player._numSprites) { + + for (int idx = 0; idx < _vm->_game->_player._numSprites; ++idx) { + SpriteAsset *asset = _vm->_game->_scene._sprites[ + _vm->_game->_player._spritesStart + idx]; + + uint32 mask = 1; + if (asset->_usageIndex) + mask <<= asset->_usageIndex; + + palMask = mask; + } + } + + for (int idx = 0; idx < PALETTE_COUNT; ++idx) + _palFlags[idx] = palMask; + + _lockFl = false; + _rgbList.reset(); +} + +void Palette::initVGAPalette(byte *palette) { + byte *destP = palette; + for (int palIndex = 0; palIndex < 16; ++palIndex) { + for (int byteCtr = 2; byteCtr >= 0; --byteCtr) + *destP++ = ((DEFAULT_VGA_LOW_PALETTE[palIndex] >> (8 * byteCtr)) & 0xff) >> 2; + } + + destP = &palette[0xF0 * 3]; + for (int palIndex = 0; palIndex < 16; ++palIndex) { + for (int byteCtr = 2; byteCtr >= 0; --byteCtr) + *destP++ = ((DEFAULT_VGA_HIGH_PALETTE[palIndex] >> (8 * byteCtr)) & 0xff) >> 2; + } +} + +void Palette::setLowRange() { + _mainPalette[0] = _mainPalette[1] = _mainPalette[2] = VGA_COLOR_TRANS(0); + _mainPalette[3] = _mainPalette[4] = _mainPalette[5] = VGA_COLOR_TRANS(0x15); + _mainPalette[6] = _mainPalette[7] = _mainPalette[8] = VGA_COLOR_TRANS(0x2A); + _mainPalette[9] = _mainPalette[10] = _mainPalette[11] = VGA_COLOR_TRANS(0x3F); + _vm->_palette->setPalette(_mainPalette, 0, 4); +} + +void Palette::setColorFlags(byte r, byte g, byte b) { + _colorFlags[0] = r; + _colorFlags[1] = g; + _colorFlags[2] = b; +} + +void Palette::setColorValues(byte r, byte g, byte b) { + _colorValues[0] = r; + _colorValues[1] = g; + _colorValues[2] = b; +} + +void Palette::lock() { + if (_rgbList[31] && !_lockFl) + error("Palette Lock - Unexpected values"); + + _lockFl = true; + _rgbList[31] = true; + + for (int i = 0; i < 256; i++) { + if (_palFlags[i]) + _palFlags[i] |= 0x80000000; + } +} + +void Palette::unlock() { + if (!_lockFl) + return; + + for (int i = 0; i < 256; i++) + _palFlags[i] &= 0x7FFFFFFF; + + _rgbList[31] = false; + _lockFl = false; +} + +void Palette::refreshSceneColors() { + int val = 18; + if (_vm->_game->_scene._cyclingActive) + val += _vm->_game->_scene._totalCycleColors; + + setPalette(_mainPalette + (val * 3), val, 256 - val); +} + +} // End of namespace MADS diff --git a/engines/mads/palette.h b/engines/mads/palette.h new file mode 100644 index 0000000000..ff93b2f2fe --- /dev/null +++ b/engines/mads/palette.h @@ -0,0 +1,330 @@ +/* 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. + * + */ + +#ifndef MADS_PALETTE_H +#define MADS_PALETTE_H + +#include "common/scummsys.h" +#include "common/stream.h" + +namespace MADS { + +class MADSEngine; + +#define PALETTE_USAGE_COUNT 4 + +#define PALETTE_RESERVED_LOW_COUNT 18 +#define PALETTE_RESERVED_HIGH_COUNT 10 + +#define PALETTE_COUNT 256 +#define PALETTE_SIZE (256 * 3) + +/** + * Palette mapping options + */ +enum { + PALFLAG_BACKGROUND = 0x8000, // Loading initial background + PALFLAG_RESERVED = 0x4000, // Enable mapping reserved colors + PALFLAG_ANY_TO_CLOSEST = 0x2000, // Any color can map to closest + PALFLAG_ALL_TO_CLOSEST = 0x1000, // Any colors that can map must map + PALFLAG_TOP_COLORS = 0x0800, // Allow mapping to high four colors + PALFLAG_DEFINE_RESERVED = 0x0400, // Define initial reserved color + PALFLAG_MASK = 0xfc00 // Mask for all the palette flags +}; + +struct PaletteCycle { + byte _colorCount; + byte _firstListColor; + byte _firstColorIndex; + byte _ticks; + + PaletteCycle() { _colorCount = _firstListColor = _firstColorIndex = _ticks = 0; } +}; + +struct RGB6 { + byte r; + byte g; + byte b; + byte _palIndex; + byte _u2; + byte _flags; + + /** + * Load an entry from a stream + */ + void load(Common::SeekableReadStream *f); +}; + +class PaletteUsage { +public: + struct UsageEntry { + uint16 _palIndex; + int _sortValue; + + UsageEntry(int palIndex) { _palIndex = palIndex; _sortValue = -1; } + UsageEntry() { _palIndex = 0; _sortValue = 0; } + }; + struct UsageRange { + byte _v1, _v2; + + UsageRange(byte v1, byte v2) { _v1 = v1; _v2 = v2; } + }; +private: + MADSEngine *_vm; + Common::Array<UsageEntry> *_data; + + int getGamePalFreeIndex(int *palIndex); + + int rgbFactor(byte *palEntry, RGB6 &pal6); + + Common::Array<UsageEntry> _nullUsage; +public: + /** + * Constructor + */ + PaletteUsage(MADSEngine *vm); + + void load(Common::Array<UsageEntry> *data); + + /** + * Returns whether the usage list is empty + */ + bool empty() const { return _data == nullptr; } + + uint16 &operator[](int index) { return (*_data)[index]._palIndex; } + + /** + * Assigns the class to an empty usage array + */ + void setEmpty() { _data = &_nullUsage; } + + /** + * Gets key entries from the passed palette + * @param palette 6-bit per entry read in palette + */ + void getKeyEntries(Common::Array<RGB6> &palette); + + /** + * Prioritizes the palette index list based on the intensity of the + * RGB values of the palette entries that they refer to + */ + void prioritize(Common::Array<RGB6> &palette); + + int process(Common::Array<RGB6> &palette, uint flags); + + void transform(Common::Array<RGB6> &palette); + + void updateUsage(Common::Array<int> &usageList, int sceneUsageIndex); + + void resetPalFlags(int idx); +}; + +class RGBList { +private: + bool _data[32]; +public: + RGBList() { clear(); } + + void clear(); + + void reset(); + + /** + * Copies the data from another instance + */ + void copy(RGBList &src); + + /** + * Scans for a free slot + */ + int scan(); + + bool &operator[](int idx) { return _data[idx]; } +}; + +class Fader { +public: + struct GreyEntry { + byte _intensity; + byte _mapColor; + uint16 _accum[3]; + }; +private: + void mapToGreyRamp(byte palette[PALETTE_SIZE], int baseColor, int numColors, + int baseGrey, int numGreys, GreyEntry *map); + + void getGreyValues(const byte palette[PALETTE_SIZE], byte greyList[PALETTE_COUNT], + int baseColor, int numColors); + + /** + * Given a grey value list containing grey shades (0-63), creates a 64 byte + * grey table containing the number of grey values for each intensity + */ + void greyPopularity(const byte greyList[PALETTE_COUNT], byte greyTable[64], int numColors); + + /** + * Does an insertion sort of a given id/value array pair + */ + void insertionSort(int size, byte *id, byte *value); +protected: + MADSEngine *_vm; + byte _rgb64Map[PALETTE_COUNT]; +public: + bool _colorFlags[4]; + int _colorValues[4]; +public: + /** + * Constructor + */ + Fader(MADSEngine *vm); + + /** + * Sets a new palette + */ + void setPalette(const byte *colors, uint start, uint num); + + /** + * Returns a subset of the currently loaded palette + */ + void grabPalette(byte *colors, uint start, uint num); + + /** + * Gets the entire palette at once + */ + void getFullPalette(byte palette[PALETTE_SIZE]) { + grabPalette(&palette[0], 0, PALETTE_COUNT); + } + + /** + * Sets the entire palette at once + */ + void setFullPalette(byte palette[PALETTE_SIZE]) { + setPalette(&palette[0], 0, PALETTE_COUNT); + } + + /** + * Calculates a merge/hash for a given palette entry + */ + int rgbMerge(byte r, byte g, byte b); + + /** + * Calculates a merge/hash for a given palette entry + */ + int rgbMerge(RGB6 &palEntry); + + /** + * Fades the given palette out to black or grey + */ + void fadeOut(byte palette[PALETTE_SIZE], byte *paletteMap, + int baseColor, int numColors, int baseGrey, int numGreys, + int tickDelay, int steps); + + /** + * Fade into the given palette + */ + void fadeIn(byte palette[PALETTE_SIZE], byte destPalette[PALETTE_SIZE], + int baseColor, int numColors, int baseGrey, int numGreys, + int tickDelay, int steps); +}; + +class Palette : public Fader { +private: + /** + * Initializes the first 16 palette indexes with the equivalent + * standard VGA palette + */ + void initVGAPalette(byte *palette); +public: + byte _mainPalette[PALETTE_SIZE]; + byte _cyclingPalette[PALETTE_SIZE]; + uint32 _palFlags[PALETTE_COUNT]; + PaletteUsage _paletteUsage; + RGBList _rgbList; + bool _lockFl; + int _lowRange; + int _highRange; +public: + /** + * Constructor + */ + Palette(MADSEngine *vm); + + /** + * Destructor + */ + virtual ~Palette() {} + + /** + * Set a palette entry + */ + void setEntry(byte palIndex, byte r, byte g, byte b); + + /** + * Returns the palette index in the palette that most closely matches the + * specified RGB pair + */ + uint8 palIndexFromRgb(byte r, byte g, byte b, byte *paletteData = nullptr); + + /** + * Sets a small set of system/core colors needed by the game + */ + void setSystemPalette(); + + /** + * Update a range of an arbitrary palette + */ + static void setGradient(byte *palette, int start, int count, int rgbValue1, int rgbValue2); + + /** + * Resets the game palette + */ + void resetGamePalette(int v1, int v2); + + /** + * Initializes the main palette + */ + void initPalette(); + + /** + * Set the first four palette entries with preset values + */ + void setLowRange(); + + /** + * Set up the palette as the game ends + */ + void close() { + warning("TODO: Palette::close"); + } + + void setColorFlags(byte r, byte g, byte b); + void setColorValues(byte r, byte g, byte b); + + void lock(); + void unlock(); + + void refreshSceneColors(); +}; + +} // End of namespace MADS + +#endif /* MADS_PALETTE_H */ diff --git a/engines/mads/phantom/game_phantom.cpp b/engines/mads/phantom/game_phantom.cpp new file mode 100644 index 0000000000..15ac241d8c --- /dev/null +++ b/engines/mads/phantom/game_phantom.cpp @@ -0,0 +1,161 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 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. + * + */ + +#include "common/scummsys.h" +#include "common/config-manager.h" +#include "mads/mads.h" +#include "mads/game.h" +#include "mads/screen.h" +#include "mads/msurface.h" +#include "mads/phantom/game_phantom.h" +//#include "mads/nebular/dialogs_nebular.h" +//#include "mads/nebular/globals_nebular.h" +#include "mads/phantom/phantom_scenes.h" + +namespace MADS { + +namespace Phantom { + +GamePhantom::GamePhantom(MADSEngine *vm) + : Game(vm) { + _surface = new MSurface(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT); + _storyMode = STORYMODE_NAUGHTY; +} + +ProtectionResult GamePhantom::checkCopyProtection() { + /* + // DEBUG: Flag copy protection failure + _globals[5] = -1; + + if (!ConfMan.getBool("copy_protection")) + return true; + + * DEBUG: Disabled for now + CopyProtectionDialog *dlg = new CopyProtectionDialog(_vm, false); + dlg->show(); + delete dlg; + */ + + // DEBUG: Return that copy protection failed + return PROTECTION_SUCCEED; +} + +void GamePhantom::initializeGlobals() { + //int count, count2; + //int bad; + + _globals.reset(); + //_globals[kTalkInanimateCount] = 8; + + /* Section #1 variables */ + // TODO + + /* Section #2 variables */ + // TODO + + /* Section #3 variables */ + // TODO + + /* Section #4 variables */ + // TODO + + /* Section #5 variables */ + // TODO + + /* Section #9 variables */ + // TODO + + _player._facing = FACING_NORTH; + _player._turnToFacing = FACING_NORTH; + + //Player::preloadSequences("RXM", 1); + //Player::preloadSequences("ROX", 1); +} + +void GamePhantom::setSectionHandler() { + delete _sectionHandler; + + switch (_sectionNumber) { + case 1: + _sectionHandler = new Section1Handler(_vm); + break; + case 2: + _sectionHandler = new Section2Handler(_vm); + break; + case 3: + _sectionHandler = new Section3Handler(_vm); + break; + case 4: + _sectionHandler = new Section4Handler(_vm); + break; + case 5: + _sectionHandler = new Section5Handler(_vm); + break; + default: + break; + } +} + +void GamePhantom::checkShowDialog() { + // TODO: Copied from Nebular + if (_vm->_dialogs->_pendingDialog && _player._stepEnabled && !_globals[5]) { + _player.releasePlayerSprites(); + _vm->_dialogs->showDialog(); + _vm->_dialogs->_pendingDialog = DIALOG_NONE; + } +} + +void GamePhantom::doObjectAction() { + // TODO: Copied from Nebular + //Scene &scene = _scene; + MADSAction &action = _scene._action; + //Dialogs &dialogs = *_vm->_dialogs; + //int id; + + action._inProgress = false; +} + +void GamePhantom::unhandledAction() { + // TODO +} + +void GamePhantom::step() { + if (_player._visible && _player._stepEnabled && !_player._moving && + (_player._facing == _player._turnToFacing)) { + + // TODO + } + +} + +void GamePhantom::synchronize(Common::Serializer &s, bool phase1) { + Game::synchronize(s, phase1); + + // TODO: Copied from Nebular + if (!phase1) { + _globals.synchronize(s); + } +} + +} // End of namespace Phantom + +} // End of namespace MADS diff --git a/engines/mads/phantom/game_phantom.h b/engines/mads/phantom/game_phantom.h new file mode 100644 index 0000000000..7a84ee1c72 --- /dev/null +++ b/engines/mads/phantom/game_phantom.h @@ -0,0 +1,124 @@ +/* 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. + * + */ + +#ifndef MADS_GAME_PHANTOM_H +#define MADS_GAME_PHANTOM_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/globals.h" +//#include "mads/nebular/globals_nebular.h" + +namespace MADS { + +namespace Phantom { + +// TODO: Adapt for Phantom's difficulty setting +enum StoryMode { STORYMODE_NAUGHTY = 1, STORYMODE_NICE = 2 }; + +enum InventoryObject { + OBJ_NONE = -1, + OBJ_KEY = 0, + OBJ_LANTERN = 1, + OBJ_RED_FRAME = 2, + OBJ_SANDBAG = 3, + OBJ_YELLOW_FRAME = 4, + OBJ_FIRE_AXE = 5, + OBJ_SMALL_NOTE = 6, + OBJ_ROPE = 7, + OBJ_SWORD = 8, + OBJ_ENVELOPE = 9, + OBJ_TICKET = 10, + OBJ_PIECE_OF_PAPER = 11, + OBJ_PARCHMENT = 12, + OBJ_LETTER = 13, + OBJ_NOTICE = 14, + OBJ_BOOK = 15, + OBJ_CRUMPLED_NOTE = 16, + OBJ_BLUE_FRAME = 17, + OBJ_LARGE_NOTE = 18, + OBJ_GREEN_FRAME = 19, + OBJ_MUSIC_SCORE = 20, + OBJ_WEDDING_RING = 21, + OBJ_CABLE_HOOK = 22, + OBJ_ROPE_WITH_HOOK = 23, + OBJ_OAR = 24 +}; + +// HACK: A stub for now, remove from here once it's implemented properly +class PhantomGlobals : public Globals { +public: + PhantomGlobals() { + resize(210); // Rex has 210 globals + } + virtual ~PhantomGlobals() {} +}; + +class GamePhantom : public Game { + friend class Game; +protected: + GamePhantom(MADSEngine *vm); + + virtual ProtectionResult checkCopyProtection(); + + virtual void initializeGlobals(); + + virtual void setSectionHandler(); + + virtual void checkShowDialog(); +public: + PhantomGlobals _globals; + StoryMode _storyMode; + + virtual Globals &globals() { return _globals; } + + virtual void doObjectAction(); + + virtual void unhandledAction(); + + virtual void step(); + + virtual void synchronize(Common::Serializer &s, bool phase1); +}; + + +class Section1Handler : public SectionHandler { +public: + Section1Handler(MADSEngine *vm) : SectionHandler(vm) {} + + // TODO: Properly implement handler methods + virtual void preLoadSection() {} + virtual void sectionPtr2() {} + virtual void postLoadSection() {} +}; + +// TODO: Properly implement handler classes +typedef Section1Handler Section2Handler; +typedef Section1Handler Section3Handler; +typedef Section1Handler Section4Handler; +typedef Section1Handler Section5Handler; + +} // End of namespace Nebular + +} // End of namespace MADS + +#endif /* MADS_GAME_PHANTOM_H */ diff --git a/engines/mads/phantom/phantom_scenes.cpp b/engines/mads/phantom/phantom_scenes.cpp new file mode 100644 index 0000000000..dbce014525 --- /dev/null +++ b/engines/mads/phantom/phantom_scenes.cpp @@ -0,0 +1,204 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "common/config-manager.h" +#include "mads/mads.h" +#include "mads/compression.h" +#include "mads/resources.h" +#include "mads/scene.h" +#include "mads/phantom/game_phantom.h" +#include "mads/phantom/phantom_scenes.h" + +namespace MADS { + +namespace Phantom { + +SceneLogic *SceneFactory::createScene(MADSEngine *vm) { + Scene &scene = vm->_game->_scene; + + // TODO + //scene.addActiveVocab(NOUN_DROP); + + switch (scene._nextSceneId) { + // Scene group #1 (theater, stage and dressing rooms) + case 101: // seats + return new DummyScene(vm); // TODO + case 102: // music stands + return new DummyScene(vm); // TODO + case 103: // below stage + return new DummyScene(vm); // TODO + case 104: // stage + return new DummyScene(vm); // TODO + case 105: // ground floor, storage room + return new DummyScene(vm); // TODO + case 106: // behind stage + return new DummyScene(vm); // TODO + case 107: // stage right wing + return new DummyScene(vm); // TODO + case 108: // stage left wing + return new DummyScene(vm); // TODO + case 109: // upper floor, staircase + return new DummyScene(vm); // TODO + case 110: // outside dressing rooms 1 + return new DummyScene(vm); // TODO + case 111: // outside dressing rooms 2 + return new DummyScene(vm); // TODO + case 112: // inside dressing room 1 + return new DummyScene(vm); // TODO + case 113: // inside dressing room 2 + return new DummyScene(vm); // TODO + case 114: // lower floor, storage room + return new DummyScene(vm); // TODO + case 150: // cutscene + return new DummyScene(vm); // TODO + + // Scene group #2 (theater entrance, offices, balcony) + case 201: // entrance / ticket office + return new DummyScene(vm); // TODO + case 202: // outside offices / paintings room + return new DummyScene(vm); // TODO + case 203: // office + return new DummyScene(vm); // TODO + case 204: // library + return new DummyScene(vm); // TODO + case 205: // upper floor, outside balcony boxes + return new DummyScene(vm); // TODO + case 206: // balcony box #1 + return new DummyScene(vm); // TODO + case 207: // balcony box #2 + return new DummyScene(vm); // TODO + case 208: // stage and balcony view + return new DummyScene(vm); // TODO + case 250: // cutscene + return new DummyScene(vm); // TODO + + // Scene group #3 (catwalks, chandelier, lake / catacombs entrance) + case 301: // catwalk #1 above stage + return new DummyScene(vm); // TODO + case 302: // catwalk #2 above stage + return new DummyScene(vm); // TODO + case 303: // above chandelier + return new DummyScene(vm); // TODO + case 304: // chandelier + return new DummyScene(vm); // TODO + case 305: // chandelier fight, phantom closeup + return new DummyScene(vm); // TODO + case 306: // chandelier #2 + return new DummyScene(vm); // TODO + case 307: // catwalk #3 above stage + return new DummyScene(vm); // TODO + case 308: // hidden staircase behind balcony box + return new DummyScene(vm); // TODO + case 309: // lake and archway + return new DummyScene(vm); // TODO + case 310: // lake + return new DummyScene(vm); // TODO + + // Scene group #4 (labyrinth) + case 401: // labyrinth room, 3 exits + return new DummyScene(vm); // TODO + case 403: // labyrinth room (big), 4 exits + 1 bricked door, left + return new DummyScene(vm); // TODO + case 404: // labyrinth room, 3 exits + return new DummyScene(vm); // TODO + case 406: // labyrinth room, 2 exits + return new DummyScene(vm); // TODO + case 407: // catacomb room / lake + return new DummyScene(vm); // TODO + case 408: // catacomb corridor + return new DummyScene(vm); // TODO + case 409: // catacomb room, door with switch panel + return new DummyScene(vm); // TODO + case 410: // skull switch panel + return new DummyScene(vm); // TODO + case 453: // Labyrinth room (big), 4 exits + 1 bricked door, right + return new DummyScene(vm); // TODO + case 456: // Labyrinth room, 2 exits + return new DummyScene(vm); // TODO + + // Scene group #5 (Phantom's hideout) + case 501: // catacombs, outside phantom's hideout, lake and boat + return new DummyScene(vm); // TODO + case 502: // push panel trap + return new DummyScene(vm); // TODO + case 504: // Phantom's hideout, church organ + return new DummyScene(vm); // TODO + case 505: // Phantom's hideout, sarcophagus + return new DummyScene(vm); // TODO + case 506: // catacomb room with ramp + return new DummyScene(vm); // TODO + + default: + error("Invalid scene %d called", scene._nextSceneId); + } +} + +/*------------------------------------------------------------------------*/ + +PhantomScene::PhantomScene(MADSEngine *vm) : SceneLogic(vm), + _globals(static_cast<GamePhantom *>(vm->_game)->_globals), + _game(*static_cast<GamePhantom *>(vm->_game)), + _action(vm->_game->_scene._action) { +} + +Common::String PhantomScene::formAnimName(char sepChar, int suffixNum) { + return Resources::formatName(_scene->_currentSceneId, sepChar, suffixNum, + EXT_NONE, ""); +} + +/*------------------------------------------------------------------------*/ + +void SceneInfoPhantom::loadCodes(MSurface &depthSurface, int variant) { + File f(Resources::formatName(RESPREFIX_RM, _sceneId, ".DAT")); + MadsPack codesPack(&f); + Common::SeekableReadStream *stream = codesPack.getItemStream(variant + 1); + + loadCodes(depthSurface, stream); + + delete stream; + f.close(); +} + +void SceneInfoPhantom::loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream) { + byte *destP = depthSurface.getData(); + byte *endP = depthSurface.getBasePtr(0, depthSurface.h); + + byte runLength = stream->readByte(); + while (destP < endP && runLength > 0) { + byte runValue = stream->readByte(); + + // Write out the run length + Common::fill(destP, destP + runLength, runValue); + destP += runLength; + + // Get the next run length + runLength = stream->readByte(); + } + + if (destP < endP) + Common::fill(destP, endP, 0); +} + +} // End of namespace Phantom + +} // End of namespace MADS diff --git a/engines/mads/phantom/phantom_scenes.h b/engines/mads/phantom/phantom_scenes.h new file mode 100644 index 0000000000..cd295a28b6 --- /dev/null +++ b/engines/mads/phantom/phantom_scenes.h @@ -0,0 +1,521 @@ +/* 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. + * + */ + +#ifndef MADS_PHANTOM_SCENES_H +#define MADS_PHANTOM_SCENES_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/scene.h" +#include "mads/phantom/game_phantom.h" +//#include "mads/phantom/globals_phantom.h" + + +namespace MADS { + +namespace Phantom { + +enum Noun { + NOUN_GAME = 0x1, + NOUN_QSAVE = 0x2, + NOUN_LOOK = 0x3, + NOUN_TAKE = 0x4, + NOUN_PUSH = 0x5, + NOUN_OPEN = 0x6, + NOUN_PUT = 0x7, + NOUN_TALK_TO = 0x8, + NOUN_GIVE = 0x9, + NOUN_PULL = 0xA, + NOUN_CLOSE = 0xB, + NOUN_THROW = 0xC, + NOUN_WALK_TO = 0xD, + NOUN_ = 0xE, + NOUN_IN_ONE = 0xF, + NOUN_IN_TWO = 0x10, + NOUN_ACT_CURTAIN = 0x11, + NOUN_AISLE = 0x12, + NOUN_APRON = 0x13, + NOUN_ATTACK = 0x14, + NOUN_BACKSTAGE = 0x15, + NOUN_BEAR_PROP = 0x16, + NOUN_BLUE_FRAME = 0x17, + NOUN_BOOK = 0x18, + NOUN_BUST = 0x19, + NOUN_CABLE = 0x1A, + NOUN_CARPET = 0x1B, + NOUN_CARTON = 0x1C, + NOUN_CARTONS = 0x1D, + NOUN_CEILING = 0x1E, + NOUN_CHAIR = 0x1F, + NOUN_CIRCULAR_STAIRCASE = 0x20, + NOUN_CLIMB_DOWN = 0x21, + NOUN_CLIMB_INTO = 0x22, + NOUN_CLIMB_THROUGH = 0x23, + NOUN_COLUMN_PROP = 0x24, + NOUN_CONDUCTORS_STAND = 0x25, + NOUN_CORRIDOR = 0x26, + NOUN_COUCH = 0x27, + NOUN_COUNTERWEIGHT_SYSTEM = 0x28, + NOUN_CRATE = 0x29, + NOUN_CRATES = 0x2A, + NOUN_CRUMPLED_NOTE = 0x2B, + NOUN_CYCLORAMA = 0x2C, + NOUN_CYLINDER = 0x2D, + NOUN_DOOR = 0x2E, + NOUN_DRESSING_ROOM_DOOR = 0x2F, + NOUN_DRESSING_SCREEN = 0x30, + NOUN_DRESSING_TABLE = 0x31, + NOUN_ELEPHANT_PROP = 0x32, + NOUN_ENVELOPE = 0x33, + NOUN_EXIT = 0x34, + NOUN_EXIT_DOWN = 0x35, + NOUN_EXIT_SIGN = 0x36, + NOUN_EXIT_TO = 0x37, + NOUN_EXIT_TO_BACKSTAGE = 0x38, + NOUN_EXIT_TO_CELLAR = 0x39, + NOUN_EXIT_TO_CORRIDOR = 0x3A, + NOUN_EXIT_TO_DRESSING_RMS = 0x3B, + NOUN_EXIT_TO_LEFT_WING = 0x3C, + NOUN_EXIT_TO_PIT = 0x3D, + NOUN_EXIT_TO_RIGHT_WING = 0x3E, + NOUN_EXIT_TO_STAGE = 0x3F, + NOUN_EXIT_TO_STAIRWELL = 0x40, + NOUN_EXIT_TO_TRAP_ROOM = 0x41, + NOUN_EXIT_UP = 0x42, + NOUN_EXPOSED_BRICK = 0x43, + NOUN_FAN = 0x44, + NOUN_FIRE_AXE = 0x45, + NOUN_FL = 0x46, + NOUN_FLAT = 0x47, + NOUN_FLATS = 0x48, + NOUN_FLOOR = 0x49, + NOUN_FOLDING_CHAIRS = 0x4A, + NOUN_GARBAGE_CAN = 0x4B, + NOUN_GRAFFITI = 0x4C, + NOUN_GREEN_FRAME = 0x4D, + NOUN_HEMP = 0x4E, + NOUN_HOLE = 0x4F, + NOUN_HOUSE = 0x50, + NOUN_IN_ONE2 = 0x51, + NOUN_IN_TWO2 = 0x52, + NOUN_JUMP_INTO = 0x53, + NOUN_JUNK = 0x54, + NOUN_KEY = 0x55, + NOUN_LAMP = 0x56, + NOUN_LANTERN = 0x57, + NOUN_LARGE_NOTE = 0x58, + NOUN_LASSO = 0x59, + NOUN_LEG = 0x5A, + NOUN_LETTER = 0x5B, + NOUN_LIGHT_FIXTURE = 0x5C, + NOUN_LOCK = 0x5D, + NOUN_LOCKING_RAIL = 0x5E, + NOUN_LOCKRAIL = 0x5F, + NOUN_LOOK_AT = 0x60, + NOUN_LOOK_THROUGH = 0x61, + NOUN_MANNEQUINS = 0x62, + NOUN_MIRROR = 0x63, + NOUN_MUMMY_PROP = 0x64, + NOUN_MURAL = 0x65, + NOUN_MUSIC_SCORE = 0x66, + NOUN_MUSIC_STAND = 0x67, + NOUN_MUSIC_STANDS = 0x68, + NOUN_NOTHING = 0x69, + NOUN_NOTICE = 0x6A, + NOUN_ORCHESTRA_DOOR = 0x6B, + NOUN_ORCHESTRA_PIT = 0x6C, + NOUN_PAINTING = 0x6D, + NOUN_PARCHMENT = 0x6E, + NOUN_PIECE_OF_PAPER = 0x6F, + NOUN_PIPE = 0x70, + NOUN_PIT = 0x71, + NOUN_PLANT = 0x72, + NOUN_POSTER = 0x73, + NOUN_PROMPTERS_BOX = 0x74, + NOUN_PROP_TABLE = 0x75, + NOUN_PROPS = 0x76, + NOUN_PROSCENIUM_ARCH = 0x77, + NOUN_PURCHASE_LINES = 0x78, + NOUN_RAILING = 0x79, + NOUN_READ = 0x7A, + NOUN_RED_FRAME = 0x7B, + NOUN_REMOVE = 0x7C, + NOUN_ROPE = 0x7D, + NOUN_RUG = 0x7E, + NOUN_SANDBAG = 0x7F, + NOUN_SCAFFOLDING = 0x80, + NOUN_SEATS = 0x81, + NOUN_SIDE_WALL = 0x82, + NOUN_SMALL_NOTE = 0x83, + NOUN_STAGE = 0x84, + NOUN_STAGE_EXIT = 0x85, + NOUN_STAGE_LEFT = 0x86, + NOUN_STAGE_RIGHT = 0x87, + NOUN_STAGEMANAGERS_POST = 0x88, + NOUN_STAIR_UNIT = 0x89, + NOUN_STAIRCASE = 0x8A, + NOUN_STAIRWELL = 0x8B, + NOUN_STOOL = 0x8C, + NOUN_STRIKE = 0x8D, + NOUN_SWORD = 0x8E, + NOUN_TABLE = 0x8F, + NOUN_THE_HOUSE = 0x90, + NOUN_THUNDER_MACHINE = 0x91, + NOUN_TICKET = 0x92, + NOUN_TRAP_CEILING = 0x93, + NOUN_TRAP_DOOR = 0x94, + NOUN_TURN_OFF = 0x95, + NOUN_TURN_ON = 0x96, + NOUN_UNLOCK = 0x97, + NOUN_URN = 0x98, + NOUN_WALK_ACROSS = 0x99, + NOUN_WALK_DOWN = 0x9A, + NOUN_WALK_THROUGH = 0x9B, + NOUN_WALK_UP = 0x9C, + NOUN_WALL = 0x9D, + NOUN_WARDROBE = 0x9E, + NOUN_WASTE_BASKET = 0x9F, + NOUN_WATER_PIPE = 0xA0, + NOUN_WEAR = 0xA1, + NOUN_WEDDING_RING = 0xA2, + NOUN_YELLOW_FRAME = 0xA3, + NOUN_PROP = 0xA4, + NOUN_CLIMB_UP = 0xA5, + NOUN_WALK_ONTO = 0xA6, + NOUN_WALK = 0xA7, + NOUN_LEFT_DOOR = 0xA8, + NOUN_RIGHT_DOOR = 0xA9, + NOUN_DOOR_TO_PIT = 0xAA, + NOUN_HEADPHONES = 0xAB, + NOUN_BOXES = 0xAC, + NOUN_MUG = 0xAD, + NOUN_DINETTE_SET = 0xAE, + NOUN_BOX = 0xAF, + NOUN_CASES = 0xB0, + NOUN_TRASH_BUCKET = 0xB1, + NOUN_CORK_BOARD = 0xB2, + NOUN_HEADSET = 0xB3, + NOUN_GRAND_FOYER = 0xB4, + NOUN_BACK_WALL = 0xB5, + NOUN_BALLET_BAR = 0xB6, + NOUN_THROW_RUGS = 0xB7, + NOUN_COSTUME_RACK = 0xB8, + NOUN_COAT_RACK = 0xB9, + NOUN_PAINTINGS = 0xBA, + NOUN_UMBRELLA = 0xBB, + NOUN_SHELF = 0xBC, + NOUN_CONTAINER = 0xBD, + NOUN_TORN_POSTER = 0xBE, + NOUN_REVIEW = 0xBF, + NOUN_REVIEWS = 0xC0, + NOUN_STAGE_RIGHT_WING = 0xC1, + NOUN_STAGE_LEFT_WING = 0xC2, + NOUN_PEDESTAL = 0xC3, + NOUN_PLANT_PROP = 0xC4, + NOUN_STATUE = 0xC5, + NOUN_BATTEN = 0xC6, + NOUN_BIG_PROP = 0xC7, + NOUN_VENTILATION_DUCT = 0xC8, + NOUN_CHANDELIER = 0xC9, + NOUN_BARRIER = 0xCA, + NOUN_PLACARD = 0xCB, + NOUN_TICKET_WINDOW = 0xCC, + NOUN_ARCHWAY = 0xCD, + NOUN_COLUMN = 0xCE, + NOUN_RAIL = 0xCF, + NOUN_SEAT = 0xD0, + NOUN_LOGE_CORRIDOR = 0xD1, + NOUN_HOUSE_LIGHT = 0xD2, + NOUN_FLOV = 0xD3, + NOUN_LEFT_COLUMN = 0xD4, + NOUN_RIGHT_COLUMN = 0xD5, + NOUN_BOOKCASE = 0xD6, + NOUN_DOORWAY = 0xD7, + NOUN_COMFY_CHAIR = 0xD8, + NOUN_DESK = 0xD9, + NOUN_MANAGERS_CHAIR = 0xDA, + NOUN_DESK_LAMP = 0xDB, + NOUN_WINDOW = 0xDC, + NOUN_SHEERS = 0xDD, + NOUN_TAPESTRY = 0xDE, + NOUN_OVERDOOR_MEDALLION = 0xDF, + NOUN_LATTICEWORK = 0xE0, + NOUN_DECORATIVE_MOLDING = 0xE1, + NOUN_LEFT_DOORWAY = 0xE2, + NOUN_LEFT_ARCHWAY = 0xE3, + NOUN_RIGHT_DOORWAY = 0xE4, + NOUN_RIGHT_ARCHWAY = 0xE5, + NOUN_SOFA = 0xE6, + NOUN_END_TABLE = 0xE7, + NOUN_COFFEE_TABLE = 0xE8, + NOUN_DECORATIVE_VASE = 0xE9, + NOUN_MARBLE_COLUMN = 0xEA, + NOUN_BOX_FIVE = 0xEB, + NOUN_ENTER = 0xEC, + NOUN_BOX_SIX = 0xED, + NOUN_BOX_SEVEN = 0xEE, + NOUN_BOX_EIGHT = 0xEF, + NOUN_BOX_NINE = 0xF0, + NOUN_STEP = 0xF1, + NOUN_PANEL = 0xF2, + NOUN_WALK_BEHIND = 0xF3, + NOUN_MIDDLE_DOORWAY = 0xF4, + NOUN_LIGHT = 0xF5, + NOUN_CANDLE = 0xF6, + NOUN_CASE = 0xF7, + NOUN_HANDLE = 0xF8, + NOUN_AXE = 0xF9, + NOUN_DOOR_CHUNKS = 0xFA, + NOUN_FLO = 0xFB, + NOUN_BULLETIN_BOARD = 0xFC, + NOUN_JULIE = 0xFD, + NOUN_GLASS_CASE = 0xFE, + NOUN_KEYHOLE = 0xFF, + NOUN_MIDDLE_DOOR = 0x100, + NOUN_DRESSING_GOWN = 0x101, + NOUN_MONSIEUR_BRIE = 0x102, + NOUN_CATWALK = 0x103, + NOUN_GRID = 0x104, + NOUN_GIRDER = 0x105, + NOUN_GRIDWORK = 0x106, + NOUN_DUCTWORK = 0x107, + NOUN_OPENING = 0x108, + NOUN_DOME = 0x109, + NOUN_ALCOVE = 0x10A, + NOUN_CHRISTINE_DAAE = 0x10B, + NOUN_CHRISTINE = 0x10C, + NOUN_WOMAN = 0x10D, + NOUN_PROMPTERS_STAND = 0x10E, + NOUN_SUPPORT = 0x10F, + NOUN_OTHER_CATWALK = 0x110, + NOUN_SLOT = 0x111, + NOUN_BEAM_POSITION = 0x112, + NOUN_LIGHTING_INSTRUMENT = 0x113, + NOUN_TARP = 0x114, + NOUN_FACE = 0x115, + NOUN_CATWALK_OVER_HOUSE = 0x116, + NOUN_STAIRCASE_POST = 0x117, + NOUN_JACQUES = 0x118, + NOUN_GENTLEMAN = 0x119, + NOUN_BODY = 0x11A, + NOUN_HOLLOW_COLUMN = 0x11B, + NOUN_UPPER_LEVEL = 0x11C, + NOUN_MIDDLE_LEVEL = 0x11D, + NOUN_LOWER_LEVEL = 0x11E, + NOUN_LADDER = 0x11F, + NOUN_CLIMB = 0x120, + NOUN_CHANDELIER_TRAP = 0x121, + NOUN_PIECE_OF_WOOD = 0x122, + NOUN_CUT_HEMP = 0x123, + NOUN_STONE_WALL = 0x124, + NOUN_LAKE = 0x125, + NOUN_STONE_COLUMN = 0x126, + NOUN_EXIT_THROUGH = 0x127, + NOUN_STONE_FLOOR = 0x128, + NOUN_STONE_ARCHWAY = 0x129, + NOUN_CHARLES = 0x12A, + NOUN_SWITCH = 0x12B, + NOUN_PROMPTERS_SEAT = 0x12C, + NOUN_LEVER = 0x12D, + NOUN_MONSIEUR_RICHARD = 0x12E, + NOUN_JULIE2 = 0x12F, + NOUN_CABLE_HOOK = 0x130, + NOUN_ATTACH = 0x131, + NOUN_ROPE_WITH_HOOK = 0x132, + NOUN_GRAPPLE = 0x133, + NOUN_OAR = 0x134, + NOUN_ORGAN = 0x135, + NOUN_SIT_AT = 0x136, + NOUN_ORGAN_BENCH = 0x137, + NOUN_SIT_ON = 0x138, + NOUN_LARGE_CHAIR = 0x139, + NOUN_SIT_IN = 0x13A, + NOUN_SARCOPHAGUS = 0x13B, + NOUN_SKULL = 0x13C, + NOUN_SKULLS = 0x13D, + NOUN_TOTEM = 0x13E, + NOUN_POLE = 0x13F, + NOUN_CURTAIN = 0x140, + NOUN_TORCH = 0x141, + NOUN_RAMP = 0x142, + NOUN_MADAME_GIRY = 0x143, + NOUN_PANELS = 0x144, + NOUN_MORE_CATACOMBS = 0x145, + NOUN_BLOCKED_ARCHWAY = 0x146, + NOUN_GRATE = 0x147, + NOUN_CATACOMBS = 0x148, + NOUN_TICKET_SELLER = 0x149, + NOUN_USHER = 0x14A, + NOUN_UNLUCKY_ADVENTURER = 0x14B, + NOUN_SWITCH_PANEL = 0x14C, + NOUN_SKULL_SWITCH = 0x14D, + NOUN_TOGGLE = 0x14E, + NOUN_CATACOMB_ROOM = 0x14F, + NOUN_BOX_TEN = 0x150, + NOUN_FOYER = 0x151, + NOUN_WALK_DOWN_STAIRCASE = 0x152, + NOUN_WALK_DOWN_STAIRS_TO = 0x153, + NOUN_HAT_RACK = 0x154, + NOUN_VASE = 0x155, + NOUN_CLOTHES_DUMMY = 0x156, + NOUN_NOTICES = 0x157, + NOUN_ARCHWAY_TO_NORTH = 0x158, + NOUN_ARCHWAY_TO_WEST = 0x159, + NOUN_ARCHWAY_TO_EAST = 0x15A, + NOUN_GATE = 0x15B, + NOUN_NEST = 0x15C, + NOUN_POT = 0x15D, + NOUN_PUDDLE = 0x15E, + NOUN_WEB = 0x15F, + NOUN_PLANK = 0x160, + NOUN_BLOCK = 0x161, + NOUN_RATS_NEST = 0x162, + NOUN_BROKEN_POT = 0x163, + NOUN_STONE = 0x164, + NOUN_DRAIN = 0x165, + NOUN_FATE = 0x166, + NOUN_SKULL_SWITCH_1 = 0x167, + NOUN_SKULL_SWITCH_2 = 0x168, + NOUN_SKULL_SWITCH_3 = 0x169, + NOUN_SKULL_SWITCH_4 = 0x16A, + NOUN_SKULL_SWITCH_5 = 0x16B, + NOUN_SKULL_SWITCH_6 = 0x16C, + NOUN_SKULL_SWITCH_7 = 0x16D, + NOUN_SKULL_SWITCH_8 = 0x16E, + NOUN_SKULL_SWITCH_9 = 0x16F, + NOUN_SKULL_SWITCH_10 = 0x170, + NOUN_SKULL_SWITCH_11 = 0x171, + NOUN_SKULL_SWITCH_12 = 0x172, + NOUN_SKULL_SWITCH_13 = 0x173, + NOUN_SKULL_SWITCH_14 = 0x174, + NOUN_SKULL_SWITCH_15 = 0x175, + NOUN_SKULL_SWITCH_16 = 0x176, + NOUN_SKULL_SWITCH_17 = 0x177, + NOUN_SKULL_SWITCH_18 = 0x178, + NOUN_SKULL_SWITCH_19 = 0x179, + NOUN_SKULL_SWITCH_20 = 0x17A, + NOUN_SKULL_SWITCH_21 = 0x17B, + NOUN_SKULL_SWITCH_22 = 0x17C, + NOUN_SKULL_SWITCH_23 = 0x17D, + NOUN_SKULL_SWITCH_24 = 0x17E, + NOUN_SKULL_SWITCH_25 = 0x17F, + NOUN_SKULL_SWITCH_26 = 0x180, + NOUN_EDGAR_DEGAS = 0x181, + NOUN_CHANDELIER_CABLE = 0x182, + NOUN_COB_WEB = 0x183, + NOUN_SKULL_FACE = 0x184, + NOUN_BOAT = 0x185, + NOUN_HOOK = 0x186, + NOUN_AROUND = 0x187, + NOUN_CANE = 0x188, + NOUN_MASK = 0x189, + NOUN_COVER = 0x18A, + NOUN_PADLOCK = 0x18B, + NOUN_LID = 0x18C, + NOUN_COBWEB = 0x18D, + NOUN_PHANTOM = 0x18E, + NOUN_PAPER = 0x18F +}; + +class SceneFactory { +public: + static SceneLogic *createScene(MADSEngine *vm); +}; + +/** + * Specialized base class for Dragonsphere game scenes + */ +class PhantomScene : public SceneLogic { +protected: + PhantomGlobals &_globals; + GamePhantom &_game; + MADSAction &_action; + + /** + * Forms an animation resource name + */ + Common::String formAnimName(char sepChar, int suffixNum); + + /** + * Plays appropriate sound for entering varous rooms + */ + void lowRoomsEntrySound(); +public: + /** + * Constructor + */ + PhantomScene(MADSEngine *vm); + + void sub7178C(); +}; + +class SceneInfoPhantom : public SceneInfo { + friend class SceneInfo; +protected: + virtual void loadCodes(MSurface &depthSurface, int variant); + + virtual void loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream); + + /** + * Constructor + */ + SceneInfoPhantom(MADSEngine *vm) : SceneInfo(vm) {} +}; + +// TODO: Temporary, remove once implemented properly +class Scene1xx : public PhantomScene { +protected: + /** + * Plays an appropriate sound when entering a scene + */ + void sceneEntrySound() {} + + /** + *Sets the AA file to use for the scene + */ + void setAAName() {} + + /** + * Updates the prefix used for getting player sprites for the scene + */ + void setPlayerSpritesPrefix() {} +public: + Scene1xx(MADSEngine *vm) : PhantomScene(vm) {} +}; + +// TODO: Temporary, remove once implemented properly +class DummyScene : public PhantomScene { +public: + DummyScene(MADSEngine *vm) : PhantomScene(vm) { + warning("Unimplemented scene"); + } + + virtual void setup() {} + virtual void enter() {} + virtual void actions() {} +}; + +} // End of namespace Phantom + +} // End of namespace MADS + +#endif /* MADS_PHANTOM_SCENES_H */ diff --git a/engines/mads/player.cpp b/engines/mads/player.cpp new file mode 100644 index 0000000000..ed585cf636 --- /dev/null +++ b/engines/mads/player.cpp @@ -0,0 +1,794 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "mads/mads.h" +#include "mads/player.h" + +namespace MADS { + +#define PLAYER_SEQ_INDEX -2 + +const int Player::_directionListIndexes[32] = { + 0, 7, 4, 3, 6, 0, 2, 5, 0, 1, 9, 4, 1, 2, 7, 9, 3, 8, 9, 6, 7, 2, 3, 6, 1, 7, 9, 4, 7, 8, 0, 0 +}; + +Player::Player(MADSEngine *vm) + : _vm(vm) { + _action = nullptr; + _facing = FACING_NORTH; + _turnToFacing = FACING_NORTH; + _targetFacing = FACING_NORTH; + _prepareWalkFacing = FACING_NONE; + _mirror = false; + _spritesLoaded = false; + _spritesStart = 0; + _spritesIdx = 0; + _numSprites = 0; + _stepEnabled = false; + _visible = false; + _priorVisible = false; + _needToWalk = false; + _readyToWalk = false; + _beenVisible = false; + _loadsFirst = false; + _loadedFirst = false; + _walkAnywhere = false; + _special = 0; + _ticksAmount = 0; + _priorTimer = 0; + _trigger = 0; + _scalingVelocity = false; + _spritesChanged = false; + _forceRefresh = false; + _highSprites = false; + _currentDepth = 0; + _currentScale = 0; + _frameNumber = 0; + _centerOfGravity = 0; + _frameCount = 0; + _velocity = 0; + _upcomingTrigger = 0; + _trigger = 0; + _frameListIndex = 0; + _stopWalkerIndex = 0; + _totalDistance = 0; + _distAccum = 0; + _pixelAccum = 0; + _deltaDistance = 0; + _xDirection = 0; + _yDirection = 0; + _moving = false; + _walkOffScreen = 0; + _walkOffScreenSceneId = -1; + + Common::fill(&_stopWalkerList[0], &_stopWalkerList[12], 0); + Common::fill(&_stopWalkerTrigger[0], &_stopWalkerTrigger[12], 0); + Common::fill(&_spriteSetsPresent[0], &_spriteSetsPresent[PLAYER_SPRITES_FILE_COUNT], false); +} + +void Player::cancelWalk() { + Scene &scene = _vm->_game->_scene; + _action = &scene._action; + _targetPos = _playerPos; + _targetFacing = FACING_NONE; + _turnToFacing = _facing; + _moving = false; + _walkOffScreen = _walkOffScreenSceneId = 0; + scene._rails.resetRoute(); + _walkAnywhere = false; + + _needToWalk = false; + _readyToWalk = false; +} + +bool Player::loadSprites(const Common::String &prefix) { + Common::String suffixList = "89632741"; + + Common::String newPrefix; + if (prefix.empty()) { + newPrefix = _spritesPrefix; + } else { + _spritesPrefix = prefix; + newPrefix = prefix; + } + + _numSprites = 0; + if (!_spritesPrefix.empty()) { + for (int fileIndex = 0; fileIndex < PLAYER_SPRITES_FILE_COUNT; ++fileIndex) { + Common::String setName = Common::String::format("*%s_%c.SS", + newPrefix.c_str(), suffixList[fileIndex]); + if (fileIndex >= 5) + _highSprites = true; + + _spriteSetsPresent[fileIndex] = true; + + int setIndex = -1; + if (Common::File::exists(setName)) { + setIndex = _vm->_game->_scene._sprites.addSprites(setName, 4); + ++_numSprites; + } else if (fileIndex < 5) { + _highSprites = 0; + return true; + } else { + _spriteSetsPresent[fileIndex] = false; + } + + if (fileIndex == 0) + _spritesStart = setIndex; + } + + _spritesLoaded = true; + _spritesChanged = false; + _highSprites = false; + return false; + } else { + Common::fill(&_spriteSetsPresent[0], &_spriteSetsPresent[PLAYER_SPRITES_FILE_COUNT], false); + _highSprites = false; + return false; + } +} + +void Player::setFinalFacing() { + if (_targetFacing != FACING_NONE) + _turnToFacing = _targetFacing; +} + +void Player::changeFacing() { + int dirIndex = 0, dirIndex2 = 0; + int newDir = 0, newDir2 = 0; + + if (_facing != _turnToFacing) { + // Find the index for the given direction in the player direction list + int tempDir = _facing; + do { + ++dirIndex; + newDir += tempDir; + tempDir = _directionListIndexes[tempDir + 10]; + } while (tempDir != _turnToFacing); + } + + + if (_facing != _turnToFacing) { + // Find the index for the given direction in the player direction list + int tempDir = _facing; + do { + ++dirIndex2; + newDir2 += tempDir; + tempDir = _directionListIndexes[tempDir + 20]; + } while (tempDir != _turnToFacing); + } + + int diff = dirIndex - dirIndex2; + if (diff == 0) + diff = newDir - newDir2; + + _facing = (diff >= 0) ? (Facing)_directionListIndexes[_facing + 20] : + (Facing)_directionListIndexes[_facing + 10]; + selectSeries(); + + if ((_facing == _turnToFacing) && !_moving) + updateFrame(); + + _priorTimer += 1; +} + +void Player::cancelCommand() { + cancelWalk(); + _action->_inProgress = false; +} + +void Player::selectSeries() { + Scene &scene = _vm->_game->_scene; + + clearStopList(); + _mirror = false; + + _spritesIdx = _directionListIndexes[_facing]; + if (!_spriteSetsPresent[_spritesIdx]) { + // Direction isn't present, so use alternate direction, with entries flipped + _spritesIdx -= 4; + _mirror = true; + } + + // If the user isn't to be present (such as for a cutscene), exit immediately + // WORKAROUND: Original didn't do a secondary check for the sprite set being + // present, but it's needed to prevent invalid reads during cutscenes + if ((_spritesStart + _spritesIdx) < 0 || !_spriteSetsPresent[_spritesIdx]) + return; + + SpriteAsset &spriteSet = *scene._sprites[_spritesStart + _spritesIdx]; + assert(spriteSet._charInfo); + _velocity = MAX(spriteSet._charInfo->_velocity, 100); + setBaseFrameRate(); + + _frameCount = spriteSet._charInfo->_totalFrames; + if (_frameCount == 0) + _frameCount = spriteSet.getCount(); + + _centerOfGravity = spriteSet._charInfo->_centerOfGravity; + + if ((_frameNumber <= 0) || (_frameNumber > _frameCount)) + _frameNumber = 1; + + _forceRefresh = true; +} + +void Player::updateFrame() { + // WORKAROUND: Prevent character info being referenced when not present + if ((_spritesStart + _spritesIdx) < 0 || !_spriteSetsPresent[_spritesStart + _spritesIdx]) + return; + + Scene &scene = _vm->_game->_scene; + SpriteAsset &spriteSet = *scene._sprites[_spritesStart + _spritesIdx]; + assert(spriteSet._charInfo); + + if (!spriteSet._charInfo->_numEntries) { + _frameNumber = 1; + } else { + _frameListIndex = _stopWalkerList[_stopWalkerIndex]; + + if (!_visible) { + _upcomingTrigger = 0; + } else { + _upcomingTrigger = _stopWalkerTrigger[_stopWalkerIndex]; + + if (_stopWalkerIndex > 0) + --_stopWalkerIndex; + } + + // Set the player frame number + int listIndex = ABS(_frameListIndex); + _frameNumber = (_frameListIndex >= 0) ? spriteSet._charInfo->_startFrames[listIndex] : + spriteSet._charInfo->_stopFrames[listIndex]; + + // Set next waiting period in ticks + if (listIndex == 0) { + setBaseFrameRate(); + } else { + _ticksAmount = spriteSet._charInfo->_ticksList[listIndex]; + } + } + + _forceRefresh = true; +} + +void Player::update() { + Scene &scene = _vm->_game->_scene; + + if (_forceRefresh || (_visible != _priorVisible)) { + int slotIndex = getSpriteSlot(); + if (slotIndex >= 0) + scene._spriteSlots[slotIndex]._flags = IMG_ERASE; + + int newDepth = 1; + int yp = MIN(_playerPos.y, (int16)(MADS_SCENE_HEIGHT - 1)); + + for (int idx = 1; idx < 15; ++idx) { + if (scene._sceneInfo->_depthList[newDepth] >= yp) + newDepth = idx + 1; + } + _currentDepth = newDepth; + + // Get the scale + int newScale = getScale(_playerPos.y); + _currentScale = MIN(newScale, 100); + + if (_visible) { + // Player sprite needs to be rendered + SpriteSlot slot; + slot._flags = IMG_UPDATE; + slot._seqIndex = PLAYER_SEQ_INDEX; + slot._spritesIndex = _spritesStart + _spritesIdx; + slot._frameNumber = _mirror ? -_frameNumber : _frameNumber; + slot._position.x = _playerPos.x; + slot._position.y = _playerPos.y + (_centerOfGravity * newScale) / 100; + slot._depth = newDepth; + slot._scale = newScale; + + if (slotIndex >= 0) { + // Check if the existing player slot has the same details, and can be re-used + SpriteSlot &s2 = scene._spriteSlots[slotIndex]; + bool equal = (s2._seqIndex == slot._seqIndex) + && (s2._spritesIndex == slot._spritesIndex) + && (s2._frameNumber == slot._frameNumber) + && (s2._position == slot._position) + && (s2._depth == slot._depth) + && (s2._scale == slot._scale); + + if (equal) + // Undo the prior expiry of the player sprite + s2._flags = IMG_STATIC; + else + slotIndex = -1; + } + + if (slotIndex < 0) { + // New slot needed, so allocate one and copy the slot data + slotIndex = scene._spriteSlots.add(); + scene._spriteSlots[slotIndex] = slot; + } + + // If changing a scene, check to change the scene when the player + // has moved off-screen + if (_walkOffScreen) { + SpriteAsset *asset = scene._sprites[slot._spritesIndex]; + MSprite *frame = asset->getFrame(_frameNumber - 1); + int xScale = frame->w * newScale / 200; + int yScale = frame->h * newScale / 100; + int playerX = slot._position.x; + int playerY = slot._position.y; + + if ((playerX + xScale) < 0 || (playerX + xScale) >= MADS_SCREEN_WIDTH || + playerY < 0 || (playerY + yScale) >= MADS_SCENE_HEIGHT) { + scene._nextSceneId = _walkOffScreen; + _walkOffScreen = 0; + _walkAnywhere = false; + } + } + + } + } + + _beenVisible |= _visible; + _priorVisible = _visible; + _forceRefresh = false; +} + +void Player::clearStopList() { + _stopWalkerList[0] = 0; + _stopWalkerTrigger[0] = 0; + _stopWalkerIndex = 0; + _upcomingTrigger = 0; + _trigger = 0; +} + +void Player::startWalking(const Common::Point &pt, Facing facing) { + Scene &scene = _vm->_game->_scene; + + clearStopList(); + setBaseFrameRate(); + _moving = true; + _targetFacing = facing; + + bool v = scene._depthSurface.getDepthHighBit(pt); + + scene._rails.setupRoute(v, _playerPos, pt); +} + +void Player::walk(const Common::Point &pos, Facing facing) { + cancelWalk(); + _needToWalk = true; + _readyToWalk = true; + _prepareWalkPos = pos; + _prepareWalkFacing = facing; +} + +void Player::nextFrame() { + Scene &scene = _vm->_game->_scene; + + uint32 newTime = _priorTimer + _ticksAmount; + if (scene._frameStartTime >= newTime) { + _priorTimer = scene._frameStartTime; + if (_moving) { + move(); + } else { + idle(); + } + + setFrame(); + update(); + } +} + +void Player::move() { + Scene &scene = _vm->_game->_scene; + Rails &rails = scene._rails; + bool newFacing = false; + + if (_moving) { + while (!_walkOffScreen && _playerPos == _targetPos) { + bool isRouteEmpty = rails.empty(); + if (!isRouteEmpty) { + const WalkNode &node = rails.popNode(); + + _targetPos = node._walkPos; + newFacing = true; + } else if (!_walkOffScreenSceneId) { + // End of walking path + rails.resetRoute(); + _moving = false; + setFinalFacing(); + newFacing = true; + } else { + _walkOffScreen = _walkOffScreenSceneId; + _walkAnywhere = true; + _walkOffScreenSceneId = 0; + _stepEnabled = false; + newFacing = false; + } + + if (!_moving) + break; + } + } + + if (newFacing && _moving) + startMovement(); + + if (_turnToFacing != _facing) + changeFacing(); + else if (!_moving) + updateFrame(); + + int velocity = _velocity; + if (_scalingVelocity && (_totalDistance > 0)) { + int angleRange = 100 - _currentScale; + int angleScale = angleRange * (_posDiff.x - 1) / _totalDistance + _currentScale; + velocity = MAX(1L, (angleScale * _currentScale * velocity) / 10000L); + } + + if (!_moving || (_facing != _turnToFacing)) + return; + + Common::Point newPos = _playerPos; + newFacing = false; + _special = 0; + + if (_distAccum < velocity) { + do { + if (_pixelAccum < _posDiff.x) + _pixelAccum += _posDiff.y; + if (_pixelAccum >= _posDiff.x) { + if ((_posChange.y > 0) || _walkOffScreen) + newPos.y += _yDirection; + --_posChange.y; + _pixelAccum -= _posDiff.x; + } + + if (_pixelAccum < _posDiff.x) { + if ((_posChange.x > 0) || _walkOffScreen) + newPos.x += _xDirection; + --_posChange.x; + } + + if (!_walkAnywhere && !_walkOffScreen && (_walkOffScreenSceneId == 0)) { + newFacing = scene._depthSurface.getDepthHighBit(newPos); + + if (_special == 0) + _special = scene.getDepthHighBits(newPos); + } + + _distAccum += _deltaDistance; + + } while ((_distAccum < velocity) && !newFacing && ((_posChange.x > 0) || (_posChange.y > 0) || (_walkOffScreen != 0))); + } + + _distAccum -= velocity; + + if (newFacing) { + cancelCommand(); + } else { + if (!_walkOffScreen) { + // If the move is complete, make sure the position is exactly on the given destination + if (_posChange.x == 0) + newPos.x = _targetPos.x; + if (_posChange.y == 0) + newPos.y = _targetPos.y; + } + + _playerPos = newPos; + } +} + +void Player::idle() { + Scene &scene = _vm->_game->_scene; + + if (_facing != _turnToFacing) { + // The direction has changed, so reset for new direction + changeFacing(); + return; + } + + if ((_spritesStart + _spritesIdx) < 0 || !_spriteSetsPresent[_spritesStart + _spritesIdx]) + return; + + SpriteAsset &spriteSet = *scene._sprites[_spritesStart + _spritesIdx]; + assert(spriteSet._charInfo); + if (spriteSet._charInfo->_numEntries == 0) + // No entries, so exit immediately + return; + + int frameIndex = ABS(_frameListIndex); + int direction = (_frameListIndex < 0) ? -1 : 1; + + if (frameIndex >= spriteSet._charInfo->_numEntries) { + // Reset back to the start of the list + _frameListIndex = 0; + } else { + _frameNumber += direction; + _forceRefresh = true; + + if (spriteSet._charInfo->_stopFrames[frameIndex] < _frameNumber) { + _trigger = _upcomingTrigger; + updateFrame(); + } + if (spriteSet._charInfo->_startFrames[frameIndex] < _frameNumber) { + _trigger = _upcomingTrigger; + updateFrame(); + } + } +} + +void Player::setFrame() { + if (_moving) { + if (++_frameNumber > _frameCount) + _frameNumber = 1; + _forceRefresh = true; + } else { + if (!_forceRefresh) + idle(); + } +} + +int Player::getSpriteSlot() { + SpriteSlots &spriteSlots = _vm->_game->_scene._spriteSlots; + + for (uint idx = 0; idx < spriteSlots.size(); ++idx) { + if (spriteSlots[idx]._seqIndex == PLAYER_SEQ_INDEX && + spriteSlots[idx]._flags >= IMG_STATIC) + return idx; + } + + return - 1; +} + +int Player::getScale(int yp) { + Scene &scene = _vm->_game->_scene; + + int scale = (scene._bandsRange == 0) ? scene._sceneInfo->_maxScale : + (yp - scene._sceneInfo->_yBandsStart) * scene._scaleRange / scene._bandsRange + + scene._sceneInfo->_minScale; + + return MIN(scale, 100); +} + +void Player::setBaseFrameRate() { + Scene &scene = _vm->_game->_scene; + + SpriteAsset &spriteSet = *scene._sprites[_spritesStart + _spritesIdx]; + assert(spriteSet._charInfo); + + _ticksAmount = spriteSet._charInfo->_ticksAmount; + if (_ticksAmount == 0) + _ticksAmount = 6; +} + +void Player::startMovement() { + int xDiff = _targetPos.x - _playerPos.x; + int yDiff = _targetPos.y - _playerPos.y; + int srcScale = getScale(_playerPos.y); + int destScale = getScale(_targetPos.y); + + // Sets the X direction + if (xDiff > 0) + _xDirection = 1; + else if (xDiff < 0) + _xDirection = -1; + else + _xDirection = 0; + + // Sets the Y direction + if (yDiff > 0) + _yDirection = 1; + else if (yDiff < 0) + _yDirection = -1; + else + _yDirection = 0; + + xDiff = ABS(xDiff); + yDiff = ABS(yDiff); + int scaleDiff = ABS(srcScale - destScale); + + int xAmt100 = xDiff * 100; + int yAmt100 = yDiff * 100; + int xAmt33 = xDiff * 33; + + int scaleAmount = (_scalingVelocity ? scaleDiff * 3 : 0) + 100 * yDiff / 100; + int scaleAmount100 = scaleAmount * 100; + + // Figure out direction that will need to be moved in + int majorDir; + if (xDiff == 0) { + majorDir = 1; + } else if (yDiff == 0) { + majorDir = 3; + } else { + if ((scaleAmount < xDiff) && ((xAmt33 / scaleAmount) >= 141)) + majorDir = 3; + else if (yDiff <= xDiff) + majorDir = 2; + else if ((scaleAmount100 / xDiff) >= 141) + majorDir = 1; + else + majorDir = 2; + } + + switch (majorDir) { + case 1: + _turnToFacing = (_yDirection <= 0) ? FACING_NORTH : FACING_SOUTH; + break; + case 2: { + _turnToFacing = (Facing)(((_yDirection <= 0) ? 9 : 3) - ((_xDirection <= 0) ? 2 : 0)); + break; + } + case 3: + _turnToFacing = (_xDirection <= 0) ? FACING_WEST : FACING_EAST; + break; + default: + break; + } + + _totalDistance = sqrt((double)(xAmt100 * xAmt100 + yAmt100 * yAmt100)); + _posDiff.x = xDiff + 1; + _posDiff.y = yDiff + 1; + _posChange.x = xDiff; + _posChange.y = yDiff; + + int majorChange = MAX(xDiff, yDiff); + _deltaDistance = (majorChange == 0) ? 0 : _totalDistance / majorChange; + + if (_playerPos.x > _targetPos.x) + _pixelAccum = MAX(_posChange.x, _posChange.y); + else + _pixelAccum = 0; + + _totalDistance /= 100; + _distAccum = -_deltaDistance; +} + +void Player::newWalk() { + if (_needToWalk && _readyToWalk) { + startWalking(_prepareWalkPos, _prepareWalkFacing); + _needToWalk = false; + } +} + +void Player::addWalker(int walker, int trigger) { + Scene &scene = _vm->_game->_scene; + SpriteAsset &spriteSet = *scene._sprites[_spritesStart + _spritesIdx]; + assert(spriteSet._charInfo); + + if (walker < spriteSet._charInfo->_numEntries && _stopWalkerIndex < 11) { + ++_stopWalkerIndex; + _stopWalkerList[_stopWalkerIndex] = walker; + _stopWalkerTrigger[_stopWalkerIndex] = trigger; + } +} + + +/** +* Releases any sprites used by the player +*/ +void Player::releasePlayerSprites() { + Scene &scene = _vm->_game->_scene; + + if (_spritesLoaded && _numSprites > 0) { + int spriteEnd = _spritesStart + _numSprites - 1; + do { + scene._sprites.remove(spriteEnd); + } while (--spriteEnd >= _spritesStart); + } + + _numSprites = 0; + _spritesLoaded = false; + _spritesChanged = true; + + if (scene._sprites._assetCount > 0) { + warning("Player::releasePlayerSprites(): leftover sprites remain, clearing list"); + scene._sprites.clear(); + } +} + +void Player::synchronize(Common::Serializer &s) { + s.syncAsByte(_moving); + s.syncAsSint16LE(_playerPos.x); + s.syncAsSint16LE(_playerPos.y); + s.syncAsSint16LE(_targetPos.x); + s.syncAsSint16LE(_targetPos.y); + s.syncAsSint16LE(_xDirection); + s.syncAsSint16LE(_yDirection); + s.syncAsSint16LE(_posDiff.x); + s.syncAsSint16LE(_posDiff.y); + s.syncAsSint16LE(_posChange.x); + s.syncAsSint16LE(_posChange.y); + s.syncAsUint16LE(_targetFacing); + s.syncAsSint16LE(_special); + s.syncAsByte(_forceRefresh); + s.syncAsSint16LE(_ticksAmount); + s.syncAsByte(_walkAnywhere); + s.syncAsUint16LE(_walkOffScreenSceneId); + s.syncAsByte(_walkOffScreen); + s.syncAsByte(_needToWalk); + s.syncAsByte(_readyToWalk); + s.syncAsUint16LE(_prepareWalkFacing); + s.syncAsSint16LE(_prepareWalkPos.x); + s.syncAsSint16LE(_prepareWalkPos.y); + s.syncAsByte(_stepEnabled); + s.syncAsByte(_visible); + s.syncAsByte(_priorVisible); + + for (int i = 0; i < 8; ++i) + s.syncAsByte(_spriteSetsPresent[i]); + + s.syncAsByte(_facing); + s.syncAsByte(_turnToFacing); + s.syncAsSint16LE(_spritesIdx); + s.syncAsSint16LE(_frameNumber); + s.syncAsSint16LE(_currentDepth); + s.syncAsSint16LE(_currentScale); + s.syncAsSint16LE(_frameListIndex); + + for (int i = 0; i < 12; ++i) { + s.syncAsSint16LE(_stopWalkerList[i]); + s.syncAsSint16LE(_stopWalkerTrigger[i]); + } + + s.syncAsSint16LE(_stopWalkerIndex); + s.syncAsSint16LE(_upcomingTrigger); + s.syncAsSint16LE(_trigger); + s.syncAsSint16LE(_scalingVelocity); + s.syncAsSint16LE(_pixelAccum); + s.syncAsSint16LE(_distAccum); + s.syncAsSint16LE(_deltaDistance); + s.syncAsSint16LE(_totalDistance); + s.syncAsSint16LE(_velocity); + s.syncAsUint16LE(_frameCount); + s.syncString(_spritesPrefix); + s.syncAsUint32LE(_priorTimer); + s.syncAsByte(_loadsFirst); + s.syncAsByte(_loadedFirst); + s.syncAsByte(_spritesLoaded); + s.syncAsByte(_spritesChanged); + s.syncAsByte(_beenVisible); + s.syncAsSint16LE(_centerOfGravity); + s.syncAsByte(_mirror); +} + +void Player::removePlayerSprites() { + Scene &scene = _vm->_game->_scene; + int heroSpriteId = _spritesStart; + for (int i = 0; i < 8; i++) { + if (_spriteSetsPresent[i]) { + scene._sprites.remove(heroSpriteId++); + _spriteSetsPresent[i] = false; + } + } + + if (scene._activeAnimation != nullptr) + scene._activeAnimation->resetSpriteSetsCount(); + + scene._spriteSlots.fullRefresh(); + _visible = false; +} + +} // End of namespace MADS diff --git a/engines/mads/player.h b/engines/mads/player.h new file mode 100644 index 0000000000..671ac9d16e --- /dev/null +++ b/engines/mads/player.h @@ -0,0 +1,228 @@ +/* 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. + * + */ + +#ifndef MADS_PLAYER_H +#define MADS_PLAYER_H + +#include "common/scummsys.h" +#include "common/str.h" +#include "common/serializer.h" + +namespace MADS { + +class MADSEngine; +class MADSAction; + +#define PLAYER_SPRITES_FILE_COUNT 8 +#define MAX_ROUTE_NODES 22 + +/** + * Player facings + */ +enum Facing { + FACING_NORTH = 8, FACING_SOUTH = 2, FACING_EAST = 6, FACING_WEST = 4, + FACING_NORTHEAST = 9, FACING_SOUTHEAST = 3, + FACING_SOUTHWEST = 1, FACING_NORTHWEST = 7, + FACING_NONE = 5, FACING_DUMMY = 0 +}; + +class Player { +private: + static const int _directionListIndexes[32]; +private: + MADSEngine *_vm; + bool _highSprites; + bool _spriteSetsPresent[PLAYER_SPRITES_FILE_COUNT]; + bool _mirror; + int _frameCount; + int _frameListIndex; + int _distAccum; + int _pixelAccum; + int _deltaDistance; + int _stopWalkerList[12]; + int _stopWalkerTrigger[12]; + int _totalDistance; + + void clearStopList(); + + /** + * If the player is moving, handles figuring out the correct motion + */ + void move(); + + /** + * Update the player's frame number + */ + void setFrame(); + + /** + * Get the sprite slot index for the player + */ + int getSpriteSlot(); + + /** + * Get the scale for the player at the given Y position + */ + int getScale(int yp); + + /** + * Sets the frame rate for the current sprite set + */ + void setBaseFrameRate(); + + /** + * Starts a player moving to a given destination + */ + void startMovement(); + + void changeFacing(); +public: + MADSAction *_action; + + Facing _facing; + Facing _turnToFacing; + Facing _prepareWalkFacing; + int _xDirection, _yDirection; + Facing _targetFacing; + bool _spritesLoaded; + int _spritesStart; + int _spritesIdx; + int _numSprites; + bool _stepEnabled; + bool _spritesChanged; + bool _visible; + bool _priorVisible; + bool _beenVisible; + bool _walkAnywhere; + int _frameNumber; + bool _loadsFirst; + bool _loadedFirst; + Common::Point _playerPos; + Common::Point _targetPos; + Common::Point _posChange; + Common::Point _posDiff; + Common::Point _prepareWalkPos; + bool _moving; + int _walkOffScreen, _walkOffScreenSceneId; + int _special; + int _ticksAmount; + uint32 _priorTimer; + int _velocity; + int _upcomingTrigger; + int _trigger; + bool _scalingVelocity; + bool _forceRefresh; + bool _needToWalk; + bool _readyToWalk; + int _stopWalkerIndex; + int _centerOfGravity; + int _currentDepth; + int _currentScale; + Common::String _spritesPrefix; +public: + Player(MADSEngine *vm); + + /** + * Load sprites for the player + */ + bool loadSprites(const Common::String &prefix); + + /** + * Called when the player has reached the given destination, start him + * turning to the specified facing + */ + void setFinalFacing(); + + /** + * Stops the player walking + */ + void cancelWalk(); + + /** + * Cancels any oustanding player action + */ + void cancelCommand(); + + /** + * Set up control parameters for the current active series (the + * direction which the player is facing in) */ + void selectSeries(); + + /* + * Moves to the next frame for the currently active player sprite set + */ + void updateFrame(); + + void update(); + + /** + * Handler method for when the player is not moving + */ + void idle(); + + /** + * Starts the player walking towards a given point and direction facing + * @param pos Destination location + * @param facing Direction to face once the destination is reached + */ + void startWalking(const Common::Point &pt, Facing facing); + + /** + * Used by the game scripst to make the player walk to a given destination. + * The difference from startWalking is that this contains several extra + * layers of checking that startWalking bypasses. + */ + void walk(const Common::Point &pos, Facing facing); + + /** + * If a new walk sequence is pending, and has been okayed by the preparser, + * start the actual walking + */ + void newWalk(); + + void nextFrame(); + + /** + * Add a walker to the current queue + */ + void addWalker(int walker, int trigger); + + /** + * Delete any sprites used by the player + */ + void releasePlayerSprites(); + + /** + * Serialize the data of the player + */ + void synchronize(Common::Serializer &s); + + static void preloadSequences(const Common::String &prefix, int level) { + // No implementation in ScummVM + } + + void removePlayerSprites(); +}; + +} // End of namespace MADS + +#endif /* MADS_PLAYER_H */ diff --git a/engines/mads/rails.cpp b/engines/mads/rails.cpp new file mode 100644 index 0000000000..7f8a56d21b --- /dev/null +++ b/engines/mads/rails.cpp @@ -0,0 +1,277 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "mads/mads.h" +#include "mads/rails.h" + +namespace MADS { + +WalkNode::WalkNode() { + _active = false; + Common::fill(&_distances[0], &_distances[MAX_ROUTE_NODES], 0); +} + +void WalkNode::load(Common::SeekableReadStream *f) { + _walkPos.x = f->readSint16LE(); + _walkPos.y = f->readSint16LE(); + for (int i = 0; i < MAX_ROUTE_NODES; ++i) + _distances[i] = f->readUint16LE(); +} + +/*------------------------------------------------------------------------*/ + +Rails::Rails() { + _depthSurface = nullptr; + _routeLength = 0; + _depthStyle = 0; + _next = 0; +} + +void Rails::load(const WalkNodeList &nodes, DepthSurface *depthSurface, int depthStyle) { + // Store the depth surface and depth style to use + _depthSurface = depthSurface; + _depthStyle = depthStyle; + + // Load the passed node list + _nodes.clear(); + + for (uint i = 0; i < nodes.size(); ++i) + _nodes.push_back(nodes[i]); + + // Add two more empty nodes for the start and end points of any walk sequence + _nodes.push_back(WalkNode()); + _nodes.push_back(WalkNode()); +} + + +void Rails::setupRoute(bool bitFlag, const Common::Point &srcPos, const Common::Point &destPos) { + // Reset the nodes in as being inactive + for (uint i = 0; i < _nodes.size(); ++i) + _nodes[i]._active = false; + + // Set the two extra walk nodes to the start and destination positions + setNodePosition(_nodes.size() - 2, srcPos); + setNodePosition(_nodes.size() - 1, destPos); + + // Start constructing route node list + _routeLength = 0x3FFF; + _routeIndexes.clear(); + + // Recursively form a route from the destination walk node back to the player's position + setupRouteNode(&_tempRoute[0], _nodes.size() - 1, bitFlag ? 0xC000 : 0x8000, 0); + + _next = 0; + if (_routeIndexes.size() > 0) { + Common::Point currPos = srcPos; + for (int routeCtr = size() - 1; (routeCtr >= 0) && !_next; --routeCtr) { + int idx = _routeIndexes[routeCtr]; + const Common::Point &pt = _nodes[idx]._walkPos; + + _next = scanPath(currPos, pt); + currPos = pt; + } + } +} + +void Rails::setupRouteNode(int *routeIndexP, int nodeIndex, int flags, int routeLength) { + WalkNode ¤tNode = _nodes[nodeIndex]; + currentNode._active = true; + + *routeIndexP++ = nodeIndex; + + // Get the index of the ultimate source position (the player) + int subIndex = _nodes.size() - 2; + + int distanceVal = _nodes[nodeIndex]._distances[subIndex]; + if (distanceVal & flags) { + routeLength += distanceVal & 0x3FFF; + if (routeLength < _routeLength) { + // Found a new shorter route to destination, so set up the route with the found one + _routeIndexes.clear(); + for (int i = 0; routeIndexP != &_tempRoute[i]; ++i) + _routeIndexes.push(_tempRoute[i]); + _routeLength = routeLength; + } + } else { + for (int idx = _nodes.size() - 2; idx > 0; --idx) { + int nodePos = idx - 1; + if (!_nodes[nodePos]._active && ((currentNode._distances[nodePos] & flags) != 0)) + setupRouteNode(routeIndexP, nodePos, 0x8000, routeLength + (distanceVal & 0x3fff)); + } + } + + currentNode._active = false; +} + + +int Rails::scanPath(const Common::Point &srcPos, const Common::Point &destPos) { + // For compressed depth surfaces, always return 0 + if (_depthStyle == 2) + return 0; + + int yDiff = destPos.y - srcPos.y; + int yAmount = MADS_SCREEN_WIDTH; + + if (yDiff < 0) { + yDiff = -yDiff; + yAmount = -yAmount; + } + + int xDiff = destPos.x - srcPos.x; + int xDirection = 1; + int xAmount = 0; + if (xDiff < 0) { + xDiff = -xDiff; + xDirection = -xDirection; + xAmount = MIN(yDiff, xDiff); + } + + ++xDiff; + ++yDiff; + + const byte *srcP = _depthSurface->getBasePtr(srcPos.x, srcPos.y); + int index = xAmount; + + // Outer loop + for (int xCtr = 0; xCtr < xDiff; ++xCtr, srcP += xDirection) { + index += yDiff; + int v = (*srcP & 0x7F) >> 4; + if (v) + return v; + + // Inner loop for handling vertical movement + while (index >= xDiff) { + index -= xDiff; + + v = (*srcP & 0x7F) >> 4; + if (v) + return v; + + srcP += yAmount; + } + } + + return 0; +} + +void Rails::resetRoute() { + _routeIndexes.clear(); + _next = 0; +} + +const WalkNode &Rails::popNode() { + assert(!_routeIndexes.empty()); + + return _nodes[_routeIndexes.pop()]; +} + +void Rails::setNodePosition(int nodeIndex, const Common::Point &pt) { + int flags, hypotenuse; + + _nodes[nodeIndex]._walkPos = pt; + + // Recalculate inter-node lengths + for (uint idx = 0; idx < _nodes.size(); ++idx) { + int entry; + if (idx == (uint)nodeIndex) { + entry = 0x3FFF; + } else { + // Process the node + flags = getRouteFlags(pt, _nodes[idx]._walkPos); + + int xDiff = ABS(_nodes[idx]._walkPos.x - pt.x); + int yDiff = ABS(_nodes[idx]._walkPos.y - pt.y); + hypotenuse = sqrt((double)(xDiff * xDiff + yDiff * yDiff)); + + if (hypotenuse >= 0x3FFF) + // Shouldn't ever be this large + hypotenuse = 0x3FFF; + + entry = hypotenuse | flags; + } + + _nodes[idx]._distances[nodeIndex] = entry; + _nodes[nodeIndex]._distances[idx] = entry; + } +} + +int Rails::getRouteFlags(const Common::Point &src, const Common::Point &dest) { + int result = 0x8000; + bool flag = false; + + int xDiff = ABS(dest.x - src.x); + int yDiff = ABS(dest.y - src.y); + int xDirection = dest.x >= src.x ? 1 : -1; + int yDirection = dest.y >= src.y ? _depthSurface->w : -_depthSurface->w; + int minorDiff = 0; + if (dest.x < src.x) + minorDiff = MIN(xDiff, yDiff); + ++xDiff; + ++yDiff; + + byte *srcP = _depthSurface->getBasePtr(src.x, src.y); + + int totalCtr = minorDiff; + for (int xCtr = 0; xCtr < xDiff; ++xCtr, srcP += xDirection) { + totalCtr += yDiff; + + if ((*srcP & 0x80) == 0) + flag = false; + else if (!flag) { + flag = true; + result -= 0x4000; + if (result == 0) + break; + } + + while (totalCtr >= xDiff) { + totalCtr -= xDiff; + + if ((*srcP & 0x80) == 0) + flag = false; + else if (!flag) { + flag = true; + result -= 0x4000; + if (result == 0) + break; + } + + srcP += yDirection; + } + if (result == 0) + break; + } + + return result; +} + +void Rails::synchronize(Common::Serializer &s) { + s.syncAsSint16LE(_routeLength); + s.syncAsSint16LE(_next); + + if (s.isLoading()) { + _routeIndexes.clear(); + } +} + +} // End of namespace MADS diff --git a/engines/mads/rails.h b/engines/mads/rails.h new file mode 100644 index 0000000000..e6cab08f85 --- /dev/null +++ b/engines/mads/rails.h @@ -0,0 +1,134 @@ +/* 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. + * + */ + +#ifndef MADS_RAILS_H +#define MADS_RAILS_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/rect.h" +#include "common/serializer.h" +#include "common/stack.h" +#include "mads/msurface.h" + +namespace MADS { + +class WalkNode { +public: + Common::Point _walkPos; + uint16 _distances[MAX_ROUTE_NODES]; + bool _active; + + /** + * Constructor + */ + WalkNode(); + + /** + * Loads the scene node + */ + void load(Common::SeekableReadStream *f); +}; +typedef Common::Array<WalkNode> WalkNodeList; + +/** + * This class handles storing the intermediate walk node points for a + * given scene, and calculating walking routes between any two positions. + */ +class Rails { +private: + WalkNodeList _nodes; + DepthSurface *_depthSurface; + int _depthStyle; + int _routeLength; + int _next; + int _tempRoute[MAX_ROUTE_NODES]; + Common::Stack<int> _routeIndexes; +private: + /** + * Change the position of a walking node. Doing so causes a recalculation of the + * distance between it and every other node, and vice versa + */ + void setNodePosition(int nodeIndex, const Common::Point &pt); + + int getRouteFlags(const Common::Point &src, const Common::Point &dest); +public: + /** + * Constructor + */ + Rails(); + + /** + * Loads the scene data for the list of intermediate walk nodes and the + * depth surface to use. + * @param nodes Intermediate walk-points + * @param depthSurface Depth surface to use + */ + void load(const WalkNodeList &nodes, DepthSurface *depthSurface, int depthStyle); + + /** + * Set up a route between two points in a scene + */ + void setupRoute(bool bitFlag, const Common::Point &srcPos, const Common::Point &destPos); + + void setupRouteNode(int *routeIndexP, int nodeIndex, int flags, int routeLength); + + /** + * Resets any currently running route + */ + void resetRoute(); + + /** + * Scans along an edge connecting two points within the depths/walk surface, and returns the information of the first + * pixel high nibble encountered with a non-zero value + */ + int scanPath(const Common::Point &srcPos, const Common::Point &destPos); + + /* + * Return the number of walk nodes in the calculated route + */ + int size() const { return _routeIndexes.size(); } + + /** + * Returns true if the current calculated walk route is empty + */ + bool empty() const { return _routeIndexes.empty(); } + + /** + * Returns the data for a given walk node + */ + const WalkNode &operator[](int idx) { return _nodes[_routeIndexes[idx]]; } + + const WalkNode &popNode(); + + void resetNext() { _next = 0; } + int getNext() { return _next; } + + /** + * Synchronize the data for the route + */ + void synchronize(Common::Serializer &s); +}; + +} // End of namespace MADS + +#endif /* MADS_RAILS_H */ diff --git a/engines/mads/resources.cpp b/engines/mads/resources.cpp new file mode 100644 index 0000000000..1fb75e6ba2 --- /dev/null +++ b/engines/mads/resources.cpp @@ -0,0 +1,417 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "common/archive.h" +#include "common/textconsole.h" +#include "mads/mads.h" +#include "mads/resources.h" + +namespace MADS { + +enum ResourceType {RESTYPE_ROOM, RESTYPE_SC, RESTYPE_TEXT, RESTYPE_QUO, RESTYPE_I, + RESTYPE_OB, RESTYPE_FONT, RESTYPE_SOUND, RESTYPE_SPEECH, RESTYPE_HAS_EXT, RESTYPE_NO_EXT}; + +/** + * HAG Archives implementation + */ +class HagArchive : public Common::Archive { +private: + /** + * Details of a single entry in a HAG file index + */ + struct HagEntry { + Common::String _resourceName; + uint32 _offset; + uint32 _size; + + HagEntry() : _offset(0), _size(0) {} + HagEntry(Common::String resourceName, uint32 offset, uint32 size) + : _resourceName(resourceName), _offset(offset), _size(size) { + } + }; + + class HagIndex { + public: + Common::List<HagEntry> _entries; + Common::String _filename; + }; + + Common::Array<HagIndex> _index; + + /** + * Load the index of all the game's HAG files + */ + void loadIndex(MADSEngine *vm); + + /** + * Given a resource name, opens up the correct HAG file and returns whether + * an entry with the given name exists. + */ + bool getHeaderEntry(const Common::String &resourceName, HagIndex &hagIndex, HagEntry &hagEntry) const; + + /** + * Returns the HAG resource filename that will contain a given resource + */ + Common::String getResourceFilename(const Common::String &resourceName) const; + + /** + * Return a resource type given a resource name + */ + ResourceType getResourceType(const Common::String &resourceName) const; +public: + HagArchive(MADSEngine *vm); + virtual ~HagArchive(); + + // Archive implementation + virtual bool hasFile(const Common::String &name) const; + virtual int listMembers(Common::ArchiveMemberList &list) const; + virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const; + virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const; +}; + +const char *const MADSCONCAT_STRING = "MADSCONCAT"; + +HagArchive::HagArchive(MADSEngine *vm) { + loadIndex(vm); +} + +HagArchive::~HagArchive() { +} + +// Archive implementation +bool HagArchive::hasFile(const Common::String &name) const { + HagIndex hagIndex; + HagEntry hagEntry; + return getHeaderEntry(name, hagIndex, hagEntry); +} + +int HagArchive::listMembers(Common::ArchiveMemberList &list) const { + int members = 0; + + for (uint hagCtr = 0; hagCtr < _index.size(); ++hagCtr) { + HagIndex hagIndex = _index[hagCtr]; + Common::List<HagEntry>::iterator i; + + for (i = hagIndex._entries.begin(); i != hagIndex._entries.end(); ++i) { + list.push_back(Common::ArchiveMemberList::value_type( + new Common::GenericArchiveMember((*i)._resourceName, this))); + ++members; + } + } + + return members; +} + +const Common::ArchiveMemberPtr HagArchive::getMember(const Common::String &name) const { + if (!hasFile(name)) + return Common::ArchiveMemberPtr(); + + return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this)); +} + +Common::SeekableReadStream *HagArchive::createReadStreamForMember(const Common::String &name) const { + HagIndex hagIndex; + HagEntry hagEntry; + + if (getHeaderEntry(name, hagIndex, hagEntry)) { + // Entry found. If the correct file is not already open, open it + Common::File f; + if (!f.open(hagIndex._filename)) + error("Could not open HAG file"); + + // Return a new stream for the specific resource + f.seek(hagEntry._offset); + return f.readStream(hagEntry._size); + } + + return nullptr; +} + +void HagArchive::loadIndex(MADSEngine *vm) { + Common::File hagFile; + + for (int sectionIndex = -1; sectionIndex < 11; ++sectionIndex) { + if (sectionIndex == 0) + continue; + + // Dragonsphere does not have some sections - skip them + if (vm->getGameID() == GType_Dragonsphere) { + if (sectionIndex == 7 || sectionIndex == 8) + continue; + } + + // Phantom does not have some sections - skip them + if (vm->getGameID() == GType_Phantom) { + if (sectionIndex == 6 || sectionIndex == 7 || sectionIndex == 8) + continue; + } + + Common::String filename = (sectionIndex == -1) ? "GLOBAL.HAG" : + Common::String::format("SECTION%d.HAG", sectionIndex); + if (sectionIndex == 10) { + // Speech + if (!Common::File::exists("SPEECH.HAG")) + break; + else + filename = "SPEECH.HAG"; + } + if (!hagFile.open(filename)) + error("Could not locate HAG file - %s", filename.c_str()); + + // Check for header + char headerBuffer[16]; + if ((hagFile.read(headerBuffer, 16) != 16) || + (strncmp(headerBuffer, MADSCONCAT_STRING, 10) != 0)) + error("Invalid HAG file opened"); + + // Scan through the HAG index + int numEntries = hagFile.readUint16LE(); + + HagIndex hagIndex; + hagIndex._filename = filename; + + for (int idx = 0; idx < numEntries; ++idx) { + // Read in the details of the next resource + char resourceBuffer[14]; + uint32 offset = hagFile.readUint32LE(); + uint32 size = hagFile.readUint32LE(); + hagFile.read(resourceBuffer, 14); + + hagIndex._entries.push_back(HagEntry(resourceBuffer, offset, size)); + } + + hagFile.close(); + _index.push_back(hagIndex); + } +} + +bool HagArchive::getHeaderEntry(const Common::String &resourceName, + HagIndex &hagIndex, HagEntry &hagEntry) const { + Common::String resName = resourceName; + resName.toUppercase(); + if (resName[0] == '*') + resName.deleteChar(0); + + Common::String hagFilename = getResourceFilename(resName); + + // Find the index for the given file + for (uint hagCtr = 0; hagCtr < _index.size(); ++hagCtr) { + hagIndex = _index[hagCtr]; + + if (hagIndex._filename == hagFilename) { + Common::List<HagEntry>::iterator ei; + for (ei = hagIndex._entries.begin(); ei != hagIndex._entries.end(); ++ei) { + hagEntry = *ei; + if (hagEntry._resourceName.compareToIgnoreCase(resName) == 0) + return true; + } + } + } + + return false; +} + +Common::String HagArchive::getResourceFilename(const Common::String &resourceName) const { + ResourceType resType = getResourceType(resourceName); + Common::String outputFilename = "GLOBAL.HAG"; + + if ((resType == RESTYPE_ROOM) || (resType == RESTYPE_SC)) { + int value = atoi(resourceName.c_str() + 2); + int hagFileNum = (resType == RESTYPE_ROOM) ? value / 100 : value; + + if (hagFileNum > 0) + outputFilename = Common::String::format("SECTION%d.HAG", hagFileNum); + } + + if (resType == RESTYPE_SPEECH) + outputFilename = "SPEECH.HAG"; + + return outputFilename; +} + +ResourceType HagArchive::getResourceType(const Common::String &resourceName) const { + if (resourceName.hasPrefix("RM")) { + // Room resource + return RESTYPE_ROOM; + } else if (resourceName.hasPrefix("SC")) { + // SC resource + return RESTYPE_SC; + } else if (resourceName.hasSuffix(".TXT")) { + // Text resource + return RESTYPE_TEXT; + } else if (resourceName.hasSuffix(".QUO")) { + // QUO resource + return RESTYPE_QUO; + } else if (resourceName.hasPrefix("I")) { + // I resource + return RESTYPE_I; + } else if (resourceName.hasPrefix("OB")) { + // OB resource + return RESTYPE_OB; + } else if (resourceName.hasPrefix("FONT")) { + // FONT resource + return RESTYPE_FONT; + } else if (resourceName.hasPrefix("SOUND")) { + // SOUND resource + return RESTYPE_SOUND; + } else if (resourceName.hasPrefix("SPCHC")) { + // SPEECH resource + return RESTYPE_SPEECH; + } + + // Check for a known extension + const char *extPos = strchr(resourceName.c_str(), '.'); + if (extPos) { + ++extPos; + if (!strcmp(extPos, "FL") || !strcmp(extPos, "LBM") || !strcmp(extPos, "ANM") || + !strcmp(extPos, "AA") || !strcmp(extPos, "SS")) { + return RESTYPE_HAS_EXT; + } + } + + return RESTYPE_NO_EXT; +} + +/*------------------------------------------------------------------------*/ + +void Resources::init(MADSEngine *vm) { + SearchMan.add("HAG", new HagArchive(vm)); +} + +Common::String Resources::formatName(RESPREFIX resType, int id, const Common::String &ext) { + Common::String result = "*"; + + if (resType == 3 && !id) { + id = id / 100; + } + + if (!ext.empty()) { + switch (resType) { + case RESPREFIX_GL: + result += "GL000"; + break; + case RESPREFIX_SC: + result += Common::String::format("SC%.3d", id); + break; + case RESPREFIX_RM: + result += Common::String::format("RM%.3d", id); + break; + default: + break; + } + + result += ext; + } + + return result; +} + +Common::String Resources::formatName(int prefix, char asciiCh, int id, EXTTYPE extType, + const Common::String &suffix) { + Common::String result; + if (prefix <= 0) { + result = "*"; + } else { + result = Common::String::format("%s%.3d", + (prefix < 100) ? "*SC" : "*RM", prefix); + } + + result += Common::String::format("%c", asciiCh); + if (id >= 0) + result += Common::String::format("%d", id); + if (!suffix.empty()) + result += suffix; + + switch (extType) { + case EXT_SS: + result += ".SS"; + break; + case EXT_AA: + result += ".AA"; + break; + case EXT_DAT: + result += ".DAT"; + break; + case EXT_HH: + result += ".HH"; + break; + case EXT_ART: + result += ".ART"; + break; + case EXT_INT: + result += ".INT"; + break; + default: + break; + } + + return result; +} + +Common::String Resources::formatResource(const Common::String &resName, + const Common::String &hagFilename) { +// int v1 = 0, v2 = 0; + + if (resName.hasPrefix("*")) { + // Resource file specified + error("TODO: formatResource"); + } else { + // File outside of hag file + return resName; + } +} + +Common::String Resources::formatAAName(int idx) { + return formatName(0, 'I', idx, EXT_AA, ""); +} + +/*------------------------------------------------------------------------*/ + +void File::openFile(const Common::String &filename) { + if (!Common::File::open(filename)) + error("Could not open file - %s", filename.c_str()); +} + +/*------------------------------------------------------------------------*/ + +void SynchronizedList::synchronize(Common::Serializer &s) { + int v = 0; + int count = size(); + s.syncAsUint16LE(count); + + if (s.isSaving()) { + for (int idx = 0; idx < count; ++idx) { + v = (*this)[idx]; + s.syncAsSint32LE(v); + } + } else { + clear(); + reserve(count); + for (int idx = 0; idx < count; ++idx) { + s.syncAsSint32LE(v); + push_back(v); + } + } +} + +} // End of namespace MADS diff --git a/engines/mads/resources.h b/engines/mads/resources.h new file mode 100644 index 0000000000..8d9ab1e39f --- /dev/null +++ b/engines/mads/resources.h @@ -0,0 +1,89 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 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. + * + */ + +#ifndef MADS_RESOURCES_H +#define MADS_RESOURCES_H + +#include "common/scummsys.h" +#include "common/file.h" +#include "common/serializer.h" +#include "common/str.h" + +namespace MADS { + +class MADSEngine; + +enum RESPREFIX { + RESPREFIX_GL = 1, RESPREFIX_SC = 2, RESPREFIX_RM = 3 +}; + +enum EXTTYPE { + EXT_NONE = -1, EXT_SS = 1, EXT_AA = 2, EXT_DAT = 3, EXT_HH = 4, + EXT_ART = 5, EXT_INT = 6 +}; + +class Resources { +public: + /** + * Instantiates the resource manager + */ + static void init(MADSEngine *vm); + + static Common::String formatName(RESPREFIX resType, int id, const Common::String &ext); + static Common::String formatName(int prefix, char asciiCh, int id, + EXTTYPE extType, const Common::String &suffix); + static Common::String formatResource(const Common::String &resName, const Common::String &hagFilename); + static Common::String formatAAName(int idx); +}; + +/** + * Derived file class + */ +class File : public Common::File { +public: + /** + * Constructor + */ + File() : Common::File() {} + + /** + * Constructor + */ + File(const Common::String &filename) { openFile(filename); } + + /** + * Opens the given file, throwing an error if it can't be opened + */ + void openFile(const Common::String &filename); +}; + +class SynchronizedList : public Common::Array<int> { +public: + /** + * Synchronize the list + */ + void synchronize(Common::Serializer &s); +}; + +} // End of namespace MADS + +#endif /* MADS_RESOURCES_H */ diff --git a/engines/mads/scene.cpp b/engines/mads/scene.cpp new file mode 100644 index 0000000000..e98648f009 --- /dev/null +++ b/engines/mads/scene.cpp @@ -0,0 +1,719 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "mads/scene.h" +#include "mads/compression.h" +#include "mads/mads.h" +#include "mads/dragonsphere/dragonsphere_scenes.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/phantom/phantom_scenes.h" + +namespace MADS { + +Scene::Scene(MADSEngine *vm) + : _vm(vm), _action(_vm), _depthSurface(vm), + _dirtyAreas(_vm), _dynamicHotspots(vm), _hotspots(vm), + _kernelMessages(vm), _sequences(vm), _sprites(vm), _spriteSlots(vm), + _textDisplay(vm), _userInterface(vm) { + _priorSceneId = 0; + _nextSceneId = 0; + _currentSceneId = 0; + _sceneLogic = nullptr; + _sceneInfo = nullptr; + _cyclingActive = false; + _cyclingThreshold = 0; + _cyclingDelay = 0; + _totalCycleColors = 0; + _depthStyle = 0; + _roomChanged = false; + _reloadSceneFlag = false; + _freeAnimationFlag = false; + _animationData = nullptr; + _activeAnimation = nullptr; + _textSpacing = -1; + _frameStartTime = 0; + _layer = LAYER_GUI; + _lookFlag = false; + _bandsRange = 0; + _scaleRange = 0; + _interfaceY = 0; + _spritesCount = 0; + _variant = 0; + + _paletteUsageF.push_back(PaletteUsage::UsageEntry(0xF)); + + // Set up a scene surface that maps to our physical screen drawing surface + _sceneSurface.init(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT, MADS_SCREEN_WIDTH, + _vm->_screen.getPixels(), Graphics::PixelFormat::createFormatCLUT8()); + + // Set up the verb list + _verbList.push_back(VerbInit(VERB_LOOK, VERB_THAT, PREP_NONE)); + _verbList.push_back(VerbInit(VERB_TAKE, VERB_THAT, PREP_NONE)); + _verbList.push_back(VerbInit(VERB_PUSH, VERB_THAT, PREP_NONE)); + _verbList.push_back(VerbInit(VERB_OPEN, VERB_THAT, PREP_NONE)); + _verbList.push_back(VerbInit(VERB_PUT, VERB_THIS, PREP_RELATIONAL)); + _verbList.push_back(VerbInit(VERB_TALKTO, VERB_THAT, PREP_NONE)); + _verbList.push_back(VerbInit(VERB_GIVE, VERB_THIS, PREP_TO)); + _verbList.push_back(VerbInit(VERB_PULL, VERB_THAT, PREP_NONE)); + _verbList.push_back(VerbInit(VERB_CLOSE, VERB_THAT, PREP_NONE)); + _verbList.push_back(VerbInit(VERB_THROW, VERB_THIS, PREP_TO)); +} + +Scene::~Scene() { + delete _sceneLogic; + delete _sceneInfo; +} + +void Scene::clearVocab() { + _activeVocabs.clear(); +} + +void Scene::addActiveVocab(int vocabId) { + if (activeVocabIndexOf(vocabId) == -1) { + assert(_activeVocabs.size() < 200); + _activeVocabs.push_back(vocabId); + } +} + +int Scene::activeVocabIndexOf(int vocabId) { + for (uint i = 0; i < _activeVocabs.size(); ++i) { + if (_activeVocabs[i] == vocabId) + return i; + } + + return -1; +} + +void Scene::clearSequenceList() { + _sequences.clear(); +} + +void Scene::clearMessageList() { + _kernelMessages.clear(); + _talkFont = FONT_CONVERSATION; + _textSpacing = -1; +} + +void Scene::loadSceneLogic() { + delete _sceneLogic; + + switch (_vm->getGameID()) { + case GType_RexNebular: + _sceneLogic = Nebular::SceneFactory::createScene(_vm); + break; + case GType_Dragonsphere: + _sceneLogic = Dragonsphere::SceneFactory::createScene(_vm); + break; + case GType_Phantom: + _sceneLogic = Phantom::SceneFactory::createScene(_vm); + break; + default: + error("Scene logic: Unknown game"); + } +} + +void Scene::loadScene(int sceneId, const Common::String &prefix, bool palFlag) { + // Store the previously active scene number and set the new one + _priorSceneId = _currentSceneId; + _currentSceneId = sceneId; + + _variant = 0; + if (palFlag) + _vm->_palette->resetGamePalette(18, 10); + + _spriteSlots.reset(false); + _sequences.clear(); + _kernelMessages.clear(); + _vm->_palette->_paletteUsage.load(&_scenePaletteUsage); + + int flags = SCENEFLAG_LOAD_SHADOW; + if (_vm->_dithering) + flags |= SCENEFLAG_DITHER; + + _sceneInfo = SceneInfo::init(_vm); + _sceneInfo->load(_currentSceneId, _variant, Common::String(), flags, + _depthSurface, _backgroundSurface); + + // Initialize palette animation for the scene + initPaletteAnimation(_sceneInfo->_paletteCycles, false); + + // Copy over nodes + _rails.load(_sceneInfo->_nodes, &_depthSurface, _sceneInfo->_depthStyle); + + // Load hotspots + loadHotspots(); + + // Load vocab + loadVocab(); + + // Load palette usage + _vm->_palette->_paletteUsage.load(&_paletteUsageF); + + // Load interface + flags = PALFLAG_RESERVED | ANIMFLAG_LOAD_BACKGROUND; + if (_vm->_dithering) + flags |= ANIMFLAG_DITHER; + if (_vm->_textWindowStill) + flags |= ANIMFLAG_LOAD_BACKGROUND_ONLY; + + _animationData = Animation::init(_vm, this); + DepthSurface depthSurface(_vm); + _animationData->load(_userInterface, depthSurface, prefix, flags, nullptr, nullptr); + + _vm->_palette->_paletteUsage.load(&_scenePaletteUsage); + + _bandsRange = _sceneInfo->_yBandsEnd - _sceneInfo->_yBandsStart; + _scaleRange = _sceneInfo->_maxScale - _sceneInfo->_minScale; + + _spriteSlots.reset(false); + _interfaceY = MADS_SCENE_HEIGHT; + _spritesCount = _sprites.size(); + + _userInterface.setup(_vm->_game->_screenObjects._inputMode); + + _vm->_game->_screenObjects._category = CAT_NONE; + _vm->_events->showCursor(); +} + +void Scene::loadHotspots() { + File f(Resources::formatName(RESPREFIX_RM, _currentSceneId, ".HH")); + MadsPack madsPack(&f); + bool isV2 = (_vm->getGameID() != GType_RexNebular); + + Common::SeekableReadStream *stream = madsPack.getItemStream(0); + int count = stream->readUint16LE(); + delete stream; + + stream = madsPack.getItemStream(1); + _hotspots.clear(); + for (int i = 0; i < count; ++i) + _hotspots.push_back(Hotspot(*stream, isV2)); + + delete stream; + f.close(); +} + +void Scene::loadVocab() { + // Add all the verbs to the active vocab list + for (uint i = 0; i < _verbList.size(); ++i) + addActiveVocab(_verbList[i]._id); + + // Load the vocabs for any object descriptions and custom actions + for (uint objIndex = 0; objIndex < _vm->_game->_objects.size(); ++objIndex) { + InventoryObject &io = _vm->_game->_objects[objIndex]; + addActiveVocab(io._descId); + + for (int vocabIndex = 0; vocabIndex <io._vocabCount; ++vocabIndex) { + addActiveVocab(io._vocabList[vocabIndex]._vocabId); + } + } + + // Load scene hotspot list vocabs and verbs + for (uint i = 0; i < _hotspots.size(); ++i) { + addActiveVocab(_hotspots[i]._vocabId); + if (_hotspots[i]._verbId) + addActiveVocab(_hotspots[i]._verbId); + } + + loadVocabStrings(); +} + +void Scene::loadVocabStrings() { + _vocabStrings.clear(); + File f("*VOCAB.DAT"); + Common::String msg; + + for (;;) { + char c = (char)f.readByte(); + if (f.eos()) break; + + if (c == '\0') { + _vocabStrings.push_back(msg); + msg = ""; + } else { + msg += c; + } + } + + f.close(); +} + +uint32 Scene::getVocabStringsCount() const { + return _vocabStrings.size(); +} + +void Scene::initPaletteAnimation(Common::Array<PaletteCycle> &palCycles, bool animFlag) { + // Initialize the animation palette and ticks list + _cycleTicks.clear(); + _paletteCycles.clear(); + + for (uint i = 0; i < palCycles.size(); ++i) { + _cycleTicks.push_back(_vm->_events->getFrameCounter()); + _paletteCycles.push_back(palCycles[i]); + } + + // Save the initial starting palette + Common::copy(&_vm->_palette->_mainPalette[0], &_vm->_palette->_mainPalette[PALETTE_SIZE], + &_vm->_palette->_cyclingPalette[0]); + + // Calculate total + _totalCycleColors = 0; + for (uint i = 0; i < _paletteCycles.size(); ++i) + _totalCycleColors += _paletteCycles[i]._colorCount; + + _cyclingThreshold = (_totalCycleColors > 16) ? 3 : 0; + _cyclingActive = animFlag; +} + +void Scene::animatePalette() { + byte rgb[3]; + + if (_cyclingActive) { + Scene::_cyclingDelay++; + if (_cyclingDelay >= _cyclingThreshold) { + uint32 frameCounter = _vm->_events->getFrameCounter(); + bool changesFlag = false; + for (uint16 idx = 0; idx < _paletteCycles.size(); idx++) { + if (frameCounter >= (_cycleTicks[idx] + _paletteCycles[idx]._ticks)) { + _cycleTicks[idx] = frameCounter; + int count = _paletteCycles[idx]._colorCount; + int first = _paletteCycles[idx]._firstColorIndex; + int listIndex = _paletteCycles[idx]._firstListColor; + changesFlag = true; + + if (count > 1) { + // Make a copy of the last color + byte *pSrc = &_vm->_palette->_cyclingPalette[first * 3]; + byte *pEnd = pSrc + count * 3; + Common::copy(pEnd - 3, pEnd, &rgb[0]); + + // Shift the cycle palette forward one entry + Common::copy_backward(pSrc, pEnd - 3, pEnd); + + // Move the saved color to the start of the cycle + Common::copy(&rgb[0], &rgb[3], pSrc); + + if (++listIndex >= count) + listIndex = 0; + } + + _paletteCycles[idx]._firstListColor = listIndex; + } + } + + if (changesFlag) { + int firstColor = _paletteCycles[0]._firstColorIndex; + byte *pSrc = &_vm->_palette->_cyclingPalette[firstColor * 3]; + _vm->_palette->setPalette(pSrc, firstColor, _totalCycleColors); + } + + _cyclingDelay = 0; + } + } +} + +bool Scene::getDepthHighBits(const Common::Point &pt) { + if (_sceneInfo->_depthStyle == 2) { + return 0; + } else { + const byte *p = _depthSurface.getBasePtr(pt.x, pt.y); + return (*p & 0x70) >> 4; + } +} + +void Scene::loop() { + while (!_vm->shouldQuit() && !_reloadSceneFlag && (_nextSceneId == _currentSceneId)) { + // Handle drawing a game frame + doFrame(); + + // TODO: Verify correctness of frame wait + _vm->_events->waitForNextFrame(); + + if (_vm->_dialogs->_pendingDialog != DIALOG_NONE && !_vm->_game->_trigger + && _vm->_game->_player._stepEnabled) + _reloadSceneFlag = true; + } +} + +void Scene::doFrame() { + Player &player = _vm->_game->_player; + bool flag = false; + + if (_action._selectedAction || !player._stepEnabled) { + _action.clear(); + _action._selectedAction = 0; + } + + if (!_vm->_game->_trigger && !player._trigger) { + // Refresh the dynamic hotspots if they've changed + if (_dynamicHotspots._changed) + _dynamicHotspots.refresh(); + + // Check all on-screen visual objects + _vm->_game->_screenObjects.check(player._stepEnabled && !player._needToWalk && + !_vm->_game->_fx); + } + + if (_action._selectedAction && player._stepEnabled && !player._needToWalk && + !_vm->_game->_trigger && !player._trigger) { + _action.startAction(); + if (_action._activeAction._verbId == Nebular::VERB_LOOK_AT) { + _action._activeAction._verbId = VERB_LOOK; + _action._savedFields._command = false; + } + + flag = true; + } + + if (flag || (_vm->_game->_trigger && _vm->_game->_triggerMode == SEQUENCE_TRIGGER_PREPARE)) { + doPreactions(); + } + + player.newWalk(); + if (!_vm->_game->_fx) + _frameStartTime = _vm->_events->getFrameCounter(); + + // Handle parser actions as well as game triggers + if ((_action._inProgress && !player._moving && !player._needToWalk && + (player._facing == player._turnToFacing) && !_vm->_game->_trigger) || + (_vm->_game->_trigger && (_vm->_game->_triggerMode == SEQUENCE_TRIGGER_PARSER))) { + doAction(); + } + + if (_currentSceneId != _nextSceneId) { + _freeAnimationFlag = true; + } else { + doSceneStep(); + checkKeyboard(); + + if (_currentSceneId != _nextSceneId) { + _freeAnimationFlag = true; + } else { + player.nextFrame(); + + // Cursor update code + updateCursor(); + + if (!_vm->_game->_trigger) { + // Handle any active sequences + _sequences.tick(); + + // Handle any active animation + if (_activeAnimation) + _activeAnimation->update(); + } + + // If the debugget flag is set, show the mouse position + int mouseTextIndex = 0; + if (_vm->_debugger->_showMousePos) { + Common::Point pt = _vm->_events->mousePos(); + Common::String msg = Common::String::format("(%d,%d)", pt.x, pt.y); + mouseTextIndex = _kernelMessages.add(Common::Point(5, 5), + 0x203, 0, 0, 1, msg); + } + + if (!_vm->_game->_trigger) { + if (_reloadSceneFlag || _currentSceneId != _nextSceneId) + _kernelMessages.reset(); + _kernelMessages.update(); + } + + _userInterface._uiSlots.draw(!_vm->_game->_fx, _vm->_game->_fx); + + // Write any text needed by the interface + if (_vm->_game->_fx) + _userInterface.drawTextElements(); + + // Draw any elements + drawElements((ScreenTransition)_vm->_game->_fx, _vm->_game->_fx); + + // Handle message updates + if (_vm->_game->_fx) { + uint32 priorTime = _vm->_game->_priorFrameTimer; + uint32 newTime = _vm->_events->getFrameCounter(); + _sequences.delay(newTime, priorTime); + _kernelMessages.delay(newTime, priorTime); + } + + if (_vm->_debugger->_showMousePos) + // Mouse position display isn't persistent, so remove it + _kernelMessages.remove(mouseTextIndex); + + // Original had a debugger check/call here to allow pausing after + // drawing each frame. Not implemented under ScummVM + } + } + + if (_vm->_game->_fx) + _cyclingActive = true; + _vm->_game->_fx = kTransitionNone; + + if (_freeAnimationFlag) + freeAnimation(); +} + +void Scene::drawElements(ScreenTransition transitionType, bool surfaceFlag) { + // Draw any sprite backgrounds + _spriteSlots.drawBackground(); + + // Set up dirty areas for any text display + _textDisplay.setDirtyAreas(); + + // Merge any identified dirty areas + _dirtyAreas.merge(1, DIRTY_AREAS_SIZE); + + // Copy background for the dirty areas to the screen + _dirtyAreas.copy(&_backgroundSurface, &_vm->_screen, _posAdjust); + + // Handle dirty areas for foreground objects + if (_vm->getGameID() == GType_RexNebular) // TODO: Implement for V2 games + _spriteSlots.setDirtyAreas(); + _textDisplay.setDirtyAreas2(); + _dirtyAreas.merge(1, DIRTY_AREAS_SIZE); + + // Draw sprites that have changed + if (_vm->getGameID() == GType_RexNebular) // TODO: Implement for V2 games + _spriteSlots.drawSprites(&_sceneSurface); + + // Draw text elements onto the view + _textDisplay.draw(&_vm->_screen); + + if (transitionType) { + // Fading in the screen + _vm->_screen.transition(transitionType, surfaceFlag); + _vm->_sound->startQueuedCommands(); + } else { + // Copy dirty areas to the screen + _dirtyAreas.copyToScreen(_vm->_screen._offset); + } + + _spriteSlots.cleanUp(); + _textDisplay.cleanUp(); +} + +void Scene::doPreactions() { + if (_vm->_game->_screenObjects._inputMode == kInputBuildingSentences || + _vm->_game->_screenObjects._inputMode == kInputLimitedSentences) { + _vm->_game->_triggerSetupMode = SEQUENCE_TRIGGER_PREPARE; + _action.checkAction(); + _sceneLogic->preActions(); + + if (_vm->_game->_triggerMode == SEQUENCE_TRIGGER_PREPARE) + _vm->_game->_trigger = 0; + } +} + +void Scene::doAction() { + bool flag = false; + + _vm->_game->_triggerSetupMode = SEQUENCE_TRIGGER_PARSER; + if ((_action._inProgress || _vm->_game->_trigger) && !_action._savedFields._commandError) { + _sceneLogic->actions(); + flag = !_action._inProgress; + } + + if (_vm->_game->_screenObjects._inputMode == kInputConversation) { + _action._inProgress = false; + } else { + if ((_action._inProgress || _vm->_game->_trigger) || + (!flag && _action._savedFields._commandError == flag)) { + _vm->_game->_sectionHandler->sectionPtr2(); + flag = !_action._inProgress; + } + + if ((_action._inProgress || _vm->_game->_trigger) && + (!flag || _action._savedFields._commandError == flag)) { + _vm->_game->doObjectAction(); + } + + if (!_action._savedFields._lookFlag) { + if (_action._inProgress) { + _action._savedFields._commandError = true; + _sceneLogic->postActions(); + } + + if (_action._inProgress) { + _action._savedFields._commandError = true; + _sceneLogic->unhandledAction(); + } + + if (_action._inProgress) + _vm->_game->unhandledAction(); + } + } + + _action._inProgress = false; + if (_vm->_game->_triggerMode == SEQUENCE_TRIGGER_PARSER) + _vm->_game->_trigger = 0; +} + +void Scene::doSceneStep() { + _vm->_game->_triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _sceneLogic->step(); + _vm->_game->_sectionHandler->step(); + _vm->_game->step(); + + if (_vm->_game->_triggerMode == SEQUENCE_TRIGGER_DAEMON) + _vm->_game->_trigger = 0; +} + +void Scene::checkKeyboard() { + if (_vm->_events->isKeyPressed()) { + Common::Event evt = _vm->_events->_pendingKeys.pop(); + _vm->_game->handleKeypress(evt); + } + + if ((_vm->_events->_mouseStatus & 3) == 3 && _vm->_game->_player._stepEnabled) { + _reloadSceneFlag = true; + _vm->_dialogs->_pendingDialog = DIALOG_GAME_MENU; + _action.clear(); + _action._selectedAction = 0; + } +} + +void Scene::loadAnimation(const Common::String &resName, int trigger) { + // WORKAROUND: If there's already a previous active animation used by the + // scene, then free it before we create the new one + if (_activeAnimation) + freeAnimation(); + + DepthSurface depthSurface(_vm); + UserInterface interfaceSurface(_vm); + + _activeAnimation = Animation::init(_vm, this); + _activeAnimation->load(interfaceSurface, depthSurface, resName, + _vm->_dithering ? ANIMFLAG_DITHER : 0, nullptr, nullptr); + _activeAnimation->startAnimation(trigger); +} + +void Scene::updateCursor() { + Player &player = _vm->_game->_player; + + CursorType cursorId = CURSOR_ARROW; + if (_action._interAwaiting == AWAITING_COMMAND && !_vm->_events->_rightMousePressed && + _vm->_game->_screenObjects._category == CAT_HOTSPOT) { + int idx = _vm->_game->_screenObjects._selectedObject - + _userInterface._categoryIndexes[CAT_HOTSPOT - 1]; + assert(idx >= 0); + + if (idx >= (int)_hotspots.size()) { + idx -= _hotspots.size(); + _vm->_events->_newCursorId = _dynamicHotspots[idx]._cursor; + } else { + idx = _hotspots.size() - idx - 1; + _vm->_events->_newCursorId = _hotspots[idx]._cursor; + } + + cursorId = _vm->_events->_newCursorId == CURSOR_NONE ? + CURSOR_ARROW : _vm->_events->_newCursorId; + } + + if (!player._stepEnabled) + cursorId = CURSOR_WAIT; + if (cursorId >= _vm->_events->_cursorSprites->getCount()) + cursorId = (CursorType)_vm->_events->_cursorSprites->getCount(); + _vm->_events->_newCursorId = cursorId; + + if (cursorId != _vm->_events->_cursorId) { + _vm->_events->setCursor(cursorId); + } +} + +void Scene::freeCurrentScene() { + if (_animationData) { + delete _animationData; + _animationData = nullptr; + } + if (_activeAnimation) { + delete _activeAnimation; + _activeAnimation = nullptr; + } + + _vm->_palette->_paletteUsage.load(nullptr); + _hotspots.clear(); + _backgroundSurface.free(); + _depthSurface.free(); + + delete _sceneInfo; + _sceneInfo = nullptr; +} + +void Scene::removeSprites() { + for (int idx = _sprites.size() - 1; idx >= _spritesCount; --idx) + _sprites.remove(idx); +} + +void Scene::changeVariant(int variant) { + _variant = variant; + _sceneInfo->loadCodes(_depthSurface, variant); + _spriteSlots.fullRefresh(); +} + +void Scene::resetScene() { + _vm->_game->clearQuotes(); + _spriteSlots.fullRefresh(true); + _sequences.clear(); +} + +void Scene::freeAnimation() { + if (_activeAnimation) { + Player &player = _vm->_game->_player; + + if (!_freeAnimationFlag) { + _spriteSlots.fullRefresh(true); + _sequences.scan(); + } + + // Refresh the player + if (player._visible) { + player._forceRefresh = true; + player.update(); + } + + // Remove any kernel messages in use by the animation + for (uint i = 0; i < _activeAnimation->_messages.size(); ++i) { + int msgIndex = _activeAnimation->_messages[i]._kernelMsgIndex; + if (msgIndex >= 0) + _kernelMessages.remove(msgIndex); + } + + // Delete the animation + delete _activeAnimation; + _activeAnimation = nullptr; + } + + _freeAnimationFlag = false; +} + +void Scene::synchronize(Common::Serializer &s) { + _action.synchronize(s); + _rails.synchronize(s); + _userInterface.synchronize(s); + s.syncAsByte(_reloadSceneFlag); + s.syncAsByte(_roomChanged); + s.syncAsUint16LE(_nextSceneId); + s.syncAsUint16LE(_priorSceneId); + _dynamicHotspots.synchronize(s); +} + +} // End of namespace MADS diff --git a/engines/mads/scene.h b/engines/mads/scene.h new file mode 100644 index 0000000000..407d70dc85 --- /dev/null +++ b/engines/mads/scene.h @@ -0,0 +1,251 @@ +/* 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. + * + */ + +#ifndef MADS_SCENE_H +#define MADS_SCENE_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/rect.h" +#include "mads/assets.h" +#include "mads/screen.h" +#include "mads/hotspots.h" +#include "mads/messages.h" +#include "mads/msurface.h" +#include "mads/scene_data.h" +#include "mads/animation.h" +#include "mads/rails.h" +#include "mads/sequence.h" +#include "mads/sprites.h" +#include "mads/user_interface.h" + +namespace MADS { + +class Scene { +private: + /** + * Return the index of a given Vocab in the active vocab list + */ + int activeVocabIndexOf(int vocabId); + + /** + * Secondary loading vocab list + */ + void loadVocabStrings(); + + /* + * Initializes the data for palette animation within the scene + */ + void initPaletteAnimation(Common::Array<PaletteCycle> &palCycles, bool animFlag); + + /** + * Handles a single frame within the game scene + */ + void doFrame(); + + void doPreactions(); + + void doAction(); + + /** + * Calls all the necessary step handlers for the current frame + */ + void doSceneStep(); + + /** + * Checks whether there's a pending keypress, and if so handles it. + */ + void checkKeyboard(); + + /** + * Checks for a highlighted hotspot, and updates the cursor accordingly + */ + void updateCursor(); +protected: + MADSEngine *_vm; +public: + SceneLogic *_sceneLogic; + MSurface _sceneSurface; + int _priorSceneId; + int _nextSceneId; + int _currentSceneId; + Common::Array<VerbInit> _verbList; + TextDisplayList _textDisplay; + SpriteSlots _spriteSlots; + SpriteSets _sprites; + DynamicHotspots _dynamicHotspots; + Common::Array<int> _activeVocabs; + SequenceList _sequences; + KernelMessages _kernelMessages; + Rails _rails; + Common::String _talkFont; + int _textSpacing; + Hotspots _hotspots; + DirtyAreas _dirtyAreas; + int _variant; + SceneInfo *_sceneInfo; + MSurface _backgroundSurface; + DepthSurface _depthSurface; + UserInterface _userInterface; + bool _cyclingActive; + int _cyclingThreshold; + int _cyclingDelay; + int _totalCycleColors; + Common::Array<uint32> _cycleTicks; + Common::Array<PaletteCycle> _paletteCycles; + Common::StringArray _vocabStrings; + Animation *_animationData; + Animation *_activeAnimation; + bool _freeAnimationFlag; + int _depthStyle; + int _bandsRange; + int _scaleRange; + int _interfaceY; + int _spritesCount; + MADSAction _action; + bool _roomChanged; + bool _reloadSceneFlag; + Common::Point _posAdjust; + uint32 _frameStartTime; + Layer _layer; + bool _lookFlag; + Common::Point _customDest; + Common::Array<PaletteUsage::UsageEntry> _paletteUsageF; + Common::Array<PaletteUsage::UsageEntry> _scenePaletteUsage; + + /** + * Constructor + */ + Scene(MADSEngine *vm); + + /** + * Destructor + */ + ~Scene(); + + /** + * Clear the vocabulary list + */ + void clearVocab(); + + /** + * Add a given vocab entry to the active list + */ + void addActiveVocab(int vocabId); + + /** + * Get the number of entries in the game's vocabulary + */ + uint32 getVocabStringsCount() const; + + /** + * Clear the sequence list + */ + void clearSequenceList(); + + /** + * Clear the message list + */ + void clearMessageList(); + + /** + * Loads the scene logic for a given scene + */ + void loadSceneLogic(); + + /** + * Loads the resources associated with the given scene + * @param sceneId Scene to load + * @param prefix Prefix to use for retrieving animation data + * @param palFlag Flag for whether to reset the high/lo palette areas + */ + void loadScene(int sceneId, const Common::String &prefix, bool palFlag); + + /** + * Loads the hotstpots for the scene + */ + void loadHotspots(); + + /** + * Loads the vocab list + */ + void loadVocab(); + + bool getDepthHighBits(const Common::Point &pt); + + /** + * Main scene loop + */ + void loop(); + + /** + * Draw all the elements onto the scene + */ + void drawElements(ScreenTransition transitionType, bool surfaceFlag); + + /** + * Handles cycling palette colors for the scene + */ + void animatePalette(); + + /** + * Load an animation + */ + void loadAnimation(const Common::String &resName, int trigger = 0); + + /** + * Returns a vocab entry + */ + Common::String getVocab(int vocabId) { return _vocabStrings[vocabId - 1]; } + + /** + * Clear the data for the currently loaded scene + */ + void freeCurrentScene(); + + /** + * Set the walk surface for a scene to a different variant + */ + void changeVariant(int variant); + + void resetScene(); + + /** + * Removes all the scene specific sprites fromt the sprites list, + * leaving any player sprites list in place at the start of the list. + */ + void removeSprites(); + + /** + * Frees any currently active animation for the scene + */ + void freeAnimation(); + + /** + * Synchronize the game + */ + void synchronize(Common::Serializer &s); +}; + +} // End of namespace MADS + +#endif /* MADS_SCENE_H */ diff --git a/engines/mads/scene_data.cpp b/engines/mads/scene_data.cpp new file mode 100644 index 0000000000..d53a668fd3 --- /dev/null +++ b/engines/mads/scene_data.cpp @@ -0,0 +1,463 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "mads/scene_data.h" +#include "mads/mads.h" +#include "mads/compression.h" +#include "mads/screen.h" +#include "mads/resources.h" +#include "mads/dragonsphere/dragonsphere_scenes.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/phantom/phantom_scenes.h" + +namespace MADS { + +KernelMessage::KernelMessage() { + _flags = 0; + _sequenceIndex = 0; + _color1 = 0; + _color2 = 0; + _msgOffset = 0; + _numTicks = 0; + _frameTimer2 = 0; + _frameTimer = 0; + _timeout = 0; + _trigger = 0; + _abortMode = SEQUENCE_TRIGGER_PARSER; + _actionDetails._verbId = VERB_NONE; + _actionDetails._objectNameId = 0; + _actionDetails._indirectObjectId = 0; + _textDisplayIndex = 0; +} + +/*------------------------------------------------------------------------*/ + +void ARTHeader::load(Common::SeekableReadStream *f, bool isV2) { + if (!isV2) { + // Read in dimensions of image + _width = f->readUint16LE(); + _height = f->readUint16LE(); + } + + // Read in palette information + int palCount = f->readUint16LE(); + for (int i = 0; i < palCount; ++i) { + RGB6 rgb; + rgb.load(f); + _palette.push_back(rgb); + } + f->skip(6 * (256 - palCount)); + + // Read palette animations + int cycleCount = f->readUint16LE(); + for (int i = 0; i < cycleCount; ++i) { + PaletteCycle cycle; + cycle._colorCount = f->readByte(); + cycle._firstListColor = f->readByte(); + cycle._firstColorIndex = f->readByte(); + cycle._ticks = f->readByte(); + + _paletteCycles.push_back(cycle); + } +} + +/*------------------------------------------------------------------------*/ + +void SceneInfo::SpriteInfo::load(Common::SeekableReadStream *f) { + f->skip(3); + _spriteSetIndex = f->readByte(); + f->skip(2); + _position.x = f->readSint16LE(); + _position.y = f->readSint16LE(); + _depth = f->readByte(); + _scale = f->readByte(); +} + +/*------------------------------------------------------------------------*/ + +SceneInfo::SceneInfo(MADSEngine *vm) : _vm(vm) { + _sceneId = 0; + _artFileNum = 0; + _depthStyle = 0; + _width = 0; + _height = 0; + _yBandsEnd = 0; + _yBandsStart = 0; + _maxScale = 0; + _minScale = 0; + _field4A = 0; + _usageIndex = 0; + for (int i = 0; i < 15; ++i) + _depthList[i] = 0; +} + +SceneInfo *SceneInfo::init(MADSEngine *vm) { + switch (vm->getGameID()) { + case GType_RexNebular: + return new Nebular::SceneInfoNebular(vm); + case GType_Dragonsphere: + return new Dragonsphere::SceneInfoDragonsphere(vm); + case GType_Phantom: + return new Phantom::SceneInfoPhantom(vm); + default: + error("SceneInfo: Unknown game"); + } + + return nullptr; +} + +void SceneInfo::load(int sceneId, int variant, const Common::String &resName, + int flags, DepthSurface &depthSurface, MSurface &bgSurface) { + bool sceneFlag = sceneId >= 0; + + // Figure out the resource to use + Common::String resourceName; + if (sceneFlag) { + resourceName = Resources::formatName(RESPREFIX_RM, sceneId, ".DAT"); + } else { + resourceName = "*" + Resources::formatResource(resName, resName); + } + + // Open the scene info resource for access + File infoFile(resourceName); + MadsPack infoPack(&infoFile); + + // Read in basic data + Common::SeekableReadStream *infoStream = infoPack.getItemStream(0); + if (_vm->getGameID() == GType_RexNebular) { + _sceneId = infoStream->readUint16LE(); + } else { + infoStream->skip(6); // actual scene ID (string) + _sceneId = sceneId; + } + + // TODO: The following isn't quite right for V2 games (it's all 0) + _artFileNum = infoStream->readUint16LE(); + _depthStyle = infoStream->readUint16LE(); + _width = infoStream->readUint16LE(); + _height = infoStream->readUint16LE(); + + // HACK for V2 games (for now) + if (_vm->getGameID() != GType_RexNebular) { + _width = 320; + _height = 156; + } + + infoStream->skip(24); + + int nodeCount = infoStream->readUint16LE(); + _yBandsEnd = infoStream->readUint16LE(); + _yBandsStart = infoStream->readUint16LE(); + _maxScale = infoStream->readUint16LE(); + _minScale = infoStream->readUint16LE(); + for (int i = 0; i < DEPTH_BANDS_SIZE; ++i) + _depthList[i] = infoStream->readUint16LE(); + _field4A = infoStream->readUint16LE(); + + // Load the set of objects that are associated with the scene + for (int i = 0; i < 20; ++i) { + WalkNode node; + node.load(infoStream); + + if (i < nodeCount) + _nodes.push_back(node); + } + + int spriteSetsCount = infoStream->readUint16LE(); + int spriteInfoCount = infoStream->readUint16LE(); + + // Load in sprite sets + Common::StringArray setNames; + for (int i = 0; i < 10; ++i) { + char name[64]; + infoStream->read(name, 64); + + if (i < spriteSetsCount) + setNames.push_back(Common::String(name)); + } + + // Load in sprite draw information + Common::Array<SpriteInfo> spriteInfo; + // TODO: The following isn't quite right for V2 games + if (_vm->getGameID() == GType_RexNebular) { + for (int i = 0; i < 50; ++i) { + SpriteInfo info; + info.load(infoStream); + + if (i < spriteInfoCount) + spriteInfo.push_back(info); + } + } + delete infoStream; + + int width = _width; + int height = _height; + + if (!bgSurface.getPixels()) { + bgSurface.setSize(width, height); + } + + if (_depthStyle == 2) + width >>= 2; + if (!depthSurface.getPixels()) { + depthSurface.setSize(width, height); + } + + if (_vm->getGameID() == GType_RexNebular) { + // Load the depth surface with the scene codes + Common::SeekableReadStream *depthStream = infoPack.getItemStream(variant + 1); + loadCodes(depthSurface, depthStream); + delete depthStream; + } + + infoFile.close(); + + if (_vm->getGameID() == GType_RexNebular) { + loadMadsV1Background(sceneId, resName, flags, bgSurface); + loadPalette(sceneId, _artFileNum, resName, flags, bgSurface); + } else { + loadMadsV2Background(sceneId, resName, flags, bgSurface); + loadPalette(sceneId, sceneId, resName, flags, bgSurface); + } + + Common::Array<SpriteAsset *> spriteSets; + Common::Array<int> usageList; + + // TODO: The following isn't quite right for V2 games + if (_vm->getGameID() == GType_RexNebular) { + for (uint i = 0; i < setNames.size(); ++i) { + Common::String setResName; + if (sceneFlag || resName.hasPrefix("*")) + setResName += "*"; + setResName += setNames[i]; + + SpriteAsset *sprites = new SpriteAsset(_vm, setResName, flags); + spriteSets.push_back(sprites); + usageList.push_back(sprites->_usageIndex); + } + } + + _vm->_palette->_paletteUsage.updateUsage(usageList, _usageIndex); + + for (uint i = 0; i < spriteInfo.size(); ++i) { + SpriteInfo &si = spriteInfo[i]; + SpriteAsset *asset = spriteSets[si._spriteSetIndex]; + assert(asset && _depthStyle != 2); + + MSprite *spr = asset->getFrame(asset->getCount() - 1); + bgSurface.copyFromScaled(spr, si._position, si._depth, &depthSurface, + si._scale, spr->getTransparencyIndex()); + } + + // Free the sprite sets + for (int i = (int)spriteSets.size() - 1; i >= 0; --i) { + _vm->_palette->_paletteUsage.resetPalFlags(spriteSets[i]->_usageIndex); + delete spriteSets[i]; + } +} + +void SceneInfo::loadPalette(int sceneId, int artFileNum, const Common::String &resName, int flags, MSurface &bgSurface) { + bool sceneFlag = sceneId >= 0; + Common::String resourceName; + bool isV2 = (_vm->getGameID() != GType_RexNebular); + Common::String extension = !isV2 ? ".ART" : ".TT"; + int paletteStream = !isV2 ? 0 : 2; + + // Get the ART resource + if (sceneFlag) { + resourceName = Resources::formatName(RESPREFIX_RM, artFileNum, extension); + } else { + resourceName = "*" + Resources::formatResource(resName, resName); + } + + // Load in the ART header and palette + File artFile(resourceName); + MadsPack artResource(&artFile); + Common::SeekableReadStream *stream = artResource.getItemStream(paletteStream); + + ARTHeader artHeader; + artHeader.load(stream, isV2); + delete stream; + + // Copy out the palette animation data + for (uint i = 0; i < artHeader._paletteCycles.size(); ++i) + _paletteCycles.push_back(artHeader._paletteCycles[i]); + + if (!(flags & 1)) { + if (!_vm->_palette->_paletteUsage.empty()) { + _vm->_palette->_paletteUsage.getKeyEntries(artHeader._palette); + _vm->_palette->_paletteUsage.prioritize(artHeader._palette); + } + + _usageIndex = _vm->_palette->_paletteUsage.process(artHeader._palette, + (flags & 0xF800) | 0x8000); + if (_usageIndex > 0) { + _vm->_palette->_paletteUsage.transform(artHeader._palette); + + for (uint i = 0; i < _paletteCycles.size(); ++i) { + byte listColor = _paletteCycles[i]._firstListColor; + _paletteCycles[i]._firstColorIndex = artHeader._palette[listColor]._palIndex; + } + } + } + + if (!(flags & 1)) { + // Translate the background to use the correct palette indexes + bgSurface.translate(artHeader._palette); + } +} + +void SceneInfo::loadMadsV1Background(int sceneId, const Common::String &resName, int flags, MSurface &bgSurface) { + bool sceneFlag = sceneId >= 0; + Common::String resourceName; + Common::SeekableReadStream *stream; + + // Get the ART resource + if (sceneFlag) { + resourceName = Resources::formatName(RESPREFIX_RM, _artFileNum, ".ART"); + } else { + resourceName = "*" + Resources::formatResource(resName, resName); + } + + // Load in the ART data + File artFile(resourceName); + MadsPack artResource(&artFile); + + // Read in the background surface data + assert(_width == bgSurface.w && _height == bgSurface.h); + stream = artResource.getItemStream(1); + stream->read(bgSurface.getPixels(), bgSurface.w * bgSurface.h); + + // Close the ART file + delete stream; + artFile.close(); +} + +void SceneInfo::loadMadsV2Background(int sceneId, const Common::String &resName, int flags, MSurface &bgSurface) { + Common::String tileMapResourceName = Resources::formatName(RESPREFIX_RM, sceneId, ".MM"); + File tileMapFile(tileMapResourceName); + MadsPack tileMapPack(&tileMapFile); + Common::SeekableReadStream *mapStream = tileMapPack.getItemStream(0); + + // Get the details of the tiles and map + mapStream->readUint32LE(); + int tileCountX = mapStream->readUint16LE(); + int tileCountY = mapStream->readUint16LE(); + int tileWidthMap = mapStream->readUint16LE(); + int tileHeightMap = mapStream->readUint16LE(); + int screenWidth = mapStream->readUint16LE(); + int screenHeight = mapStream->readUint16LE(); + int tileCountMap = tileCountX * tileCountY; + delete mapStream; + + // Obtain tile map information + typedef Common::List<Common::SharedPtr<MSurface> > TileSetList; + typedef TileSetList::iterator TileSetIterator; + TileSetList tileSet; + uint16 *tileMap = new uint16[tileCountMap]; + mapStream = tileMapPack.getItemStream(1); + for (int i = 0; i < tileCountMap; ++i) + tileMap[i] = mapStream->readUint16LE(); + delete mapStream; + tileMapFile.close(); + + // -------------------------------------------------------------------------------- + + // Tile data, which needs to be kept compressed, as the tile map offsets refer to + // the compressed data. Each tile is then uncompressed separately + Common::String tileDataResourceName = Resources::formatName(RESPREFIX_RM, sceneId, ".TT"); + File tileDataFile(tileDataResourceName); + MadsPack tileDataPack(&tileDataFile); + Common::SeekableReadStream *tileDataUncomp = tileDataPack.getItemStream(0); + + // Validate that the data matches between the tiles and tile map file and is valid + int tileCount = tileDataUncomp->readUint16LE(); + int tileWidth = tileDataUncomp->readUint16LE(); + int tileHeight = tileDataUncomp->readUint16LE(); + delete tileDataUncomp; + assert(tileCountMap == tileCount); + assert(tileWidth == tileWidthMap); + assert(tileHeight == tileHeightMap); + assert(screenWidth == _width); + assert(screenHeight <= _height); + + // -------------------------------------------------------------------------------- + + // Get tile data + + tileDataUncomp = tileDataPack.getItemStream(1); + FabDecompressor fab; + uint32 compressedTileDataSize = 0; + + for (int i = 0; i < tileCount; i++) { + tileDataUncomp->seek(i * 4, SEEK_SET); + uint32 tileOfs = tileDataUncomp->readUint32LE(); + MSurface* newTile = new MSurface(tileWidth, tileHeight); + + if (i == tileCount - 1) + compressedTileDataSize = tileDataFile.size() - tileOfs; + else + compressedTileDataSize = tileDataUncomp->readUint32LE() - tileOfs; + + //debugCN(kDebugGraphics, "Tile: %i, compressed size: %i\n", i, compressedTileDataSize); + + newTile->empty(); + + byte *compressedTileData = new byte[compressedTileDataSize]; + + tileDataFile.seek(tileDataPack.getDataOffset() + tileOfs, SEEK_SET); + tileDataFile.read(compressedTileData, compressedTileDataSize); + + fab.decompress(compressedTileData, compressedTileDataSize, (byte*)newTile->getPixels(), tileWidth * tileHeight); + tileSet.push_back(TileSetList::value_type(newTile)); + delete[] compressedTileData; + } + + delete tileDataUncomp; + + // -------------------------------------------------------------------------------- + + // Loop through the mapping data to place the tiles on the screen + + uint16 *tIndex = &tileMap[0]; + for (int y = 0; y < tileCountY; y++) { + for (int x = 0; x < tileCountX; x++) { + int tileIndex = *tIndex++; + assert(tileIndex < tileCount); + TileSetIterator tile = tileSet.begin(); + for (int i = 0; i < tileIndex; i++) + ++tile; + ((*tile).get())->copyTo(&bgSurface, Common::Point(x * tileWidth, y * tileHeight)); + } + } + tileSet.clear(); + tileDataFile.close(); +} + +/*------------------------------------------------------------------------*/ + +SceneLogic::SceneLogic(MADSEngine *vm) : _vm(vm) { + _scene = &_vm->_game->_scene; +} + +} // End of namespace MADS diff --git a/engines/mads/scene_data.h b/engines/mads/scene_data.h new file mode 100644 index 0000000000..783a9ab8a9 --- /dev/null +++ b/engines/mads/scene_data.h @@ -0,0 +1,224 @@ +/* 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. + * + */ + +#ifndef MADS_SCENE_DATA_H +#define MADS_SCENE_DATA_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/serializer.h" +#include "common/str.h" +#include "common/str-array.h" +#include "common/rect.h" +#include "mads/action.h" +#include "mads/assets.h" +#include "mads/events.h" +#include "mads/game_data.h" +#include "mads/hotspots.h" +#include "mads/messages.h" +#include "mads/rails.h" +#include "mads/user_interface.h" + +namespace MADS { + +class MADSEngine; +class Scene; +class SpriteSlot; + +#define MADS_INTERFACE_HEIGHT 44 +#define MADS_SCENE_HEIGHT 156 + +#define DEPTH_BANDS_SIZE 15 + +#define SPRITE_SLOTS_MAX_SIZE 50 +#define TEXT_DISPLAY_MAX_SIZE 40 +#define DIRTY_AREAS_SIZE (SPRITE_SLOTS_MAX_SIZE + TEXT_DISPLAY_MAX_SIZE) + +enum { + SCENEFLAG_DITHER = 0x01, // Dither to 16 colors + SCENEFLAG_LOAD_SHADOW = 0x10 // Load hard shadows +}; + +class VerbInit { +public: + int _id; + VerbType _verbType; + PrepType _prepType; + + VerbInit() {} + VerbInit(int id, VerbType verbType, PrepType prepType) + : _id(id), _verbType(verbType), _prepType(prepType) { + } +}; + +class SceneLogic { +protected: + MADSEngine *_vm; + Scene *_scene; +public: + /** + * Constructor + */ + SceneLogic(MADSEngine *vm); + + /** + * Destructor + */ + virtual ~SceneLogic() {} + + /** + * Called to initially setup a scene + */ + virtual void setup() = 0; + + /** + * Called as the scene is entered (made active) + */ + virtual void enter() = 0; + + /** + * Called one per frame + */ + virtual void step() {} + + /** + * Called before an action is started + */ + virtual void preActions() {} + + /** + * Handles scene actions + */ + virtual void actions() = 0; + + /** + * Post-action handling + */ + virtual void postActions() {} + + /** + * Unhandled action handling + */ + virtual void unhandledAction() {} + + /** + * Synchronize any local data for the scene + */ + virtual void synchronize(Common::Serializer &s) {} +}; + +struct ARTHeader { + int _width; + int _height; + Common::Array<RGB6> _palette; + Common::Array<PaletteCycle> _paletteCycles; + + void load(Common::SeekableReadStream *f, bool isV2); +}; + +/** + * Handles general data for a given scene + */ +class SceneInfo { + class SpriteInfo { + public: + int _spriteSetIndex; + Common::Point _position; + int _depth; + int _scale; + + void load(Common::SeekableReadStream *f); + }; +protected: + MADSEngine *_vm; + + /** + * Constructor + */ + SceneInfo(MADSEngine *vm); +public: + int _sceneId; + int _artFileNum; + int _depthStyle; + int _width; + int _height; + + int _yBandsEnd; + int _yBandsStart; + int _maxScale; + int _minScale; + int _depthList[DEPTH_BANDS_SIZE]; + int _field4A; // Useless field ? + + int _usageIndex; + Common::Array<PaletteCycle> _paletteCycles; + WalkNodeList _nodes; +public: + /** + * Destructor + */ + virtual ~SceneInfo() {} + + /** + * Instantiates the class + */ + static SceneInfo *init(MADSEngine *vm); + + /** + * loads the data + */ + void load(int sceneId, int variant, const Common::String &resName, int flags, + DepthSurface &depthSurface, MSurface &bgSurface); + + /** + * Loads the palette for a scene + */ + void loadPalette(int sceneId, int artFileNum, const Common::String &resName, int flags, MSurface &bgSurface); + + /** + * Loads a V1 game background + */ + void loadMadsV1Background(int sceneId, const Common::String &resName, int flags, MSurface &bgSurface); + + /** + * Loads a V2 game background + */ + void loadMadsV2Background(int sceneId, const Common::String &resName, int flags, MSurface &bgSurface); + + /** + * Loads the given surface with depth information of a given scene + * @param depthSurface Depth/walk surface + * @param variant Variant number to load + */ + virtual void loadCodes(MSurface &depthSurface, int variant) = 0; + + /** + * Loads the given surface with depth information of a given scene + * @param depthSurface Depth/walk surface + * @param stream Stream to load the data from + */ + virtual void loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream) = 0; +}; + +} // End of namespace MADS + +#endif /* MADS_SCENE_DATA_H */ diff --git a/engines/mads/screen.cpp b/engines/mads/screen.cpp new file mode 100644 index 0000000000..91aa3abdb0 --- /dev/null +++ b/engines/mads/screen.cpp @@ -0,0 +1,642 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "mads/mads.h" +#include "mads/game.h" +#include "mads/screen.h" +#include "mads/palette.h" +#include "mads/user_interface.h" + +namespace MADS { + +MADSEngine *DirtyArea::_vm = nullptr; + +DirtyArea::DirtyArea() { + _active = false; + _textActive = false; + _mergedArea = nullptr; +} + +void DirtyArea::setArea(int width, int height, int maxWidth, int maxHeight) { + if (_bounds.left % 2) { + --_bounds.left; + ++width; + } + + if (_bounds.left < 0) + _bounds.left = 0; + else if (_bounds.left > maxWidth) + _bounds.left = maxWidth; + int right = _bounds.left + width; + if (right < 0) + right = 0; + if (right > maxWidth) + right = maxWidth; + + _bounds.right = right; + + if (_bounds.top < 0) + _bounds.top = 0; + else if (_bounds.top > maxHeight) + _bounds.top = maxHeight; + int bottom = _bounds.top + height; + if (bottom < 0) + bottom = 0; + if (bottom > maxHeight) + bottom = maxHeight; + + _bounds.bottom = bottom; + _active = true; +} + + +void DirtyArea::setSpriteSlot(const SpriteSlot *spriteSlot) { + int width, height; + Scene &scene = _vm->_game->_scene; + + if (spriteSlot->_flags == IMG_REFRESH) { + // Special entry to refresh the entire screen + _bounds.left = 0; + _bounds.top = 0; + width = MADS_SCREEN_WIDTH; + height = MADS_SCENE_HEIGHT; + } else { + // Standard sprite slots + _bounds.left = spriteSlot->_position.x - scene._posAdjust.x; + _bounds.top = spriteSlot->_position.y - scene._posAdjust.y; + + SpriteAsset &spriteSet = *scene._sprites[spriteSlot->_spritesIndex]; + MSprite *frame = spriteSet.getFrame(ABS(spriteSlot->_frameNumber) - 1); + + if (spriteSlot->_scale == -1) { + width = frame->w; + height = frame->h; + } else { + width = frame->w * spriteSlot->_scale / 100; + height = frame->h * spriteSlot->_scale / 100; + + _bounds.left -= width / 2; + _bounds.top += -(height - 1); + } + } + + setArea(width, height, MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT); +} + +void DirtyArea::setTextDisplay(const TextDisplay *textDisplay) { + _bounds.left = textDisplay->_bounds.left; + _bounds.top = textDisplay->_bounds.top; + + setArea(textDisplay->_bounds.width(), textDisplay->_bounds.height(), + MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT); +} + +void DirtyArea::setUISlot(const UISlot *slot) { + int type = slot->_flags; + if (type <= IMG_UPDATE_ONLY) + type += -IMG_UPDATE_ONLY; + if (type >= 0x40) + type &= ~0x40; + + MSurface &intSurface = _vm->_game->_scene._userInterface; + switch (type) { + case IMG_REFRESH: + _bounds.left = 0; + _bounds.top = 0; + setArea(intSurface.w, intSurface.h, intSurface.w, intSurface.h); + break; + + case IMG_OVERPRINT: + _bounds.left = slot->_position.x; + _bounds.top = slot->_position.y; + _bounds.setWidth(slot->_width); + _bounds.setHeight(slot->_height); + setArea(slot->_width, slot->_height, intSurface.w, intSurface.h); + break; + + default: { + SpriteAsset *asset = _vm->_game->_scene._sprites[slot->_spritesIndex]; + MSprite *frame = asset->getFrame(slot->_frameNumber - 1); + int w = frame->w; + int h = frame->h; + + if (slot->_segmentId == IMG_SPINNING_OBJECT) { + _bounds.left = slot->_position.x; + _bounds.top = slot->_position.y; + } else { + _bounds.left = slot->_position.x + w / 2; + _bounds.top = slot->_position.y - h + 1; + } + + setArea(w, h, intSurface.w, intSurface.h); + break; + } + } +} + +/*------------------------------------------------------------------------*/ + +DirtyAreas::DirtyAreas(MADSEngine *vm) : _vm(vm) { + DirtyArea::_vm = vm; + + for (int i = 0; i < DIRTY_AREAS_SIZE; ++i) { + DirtyArea rec; + rec._active = false; + push_back(rec); + } +} + +void DirtyAreas::merge(int startIndex, int count) { + if (startIndex >= count) + return; + + for (int outerCtr = startIndex - 1, idx = 0; idx < count; ++outerCtr, ++idx) { + if (!(*this)[outerCtr]._active) + continue; + + for (int innerCtr = outerCtr + 1; innerCtr < count; ++innerCtr) { + if (!(*this)[innerCtr]._active || !intersects(outerCtr, innerCtr)) + continue; + + if ((*this)[outerCtr]._textActive && (*this)[innerCtr]._textActive) + mergeAreas(innerCtr, outerCtr); + } + } +} + +/** +* Returns true if two dirty areas intersect +*/ +bool DirtyAreas::intersects(int idx1, int idx2) { + return (*this)[idx1]._bounds.intersects((*this)[idx2]._bounds); +} + +void DirtyAreas::mergeAreas(int idx1, int idx2) { + DirtyArea &da1 = (*this)[idx1]; + DirtyArea &da2 = (*this)[idx2]; + + da1._bounds.extend(da2._bounds); + + da2._active = false; + da2._mergedArea = &da1; + da1._textActive = true; +} + +void DirtyAreas::copy(MSurface *srcSurface, MSurface *destSurface, const Common::Point &posAdjust) { + for (uint i = 0; i < size(); ++i) { + const Common::Rect &srcBounds = (*this)[i]._bounds; + + // Check if this is a sane rectangle before attempting to create it + if (srcBounds.left >= srcBounds.right || srcBounds.top >= srcBounds.bottom) + continue; + + Common::Rect bounds(srcBounds.left + posAdjust.x, srcBounds.top + posAdjust.y, + srcBounds.right + posAdjust.x, srcBounds.bottom + posAdjust.y); + + if ((*this)[i]._active && bounds.isValidRect()) { + srcSurface->copyTo(destSurface, bounds, Common::Point(bounds.left, bounds.top)); + } + } +} + +void DirtyAreas::copyToScreen(const Common::Point &posAdjust) { + for (uint i = 0; i < size(); ++i) { + const Common::Rect &srcBounds = (*this)[i]._bounds; + + // Check if this is a sane rectangle before attempting to create it + if (srcBounds.left >= srcBounds.right || srcBounds.top >= srcBounds.bottom) + continue; + + Common::Rect bounds(srcBounds.left + posAdjust.x, srcBounds.top + posAdjust.y, + srcBounds.right + posAdjust.x, srcBounds.bottom + posAdjust.y); + + if ((*this)[i]._active && (*this)[i]._bounds.isValidRect()) { + _vm->_screen.copyRectToScreen(bounds); + } + } +} + +void DirtyAreas::reset() { + for (uint i = 0; i < size(); ++i) + (*this)[i]._active = false; +} + +/*------------------------------------------------------------------------*/ + +ScreenObject::ScreenObject() { + _category = CAT_NONE; + _descId = 0; + _layer = 0; + _active = false; +} + +/*------------------------------------------------------------------------*/ + +ScreenObjects::ScreenObjects(MADSEngine *vm) : _vm(vm) { + _objectY = -1; + _forceRescan = false; + _inputMode = kInputBuildingSentences; + _v7FED6 = 0; + _v8332A = 0; + _category = CAT_NONE; + _spotId = 0; + _released = false; + _uiCount = 0; + _selectedObject = -1; + _eventFlag = false; + _baseTime = 0; +} + +void ScreenObjects::add(const Common::Rect &bounds, Layer layer, ScrCategory category, int descId) { + //assert(size() < 100); + + ScreenObject so; + so._bounds = bounds; + so._category = category; + so._descId = descId; + so._layer = layer; + so._active = true; + + push_back(so); +} + +void ScreenObjects::check(bool scanFlag) { + Scene &scene = _vm->_game->_scene; + UserInterface &userInterface = scene._userInterface; + + if (!_vm->_events->_mouseButtons || _inputMode != kInputBuildingSentences) + _vm->_events->_rightMousePressed = false; + + if ((_vm->_events->_mouseMoved || userInterface._scrollbarActive + || _v8332A || _forceRescan) && scanFlag) { + _category = CAT_NONE; + _selectedObject = scanBackwards(_vm->_events->currentPos(), LAYER_GUI); + if (_selectedObject > 0) { + ScreenObject &scrObject = (*this)[_selectedObject]; + _category = (ScrCategory)(scrObject._category & 7); + _spotId = scrObject._descId; + } + + // Handling for easy mouse + ScrCategory category = scene._userInterface._category; + if (_vm->_easyMouse && _vm->_events->_mouseButtons && category != _category + && scene._userInterface._category != CAT_NONE) { + _released = true; + if (category >= CAT_COMMAND && category <= CAT_TALK_ENTRY) { + elementHighlighted(); + } + + scene._action.checkActionAtMousePos(); + } + + //_released = _vm->_events->_mouseReleased; + if (_vm->_events->_vD2 || (_vm->_easyMouse && !_vm->_events->_mouseStatusCopy)) + scene._userInterface._category = _category; + + if (!_vm->_events->_mouseButtons || _vm->_easyMouse) { + if (userInterface._category >= CAT_COMMAND && userInterface._category <= CAT_TALK_ENTRY) { + elementHighlighted(); + } + } + + if (_vm->_events->_mouseButtons || (_vm->_easyMouse && scene._action._interAwaiting > AWAITING_COMMAND + && scene._userInterface._category == CAT_INV_LIST) || + (_vm->_easyMouse && scene._userInterface._category == CAT_HOTSPOT)) { + scene._action.checkActionAtMousePos(); + } + + if (_vm->_events->_mouseReleased) { + scene._action.leftClick(); + scene._userInterface._category = CAT_NONE; + } + + if (_vm->_events->_mouseButtons || _vm->_easyMouse || userInterface._scrollbarActive) + scene._userInterface.updateInventoryScroller(); + + if (_vm->_events->_mouseButtons || _vm->_easyMouse) + scene._action.set(); + + _forceRescan = false; + } + + scene._action.refresh(); + + uint32 currentTicks = _vm->_events->getFrameCounter(); + if (currentTicks >= _baseTime) { + // Check the user interface slots to see if there's any slots that need to be expired + UISlots &uiSlots = userInterface._uiSlots; + for (uint idx = 0; idx < uiSlots.size(); ++idx) { + UISlot &slot = uiSlots[idx]; + + if (slot._flags != IMG_REFRESH && slot._flags > IMG_UPDATE_ONLY + && slot._segmentId != IMG_SPINNING_OBJECT) + slot._flags = IMG_ERASE; + } + + // Any background animation in the user interface + userInterface.doBackgroundAnimation(); + + // Handle animating the selected inventory item + userInterface.inventoryAnim(); + + // Set the base time + _baseTime = currentTicks + 6; + } +} + +int ScreenObjects::scanBackwards(const Common::Point &pt, int layer) { + for (int i = (int)size(); i >= 1; --i) { + ScreenObject &sObj = (*this)[i]; + if (sObj._active && sObj._bounds.contains(pt) && sObj._layer == layer) + return i; + } + + // Entry not found + return 0; +} + +void ScreenObjects::elementHighlighted() { + Scene &scene = _vm->_game->_scene; + UserInterface &userInterface = scene._userInterface; + Common::Array<int> &invList = _vm->_game->_objects._inventoryList; + MADSAction &action = scene._action; + int varA; + int topIndex; + int *idxP; + int var4; + int index; + int indexEnd = -1; + int var8 = 0; + int uiCount; + + switch (userInterface._category) { + case CAT_COMMAND: + index = 10; + indexEnd = 9; + varA = 5; + topIndex = 0; + idxP = !_vm->_events->_rightMousePressed ? &userInterface._highlightedCommandIndex : + &userInterface._selectedActionIndex; + + if (_vm->_events->_rightMousePressed && userInterface._selectedItemVocabIdx >= 0) + userInterface.updateSelection(CAT_INV_VOCAB, -1, &userInterface._selectedItemVocabIdx); + + var4 = _released && !_vm->_events->_rightMousePressed ? 1 : 0; + break; + + case CAT_INV_LIST: + userInterface.scrollInventory(); + + index = MIN((int)invList.size() - userInterface._inventoryTopIndex, 5); + indexEnd = invList.size() - 1; + varA = 0; + topIndex = userInterface._inventoryTopIndex; + idxP = &userInterface._highlightedInvIndex; + var4 = (!_released || (_vm->_events->_mouseButtons && action._interAwaiting == 1)) ? 0 : 1; + break; + + case CAT_INV_VOCAB: + if (userInterface._selectedInvIndex >= 0) { + InventoryObject &invObject = _vm->_game->_objects.getItem( + userInterface._selectedInvIndex); + index = invObject._vocabCount; + indexEnd = index - 1; + } else { + index = 0; + } + + varA = 0; + topIndex = 0; + idxP = _vm->_events->_rightMousePressed ? &userInterface._selectedItemVocabIdx : &userInterface._highlightedItemVocabIndex; + + if (_vm->_events->_rightMousePressed && userInterface._selectedActionIndex >= 0) + userInterface.updateSelection(CAT_COMMAND, -1, &userInterface._selectedActionIndex); + + var4 = _released && !_vm->_events->_rightMousePressed ? 1 : 0; + break; + + case CAT_INV_ANIM: + index = 1; + indexEnd = invList.size() - 1; + varA = 0; + topIndex = userInterface._selectedInvIndex; + idxP = &var8; + var4 = -1; + break; + + case CAT_TALK_ENTRY: + index = userInterface._talkStrings.size(); + indexEnd = index - 1; + varA = 0; + topIndex = 0; + idxP = &userInterface._highlightedCommandIndex; + var4 = -1; + break; + + default: + uiCount = size() - _uiCount; + index = uiCount + scene._hotspots.size(); + indexEnd = index - 1; + varA = 0; + topIndex = 0; + idxP = &var8; + var4 = -1; + break; + } + + int newIndex = -1; + int catIndex = userInterface._categoryIndexes[userInterface._category - 1]; + int newX = 0, newY = 0; + Common::Point currentPos = _vm->_events->currentPos(); + + for (int idx = 0; idx < index && newIndex < 0; ++idx) { + int scrObjIndex = (_category == CAT_HOTSPOT) ? catIndex - idx + index - 1 : + catIndex + idx; + + ScreenObject &scrObject = (*this)[scrObjIndex]; + if (!scrObject._active) + continue; + + const Common::Rect &bounds = scrObject._bounds; + newY = MAX((int)bounds.bottom, newY); + newX = MAX((int)bounds.left, newX); + + if (currentPos.y >= bounds.top && currentPos.y < bounds.bottom) { + if (var4) { + if (currentPos.x >= bounds.left && currentPos.x < bounds.right) { + // Cursor is inside hotspot bounds + newIndex = scrObjIndex - catIndex; + if (_category == CAT_HOTSPOT && newIndex < (int)scene._hotspots.size()) + newIndex = scene._hotspots.size() - newIndex - 1; + } + } else if (!varA) { + newIndex = idx; + } else if (varA <= idx) { + if (currentPos.x > bounds.left) + newIndex = idx; + } else { + if (currentPos.x < bounds.right) + newIndex = idx; + } + } + } + + if (newIndex == -1 && index > 0 && !var4) { + if (_vm->_events->currentPos().y <= newY) { + newIndex = 0; + if (varA && _vm->_events->currentPos().x >= newX) + newIndex = varA; + } else { + newIndex = index - 1; + } + } + + if (newIndex >= 0) + newIndex = MIN(newIndex + topIndex, indexEnd); + + action._pickedWord = newIndex; + + if (_category == CAT_INV_LIST || _category == CAT_INV_ANIM) { + if (action._interAwaiting == 1 && newIndex >= 0 && _released && + (!_vm->_events->_mouseReleased || !_vm->_easyMouse)) + newIndex = -1; + } + + if (_released && !_vm->_events->_rightMousePressed && + (_vm->_events->_mouseReleased || !_vm->_easyMouse)) + newIndex = -1; + + if (_category != CAT_HOTSPOT && _category != CAT_INV_ANIM) + userInterface.updateSelection(_category, newIndex, idxP); +} + +void ScreenObjects::setActive(ScrCategory category, int descId, bool active) { + for (uint idx = 1; idx < size(); ++idx) { + ScreenObject &sObj = (*this)[idx]; + if (sObj._category == category && sObj._descId == descId) + sObj._active = active; + } +} + +void ScreenObjects::synchronize(Common::Serializer &s) { + s.syncAsSint16LE(_selectedObject); + s.syncAsSint16LE(_category); +} + +/*------------------------------------------------------------------------*/ + +ScreenSurface::ScreenSurface() { + _shakeCountdown = -1; + _random = 0x4D2; +} + +void ScreenSurface::init() { + setSize(g_system->getWidth(), g_system->getHeight()); +} + +void ScreenSurface::copyRectToScreen(const Common::Point &destPos, + const Common::Rect &bounds) { + const byte *buf = getBasePtr(destPos.x, destPos.y); + + if (bounds.width() != 0 && bounds.height() != 0) + g_system->copyRectToScreen(buf, this->pitch, bounds.left, bounds.top, + bounds.width(), bounds.height()); +} + +void ScreenSurface::copyRectToScreen(const Common::Rect &bounds) { + copyRectToScreen(Common::Point(bounds.left, bounds.top), bounds); +} + +void ScreenSurface::updateScreen() { + if (_shakeCountdown >= 0) { + _random = _random * 5 + 1; + int offset = (_random >> 8) & 3; + if (_shakeCountdown-- <= 0) + offset = 0; + + // Copy the screen with the left hand hide side of the screen of a given + // offset width shown at the very right. The offset changes to give + // an effect of shaking the screen + offset *= 4; + const byte *buf = getBasePtr(offset, 0); + g_system->copyRectToScreen(buf, this->pitch, 0, 0, + this->pitch - offset, this->h); + if (offset > 0) + g_system->copyRectToScreen(this->pixels, this->pitch, + this->pitch - offset, 0, offset, this->h); + } + + g_system->updateScreen(); +} + +void ScreenSurface::transition(ScreenTransition transitionType, bool surfaceFlag) { + Palette &pal = *_vm->_palette; + byte palData[PALETTE_SIZE]; + + switch (transitionType) { + case kTransitionFadeIn: + case kTransitionFadeOutIn: + Common::fill(&pal._colorValues[0], &pal._colorValues[3], 0); + Common::fill(&pal._colorFlags[0], &pal._colorFlags[3], false); + + if (transitionType == kTransitionFadeOutIn) { + // Fade out + pal.getFullPalette(palData); + pal.fadeOut(palData, nullptr, 0, PALETTE_COUNT, 0, 0, 1, 16); + } + + // Reset palette to black + Common::fill(&palData[0], &palData[PALETTE_SIZE], 0); + pal.setFullPalette(palData); + + copyRectToScreen(getBounds()); + pal.fadeIn(palData, pal._mainPalette, 0, 256, 0, 1, 1, 16); + break; + + case kTransitionBoxInBottomLeft: + case kTransitionBoxInBottomRight: + case kTransitionBoxInTopLeft: + case kTransitionBoxInTopRight: + error("TODO: transition"); + break; + + case kTransitionPanLeftToRight: + case kTransitionPanRightToLeft: + error("TODO: transition"); + + case kTransitionCircleIn1: + case kTransitionCircleIn2: + case kTransitionCircleIn3: + case kTransitionCircleIn4: + error("TODO circle transition"); + + case kCenterVertTransition: + error("TODO: center vert transition"); + + default: + // Quick transitions + break; + } +} + +} // End of namespace MADS diff --git a/engines/mads/screen.h b/engines/mads/screen.h new file mode 100644 index 0000000000..a3653d6d62 --- /dev/null +++ b/engines/mads/screen.h @@ -0,0 +1,240 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 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. + * + */ + +#ifndef MADS_SCREEN_H +#define MADS_SCREEN_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "mads/msurface.h" +#include "mads/action.h" + +namespace MADS { + +#define MADS_SCREEN_WIDTH 320 +#define MADS_SCREEN_HEIGHT 200 + +enum Layer { + LAYER_GUI = 19 +}; + +enum ScreenTransition { + kTransitionNone = 0, + kTransitionFadeIn, kTransitionFadeOutIn, + kTransitionBoxInBottomLeft, kTransitionBoxInBottomRight, + kTransitionBoxInTopLeft, kTransitionBoxInTopRight, + kTransitionPanLeftToRight, kTransitionPanRightToLeft, + kTransitionCircleIn1, kTransitionCircleIn2, + kTransitionCircleIn3, kTransitionCircleIn4, + kVertTransition1, kVertTransition2, kVertTransition3, + kVertTransition4, kVertTransition5, kVertTransition6, + kVertTransition7, kCenterVertTransition +}; + +enum InputMode { + kInputBuildingSentences = 0, // Normal sentence building + kInputConversation = 1, // Conversation mode + kInputLimitedSentences = 2 // Use only scene hotspots +}; + +class SpriteSlot; +class TextDisplay; +class UISlot; + +class DirtyArea { +private: + static MADSEngine *_vm; + friend class DirtyAreas; +public: + Common::Rect _bounds; + bool _textActive; + bool _active; + DirtyArea *_mergedArea; + + DirtyArea(); + + void setArea(int width, int height, int maxWidth, int maxHeight); + + /** + * Set up a dirty area for a sprite slot + */ + void setSpriteSlot(const SpriteSlot *spriteSlot); + + /** + * Set up a dirty area for a text display + */ + void setTextDisplay(const TextDisplay *textDisplay); + + /** + * Set up a dirty area for a UI slot + */ + void setUISlot(const UISlot *slot); +}; + +class DirtyAreas : public Common::Array<DirtyArea> { +private: + MADSEngine *_vm; +public: + DirtyAreas(MADSEngine *vm); + + /** + * Merge together any designated dirty areas that overlap + * @param startIndex 1-based starting dirty area starting index + * @param count Number of entries to process + */ + void merge(int startIndex, int count); + + bool intersects(int idx1, int idx2); + void mergeAreas(int idx1, int idx2); + + /** + * Copy the data specified by the dirty rect list between surfaces + * @param srcSurface Source surface + * @param destSurface Dest surface + * @param posAdjust Position adjustment + */ + void copy(MSurface *srcSurface, MSurface *destSurface, const Common::Point &posAdjust); + + /** + * Use the lsit of dirty areas to copy areas of the screen surface to + * the physical screen + * @param posAdjust Position adjustment */ + void copyToScreen(const Common::Point &posAdjust); + + void reset(); +}; + + +class ScreenObject { +public: + bool _active; + Common::Rect _bounds; + ScrCategory _category; + int _descId; + int _layer; + + ScreenObject(); +}; + +class ScreenObjects : public Common::Array<ScreenObject> { +private: + MADSEngine *_vm; + int _objectY; + + int scanBackwards(const Common::Point &pt, int layer); +public: + InputMode _inputMode; + int _v7FED6; + int _v8332A; + int _forceRescan; + int _selectedObject; + ScrCategory _category; + bool _released; + int _uiCount; + bool _eventFlag; + uint32 _baseTime; + int _spotId; + + /* + * Constructor + */ + ScreenObjects(MADSEngine *vm); + + /** + * Add a new item to the list + */ + void add(const Common::Rect &bounds, Layer layer, ScrCategory category, int descId); + + /** + */ + void check(bool scanFlag); + + /** + * Handle an element being highlighted on the screen, and make it active. + */ + void elementHighlighted(); + + /** + * Retrieve a ScreenObject from the list + * @remarks This array is 1-based indexed by the game + */ + ScreenObject &operator[](int idx) { + assert(idx > 0); + return Common::Array<ScreenObject>::operator[](idx - 1); + } + + /** + * Sets an item identified by category and Desc Id as active or not + * @param category Screen category + * @param descId Description for item + * @param active Whether to set item as active or not + */ + void setActive(ScrCategory category, int descId, bool active); + + /** + * Synchronize the data + */ + void synchronize(Common::Serializer &s); +}; + +class ScreenSurface : public MSurface { +private: + uint16 _random; +public: + Common::Point _offset; + int _shakeCountdown; +public: + /** + * Constructor + */ + ScreenSurface(); + + /** + * Initialize the surface + */ + void init(); + + /** + * Copys an area of the screen surface to a given destination position on + * the ScummVM physical screen buffer + * @param destPos Destination position + * @param bounds Area of screen surface to copy + */ + void copyRectToScreen(const Common::Point &destPos, const Common::Rect &bounds); + + /** + * Copys an area of the screen surface to the ScmmVM physical screen buffer + * @param bounds Area of screen surface to copy + */ + void copyRectToScreen(const Common::Rect &bounds); + + /** + * Updates the screen with the contents of the surface + */ + void updateScreen(); + + void transition(ScreenTransition transitionType, bool surfaceFlag); +}; + +} // End of namespace MADS + +#endif /* MADS_SCREEN_H */ diff --git a/engines/mads/sequence.cpp b/engines/mads/sequence.cpp new file mode 100644 index 0000000000..f987595f05 --- /dev/null +++ b/engines/mads/sequence.cpp @@ -0,0 +1,541 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "mads/mads.h" +#include "mads/assets.h" +#include "mads/sequence.h" +#include "mads/scene.h" + +namespace MADS { + +SequenceEntry::SequenceEntry() { + _spritesIndex = 0; + _flipped = 0; + _frameIndex = 0; + _frameStart = 0; + _numSprites = 0; + _animType = ANIMTYPE_NONE; + _frameInc = 0; + _depth = 0; + _scale = 0; + _dynamicHotspotIndex = -1; + _triggerCountdown = 0; + _doneFlag = 0; + _triggerMode = SEQUENCE_TRIGGER_DAEMON; + _numTicks = 0; + _extraTicks = 0; + _timeout = 0; + _active = false; + _nonFixed = false; + _flags = 0; + for (int i = 0; i < 5; ++i) + _entries._mode[i] = SEQUENCE_TRIGGER_EXPIRE; + + _entries._count = 0; + _actionNouns._verbId = VERB_NONE; + _actionNouns._objectNameId = -1; + _actionNouns._indirectObjectId = -1; + + Common::fill(&_entries._frameIndex[0], &_entries._frameIndex[SEQUENCE_ENTRY_SUBSET_MAX], 0); + Common::fill(&_entries._trigger[0], &_entries._trigger[SEQUENCE_ENTRY_SUBSET_MAX], 0); +} + +/*------------------------------------------------------------------------*/ + +#define SEQUENCE_LIST_SIZE 30 + +SequenceList::SequenceList(MADSEngine *vm) : _vm(vm) { + // IMPORTANT: Preallocate timer slots. Note that sprite slots refer to entries + // in this list by index, so we can't just add or delete entries later + for (int i = 0; i < SEQUENCE_LIST_SIZE; ++i) { + SequenceEntry rec; + rec._active = false; + rec._dynamicHotspotIndex = -1; + _entries.push_back(rec); + } +} + +void SequenceList::clear() { + for (uint i = 0; i < _entries.size(); ++i) { + _entries[i]._active = false; + _entries[i]._dynamicHotspotIndex = -1; + } +} + +bool SequenceList::addSubEntry(int index, SequenceTrigger mode, int frameIndex, int trigger) { + if (_entries[index]._entries._count >= SEQUENCE_ENTRY_SUBSET_MAX) + return true; + + int subIndex = _entries[index]._entries._count++; + _entries[index]._entries._mode[subIndex] = mode; + _entries[index]._entries._frameIndex[subIndex] = frameIndex; + _entries[index]._entries._trigger[subIndex] = trigger; + + return false; +} + +int SequenceList::add(int spriteListIndex, bool flipped, int frameIndex, int triggerCountdown, int delayTicks, int extraTicks, int numTicks, + int msgX, int msgY, bool nonFixed, int scale, int depth, int frameInc, SpriteAnimType animType, int numSprites, + int frameStart) { + Scene &scene = _vm->_game->_scene; + + // Find a free slot + uint seqIndex = 0; + while ((seqIndex < _entries.size()) && _entries[seqIndex]._active) + ++seqIndex; + if (seqIndex == _entries.size()) + error("TimerList full"); + + if (frameStart <= 0) + frameStart = 1; + if (numSprites == 0) + numSprites = scene._sprites[spriteListIndex]->getCount(); + if (frameStart == numSprites) + frameInc = 0; + + // Set the list entry fields + _entries[seqIndex]._active = true; + _entries[seqIndex]._spritesIndex = spriteListIndex; + _entries[seqIndex]._flipped = flipped; + _entries[seqIndex]._frameIndex = frameIndex; + _entries[seqIndex]._frameStart = frameStart; + _entries[seqIndex]._numSprites = numSprites; + _entries[seqIndex]._animType = animType; + _entries[seqIndex]._frameInc = frameInc; + _entries[seqIndex]._depth = depth; + _entries[seqIndex]._scale = scale; + _entries[seqIndex]._nonFixed = nonFixed; + _entries[seqIndex]._position.x = msgX; + _entries[seqIndex]._position.y = msgY; + _entries[seqIndex]._numTicks = numTicks; + _entries[seqIndex]._extraTicks = extraTicks; + + _entries[seqIndex]._timeout = scene._frameStartTime + delayTicks; + + _entries[seqIndex]._triggerCountdown = triggerCountdown; + _entries[seqIndex]._doneFlag = false; + _entries[seqIndex]._flags = 0; + _entries[seqIndex]._dynamicHotspotIndex = -1; + _entries[seqIndex]._entries._count = 0; + _entries[seqIndex]._triggerMode = _vm->_game->_triggerSetupMode; + + _entries[seqIndex]._actionNouns = _vm->_game->_scene._action._activeAction; + + return seqIndex; +} + +int SequenceList::addTimer(int timeout, int abortVal) { + Scene &scene = _vm->_game->_scene; + uint seqIndex; + for (seqIndex = 0; seqIndex < _entries.size(); ++seqIndex) { + if (!_entries[seqIndex]._active) + break; + } + assert(seqIndex < _entries.size()); + + SequenceEntry &se = _entries[seqIndex]; + se._active = true; + se._spritesIndex = -1; + se._numTicks = timeout; + se._extraTicks = 0; + se._timeout = scene._frameStartTime + timeout; + se._triggerCountdown = true; + se._doneFlag = false; + se._entries._count = 0; + se._triggerMode = _vm->_game->_triggerSetupMode; + se._actionNouns = _vm->_game->_scene._action._activeAction; + addSubEntry(seqIndex, SEQUENCE_TRIGGER_EXPIRE, 0, abortVal); + + return seqIndex; +} + +void SequenceList::remove(int seqIndex) { + Scene &scene = _vm->_game->_scene; + + if (_entries[seqIndex]._active) { + if (_entries[seqIndex]._dynamicHotspotIndex >= 0) + scene._dynamicHotspots.remove(_entries[seqIndex]._dynamicHotspotIndex); + } + + _entries[seqIndex]._active = false; + scene._spriteSlots.deleteTimer(seqIndex); +} + +void SequenceList::setSpriteSlot(int seqIndex, SpriteSlot &spriteSlot) { + Scene &scene = _vm->_game->_scene; + SequenceEntry &timerEntry = _entries[seqIndex]; + SpriteAsset &spriteSet = *scene._sprites[timerEntry._spritesIndex]; + + spriteSlot._flags = spriteSet.isBackground() ? IMG_DELTA : IMG_UPDATE; + spriteSlot._seqIndex = seqIndex; + spriteSlot._spritesIndex = timerEntry._spritesIndex; + spriteSlot._frameNumber = timerEntry._flipped ? -timerEntry._frameIndex : timerEntry._frameIndex; + spriteSlot._depth = timerEntry._depth; + spriteSlot._scale = timerEntry._scale; + + if (!timerEntry._nonFixed) { + spriteSlot._position = timerEntry._position; + } else { + MSprite *sprite = spriteSet.getFrame(timerEntry._frameIndex - 1); + spriteSlot._position = sprite->_offset; + } +} + +bool SequenceList::loadSprites(int seqIndex) { + Scene &scene = _vm->_game->_scene; + SequenceEntry &seqEntry = _entries[seqIndex]; + int slotIndex; + bool result = false; + int idx = -1; + + scene._spriteSlots.deleteTimer(seqIndex); + if (seqEntry._doneFlag) { + remove(seqIndex); + return false; + } + + if (seqEntry._spritesIndex == -1) { + // Doesn't have an associated sprite anymore, so mark as done + seqEntry._doneFlag = true; + } else if ((slotIndex = scene._spriteSlots.add()) >= 0) { + SpriteSlot &spriteSlot = scene._spriteSlots[slotIndex]; + setSpriteSlot(seqIndex, spriteSlot); + + if ((seqEntry._flags != 0) || (seqEntry._dynamicHotspotIndex >= 0)) { + SpriteAsset &spriteSet = *scene._sprites[seqEntry._spritesIndex]; + MSprite *frame = spriteSet.getFrame(seqEntry._frameIndex - 1); + int width = frame->getWidth() * seqEntry._scale / 200; + int height = frame->getHeight() * seqEntry._scale / 100; + Common::Point pt = spriteSlot._position; + + // Handle sprite movement, if present + if (seqEntry._flags & 1) { + seqEntry._posAccum.x += seqEntry._posDiff.x; + if (seqEntry._posAccum.x >= 100) { + int v = seqEntry._posAccum.x / 100; + seqEntry._position.x += v * seqEntry._posSign.x; + seqEntry._posAccum.x -= v * 100; + } + + seqEntry._posAccum.y += seqEntry._posDiff.y; + if (seqEntry._posAccum.y >= 100) { + int v = seqEntry._posAccum.y / 100; + seqEntry._position.y += v * seqEntry._posSign.y; + seqEntry._posAccum.y -= v * 100; + } + } + + if (seqEntry._flags & 2) { + // Check for object having moved off-scren + if ((pt.x + width) < 0 || (pt.x + width) >= MADS_SCREEN_WIDTH || + pt.y < 0 || (pt.y - height) >= MADS_SCENE_HEIGHT) { + result = true; + seqEntry._doneFlag = true; + } + } + + if (seqEntry._dynamicHotspotIndex >= 0) { + DynamicHotspot &dynHotspot = scene._dynamicHotspots[seqEntry._dynamicHotspotIndex]; + + dynHotspot._bounds.left = MAX(pt.x - width, 0); + dynHotspot._bounds.top = MAX(pt.y - height, 0); + dynHotspot._bounds.right = dynHotspot._bounds.left + width; + dynHotspot._bounds.bottom = dynHotspot._bounds.top + height; + + scene._dynamicHotspots._changed = true; + } + } + + // Frame adjustments + if (seqEntry._frameStart != seqEntry._numSprites) + seqEntry._frameIndex += seqEntry._frameInc; + + if (seqEntry._frameIndex >= seqEntry._frameStart) { + if (seqEntry._frameIndex > seqEntry._numSprites) { + result = true; + if (seqEntry._animType == ANIMTYPE_CYCLED) { + // back to the starting frame (cyclic) + seqEntry._frameIndex = seqEntry._frameStart; + } else { + // Switch into reverse mode + seqEntry._frameIndex = seqEntry._numSprites - 1; + seqEntry._frameInc = -1; + } + } + } else { + // Currently in reverse mode and moved past starting frame + result = true; + + if (seqEntry._animType == ANIMTYPE_CYCLED) + { + // Switch back to forward direction again + seqEntry._frameIndex = seqEntry._frameStart + 1; + seqEntry._frameInc = 1; + } else { + // Otherwise reset back to last sprite for further reverse animating + seqEntry._frameIndex = seqEntry._numSprites; + } + } + + if (result && (seqEntry._triggerCountdown != 0)) { + if (--seqEntry._triggerCountdown == 0) + seqEntry._doneFlag = true; + } + } else { + // Out of sprite display slots, so mark entry as done + seqEntry._doneFlag = true; + } + + for (int i = 0; i < seqEntry._entries._count; ++i) { + switch (seqEntry._entries._mode[i]) { + case SEQUENCE_TRIGGER_EXPIRE: + case SEQUENCE_TRIGGER_LOOP: + if (((seqEntry._entries._mode[i] == SEQUENCE_TRIGGER_EXPIRE) && seqEntry._doneFlag) || + ((seqEntry._entries._mode[i] == SEQUENCE_TRIGGER_LOOP) && result)) + idx = i; + break; + + case SEQUENCE_TRIGGER_SPRITE: { + int v = seqEntry._entries._frameIndex[i]; + if ((v == seqEntry._frameIndex) || (v == 0)) + idx = i; + break; + } + + default: + break; + } + } + + if (idx >= 0) { + _vm->_game->_trigger = seqEntry._entries._trigger[idx]; + _vm->_game->_triggerMode = seqEntry._triggerMode; + + if (seqEntry._triggerMode != SEQUENCE_TRIGGER_DAEMON) + scene._action._activeAction = seqEntry._actionNouns; + } + + return result; +} + +/** +* Handles counting down entries in the timer list for action +*/ +void SequenceList::tick() { + Scene &scene = _vm->_game->_scene; + for (uint idx = 0; idx < _entries.size(); ++idx) { + if ((_vm->_game->_fx == 0) && (_vm->_game->_trigger != 0)) + break; + + SequenceEntry &seqEntry = _entries[idx]; + uint32 currentTimer = scene._frameStartTime; + + if (!seqEntry._active || (currentTimer < seqEntry._timeout)) + continue; + + // Set the next timeout for the timer entry + seqEntry._timeout = currentTimer + seqEntry._numTicks; + + // Action the sprite + if (loadSprites(idx)) { + seqEntry._timeout += seqEntry._extraTicks; + } + } +} + +void SequenceList::delay(uint32 priorFrameTime, uint32 currentTime) { + for (uint idx = 0; idx < _entries.size(); ++idx) { + if (_entries[idx]._active) { + _entries[idx]._timeout += currentTime - priorFrameTime; + } + } +} + +void SequenceList::setAnimRange(int seqIndex, int startVal, int endVal) { + Scene &scene = _vm->_game->_scene; + SequenceEntry &seqEntry = _entries[seqIndex]; + SpriteAsset &spriteSet = *scene._sprites[seqEntry._spritesIndex]; + int numSprites = spriteSet.getCount(); + int tempStart, tempEnd; + + switch (startVal) { + case -2: + tempStart = numSprites; + break; + case -1: + tempStart = 1; + break; + default: + tempStart = startVal; + break; + } + + switch (endVal) { + case -2: + case 0: + tempEnd = numSprites; + break; + case -1: + tempEnd = 1; + break; + default: + tempEnd = endVal; + break; + } + + seqEntry._frameStart = tempStart; + seqEntry._numSprites = tempEnd; + + seqEntry._frameIndex = (seqEntry._frameInc >= 0) ? tempStart : tempEnd; +} + +void SequenceList::scan() { + Scene &scene = _vm->_game->_scene; + + for (uint i = 0; i < _entries.size(); ++i) { + if (_entries[i]._active && (_entries[i]._spritesIndex != -1)) { + int idx = scene._spriteSlots.add(); + setSpriteSlot(i, scene._spriteSlots[idx]); + } + } +} + +/** +* Sets the depth of the specified entry in the sequence list +*/ +void SequenceList::setDepth(int seqIndex, int depth) { + _entries[seqIndex]._depth = depth; +} + +void SequenceList::setPosition(int seqIndex, const Common::Point &pt) { + _entries[seqIndex]._position = pt; + _entries[seqIndex]._nonFixed = false; +} + +int SequenceList::addSpriteCycle(int srcSpriteIdx, bool flipped, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks) { + Scene &scene = _vm->_game->_scene; + MSprite *spriteFrame = scene._sprites[srcSpriteIdx]->getFrame(0); + int depth = scene._depthSurface.getDepth(Common::Point( + spriteFrame->_offset.x + (spriteFrame->w / 2), + spriteFrame->_offset.y + (spriteFrame->h / 2))); + + return add(srcSpriteIdx, flipped, 1, triggerCountdown, timeoutTicks, extraTicks, numTicks, 0, 0, + true, 100, depth - 1, 1, ANIMTYPE_CYCLED, 0, 0); +} + +int SequenceList::addReverseSpriteCycle(int srcSpriteIdx, bool flipped, int numTicks, + int triggerCountdown, int timeoutTicks, int extraTicks) { + Scene &scene = _vm->_game->_scene; + + SpriteAsset *asset = scene._sprites[srcSpriteIdx]; + MSprite *spriteFrame = asset->getFrame(0); + int depth = scene._depthSurface.getDepth(Common::Point( + spriteFrame->_offset.x + (spriteFrame->w / 2), + spriteFrame->_offset.y + (spriteFrame->h / 2))); + + return add(srcSpriteIdx, flipped, asset->getCount(), triggerCountdown, timeoutTicks, extraTicks, + numTicks, 0, 0, true, 100, depth - 1, -1, ANIMTYPE_CYCLED, 0, 0); +} + + +int SequenceList::startCycle(int srcSpriteIndex, bool flipped, int cycleIndex) { + int result = addSpriteCycle(srcSpriteIndex, flipped, INDEFINITE_TIMEOUT, 0, 0, 0); + if (result >= 0) + setAnimRange(result, cycleIndex, cycleIndex); + + return result; +} + +int SequenceList::startReverseCycle(int srcSpriteIndex, bool flipped, int numTicks, + int triggerCountdown, int timeoutTicks, int extraTicks) { + SpriteAsset *sprites = _vm->_game->_scene._sprites[srcSpriteIndex]; + MSprite *frame = sprites->getFrame(0); + int depth = _vm->_game->_scene._depthSurface.getDepth(Common::Point( + frame->_offset.x + frame->w / 2, frame->_offset.y + frame->h / 2)); + + return add(srcSpriteIndex, flipped, 1, triggerCountdown, timeoutTicks, extraTicks, + numTicks, 0, 0, true, 100, depth - 1, 1, ANIMTYPE_REVERSIBLE, 0, 0); +} + +void SequenceList::updateTimeout(int spriteIdx, int seqIndex) { + Player &player = _vm->_game->_player; + int timeout; + + if (spriteIdx >= 0) + timeout = _entries[spriteIdx]._timeout; + else + timeout = player._priorTimer + player._ticksAmount; + + if (seqIndex >= 0) + _entries[seqIndex]._timeout = timeout; + else + player._priorTimer = timeout - player._ticksAmount; + +} + +void SequenceList::setScale(int spriteIdx, int scale) { + _entries[spriteIdx]._scale = scale; +} + +void SequenceList::setMsgLayout(int seqIndex) { + Player &player = _vm->_game->_player; + int yp = player._playerPos.y + (player._centerOfGravity * player._currentScale) / 100; + setPosition(seqIndex, Common::Point(player._playerPos.x, yp)); + setDepth(seqIndex, player._currentDepth); + setScale(seqIndex, player._currentScale); + updateTimeout(-1, seqIndex); +} + +void SequenceList::setDone(int seqIndex) { + _entries[seqIndex]._doneFlag = true; + _entries[seqIndex]._timeout = _vm->_game->_player._priorTimer; +} + +void SequenceList::setMotion(int seqIndex, int flags, int deltaX, int deltaY) { + SequenceEntry &se = _entries[seqIndex]; + se._flags = flags | 1; + + // Set the direction sign for movement + if (deltaX > 0) { + se._posSign.x = 1; + } else if (deltaX < 0) { + se._posSign.x = -1; + } else { + se._posSign.x = 0; + } + + if (deltaY > 0) { + se._posSign.y = 1; + } + else if (deltaY < 0) { + se._posSign.y = -1; + } else { + se._posSign.y = 0; + } + + se._posDiff.x = ABS(deltaX); + se._posDiff.y = ABS(deltaY); + se._posAccum.x = se._posAccum.y = 0; +} + +} // End of namespace diff --git a/engines/mads/sequence.h b/engines/mads/sequence.h new file mode 100644 index 0000000000..ee587ff02d --- /dev/null +++ b/engines/mads/sequence.h @@ -0,0 +1,131 @@ +/* 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. + * + */ + +#ifndef MADS_SEQUENCE_H +#define MADS_SEQUENCE_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/rect.h" +#include "mads/action.h" + +namespace MADS { + +class SpriteSlot; + +enum SequenceTrigger { + SEQUENCE_TRIGGER_EXPIRE = 0, // Trigger when the sequence finishes + SEQUENCE_TRIGGER_LOOP = 1, // Trigger when the sequence loops + SEQUENCE_TRIGGER_SPRITE = 2 // Trigger when sequence reaches specific sprite +}; + +enum SpriteAnimType { ANIMTYPE_NONE = 0, ANIMTYPE_CYCLED = 1, ANIMTYPE_REVERSIBLE = 2 }; + +#define SEQUENCE_ENTRY_SUBSET_MAX 5 + +struct SequenceSubEntries { + int _count; + SequenceTrigger _mode[SEQUENCE_ENTRY_SUBSET_MAX]; + int _frameIndex[SEQUENCE_ENTRY_SUBSET_MAX]; + int _trigger[SEQUENCE_ENTRY_SUBSET_MAX]; +}; + +struct SequenceEntry { + bool _active; + int8 _spritesIndex; + bool _flipped; + + int _frameIndex; + int _frameStart; + int _numSprites; + + SpriteAnimType _animType; + int _frameInc; + + int _depth; + int _scale; + int _dynamicHotspotIndex; + + bool _nonFixed; + uint32 _flags; + + Common::Point _position; + Common::Point _posDiff; + Common::Point _posSign; + Common::Point _posAccum; + int _triggerCountdown; + bool _doneFlag; + SequenceSubEntries _entries; + TriggerMode _triggerMode; + + ActionDetails _actionNouns; + int _numTicks; + int _extraTicks; + uint32 _timeout; + + SequenceEntry(); +}; + +class MADSEngine; + +class SequenceList { +private: + MADSEngine *_vm; + Common::Array<SequenceEntry> _entries; +public: + SequenceList(MADSEngine *vm); + + SequenceEntry &operator[](int index) { return _entries[index]; } + void clear(); + bool addSubEntry(int index, SequenceTrigger mode, int frameIndex, int trigger); + int add(int spriteListIndex, bool flipped, int frameIndex, int triggerCountdown, int delayTicks, + int extraTicks, int numTicks, int msgX, int msgY, bool nonFixed, int scale, int depth, + int frameInc, SpriteAnimType animType, int numSprites, int frameStart); + + int addTimer(int timeout, int abortVal); + void remove(int seqIndex); + void setSpriteSlot(int seqIndex, SpriteSlot &spriteSlot); + bool loadSprites(int seqIndex); + void tick(); + void delay(uint32 priorFrameTime, uint32 currentTime); + void setAnimRange(int seqIndex, int startVal, int endVal); + void scan(); + void setDepth(int seqIndex, int depth); + void setPosition(int seqIndex, const Common::Point &pt); + int addSpriteCycle(int srcSpriteIdx, bool flipped, int numTicks, + int triggerCountdown = 0, int timeoutTicks = 0, int extraTicks = 0); + int addReverseSpriteCycle(int srcSpriteIdx, bool flipped, int numTicks, + int triggerCountdown = 0, int timeoutTicks = 0, int extraTicks = 0); + + int startCycle(int srcSpriteIdx, bool flipped, int cycleIndex); + int startReverseCycle(int srcSpriteIndex, bool flipped, int numTicks, + int triggerCountdown = 0, int timeoutTicks = 0, int extraTicks = 0); + void updateTimeout(int spriteIdx, int seqIndex); + void setScale(int spriteIdx, int scale); + void setMsgLayout(int seqIndex); + void setDone(int seqIndex); + void setMotion(int seqIndex, int flags, int deltaX, int deltaY); +}; + +} // End of namespace MADS + +#endif /* MADS_SEQUENCE_H */ diff --git a/engines/mads/sound.cpp b/engines/mads/sound.cpp new file mode 100644 index 0000000000..bd99aed2f4 --- /dev/null +++ b/engines/mads/sound.cpp @@ -0,0 +1,142 @@ +/* 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. + * + */ + +#include "audio/audiostream.h" +#include "audio/decoders/raw.h" +#include "common/memstream.h" +#include "mads/sound.h" +#include "mads/mads.h" +#include "mads/nebular/sound_nebular.h" + +namespace MADS { + +SoundManager::SoundManager(MADSEngine *vm, Audio::Mixer *mixer) { + _vm = vm; + _mixer = mixer; + _driver = nullptr; + _pollSoundEnabled = false; + _soundPollFlag = false; + _newSoundsPaused = false; +} + +SoundManager::~SoundManager() { + delete _driver; +} + +void SoundManager::init(int sectionNumber) { + assert(sectionNumber > 0 && sectionNumber < 10); + + switch (_vm->getGameID()) { + case GType_RexNebular: + switch (sectionNumber) { + case 1: + _driver = new Nebular::ASound1(_mixer); + break; + case 2: + _driver = new Nebular::ASound2(_mixer); + break; + case 3: + _driver = new Nebular::ASound3(_mixer); + break; + case 4: + _driver = new Nebular::ASound4(_mixer); + break; + case 5: + _driver = new Nebular::ASound5(_mixer); + break; + case 6: + _driver = new Nebular::ASound6(_mixer); + break; + case 7: + _driver = new Nebular::ASound7(_mixer); + break; + case 8: + _driver = new Nebular::ASound8(_mixer); + break; + case 9: + error("Sound driver 9 not implemented"); + default: + _driver = nullptr; + break; + } + break; + + default: + warning("SoundManager: Unknown game"); + _driver = nullptr; + break; + } +} + +void SoundManager::closeDriver() { + if (_driver) { + command(0); + setEnabled(false); + stop(); + + removeDriver(); + } +} + +void SoundManager::removeDriver() { + delete _driver; + _driver = nullptr; +} + +void SoundManager::setEnabled(bool flag) { + _pollSoundEnabled = flag; + _soundPollFlag = false; +} + +void SoundManager::pauseNewCommands() { + _newSoundsPaused = true; +} + +void SoundManager::startQueuedCommands() { + _newSoundsPaused = false; + + while (!_queuedCommands.empty()) { + int commandId = _queuedCommands.pop(); + command(commandId); + } +} + +void SoundManager::command(int commandId, int param) { + if (_newSoundsPaused) { + if (_queuedCommands.size() < 8) + _queuedCommands.push(commandId); + } else if (_driver) { + _driver->command(commandId, param); + } +} + +void SoundManager::stop() { + if (_driver) + _driver->stop(); +} + +void SoundManager::noise() { + if (_driver) + _driver->noise(); +} + +} // End of namespace MADS diff --git a/engines/mads/sound.h b/engines/mads/sound.h new file mode 100644 index 0000000000..9a251f9dd0 --- /dev/null +++ b/engines/mads/sound.h @@ -0,0 +1,103 @@ +/* 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. + * + */ + +#ifndef MADS_SOUND_H +#define MADS_SOUND_H + +#include "common/scummsys.h" +#include "common/queue.h" +#include "audio/audiostream.h" +#include "audio/mixer.h" +#include "mads/nebular/sound_nebular.h" + +namespace MADS { + +class MADSEngine; + +class SoundManager { +private: + MADSEngine *_vm; + Audio::Mixer *_mixer; + Nebular::ASound *_driver; + bool _pollSoundEnabled; + bool _soundPollFlag; + bool _newSoundsPaused; + Common::Queue<int> _queuedCommands; +public: + SoundManager(MADSEngine *vm, Audio::Mixer *mixer); + ~SoundManager(); + + /** + * Initializes the sound driver for a given game section + */ + void init(int sectionNumber); + + /** + * Stop any currently active sound and remove the driver + */ + void closeDriver(); + + /** + * Remove the driver + */ + void removeDriver(); + + /** + * Sets the enabled status of the sound + * @flag True if sound should be enabled + */ + void setEnabled(bool flag); + + /** + * Temporarily pause the playback of any new sound commands + */ + void pauseNewCommands(); + + /** + * Stop queueing sound commands, and execute any previously queued ones + */ + void startQueuedCommands(); + + //@{ + /** + * Executes a command on the sound driver + * @param commandid Command Id to execute + * @param param Optional paramater specific to a few commands + */ + void command(int commandId, int param = 0); + + /** + * Stops any currently playing sound + */ + void stop(); + + /** + * Noise + * Some sort of random noise generation? + */ + void noise(); + //@} +}; + +} // End of namespace MADS + +#endif /* MADS_SOUND_H */ diff --git a/engines/mads/sprites.cpp b/engines/mads/sprites.cpp new file mode 100644 index 0000000000..a229fccb89 --- /dev/null +++ b/engines/mads/sprites.cpp @@ -0,0 +1,417 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "engines/util.h" +#include "graphics/palette.h" +#include "mads/mads.h" +#include "mads/screen.h" +#include "mads/msurface.h" +#include "mads/sprites.h" + +namespace MADS { + +enum { + kEndOfLine = 0, + kEndOfSprite = 1, + kMarker = 2 +}; + +#define TRANSPARENT_COLOR_INDEX 0xFF + +class DepthEntry { +public: + int depth; + int index; + + DepthEntry(int depthAmt, int indexVal) { depth = depthAmt; index = indexVal; } +}; + +bool sortHelper(const DepthEntry &entry1, const DepthEntry &entry2) { + return entry1.depth < entry2.depth; +} + +typedef Common::List<DepthEntry> DepthList; + +/*------------------------------------------------------------------------*/ + +MSprite::MSprite() + : MSurface() { +} + +MSprite::MSprite(Common::SeekableReadStream *source, const Common::Array<RGB6> &palette, + const Common::Rect &bounds) + : MSurface(bounds.width(), bounds.height()), + _offset(Common::Point(bounds.left, bounds.top)) { + // Load the sprite data + loadSprite(source, palette); +} + +MSprite::~MSprite() { +} + +void MSprite::loadSprite(Common::SeekableReadStream *source, + const Common::Array<RGB6> &palette) { + byte *outp, *lineStart; + bool newLine = false; + + outp = getData(); + lineStart = getData(); + int spriteSize = this->w * this->h; + byte transIndex = getTransparencyIndex(); + Common::fill(outp, outp + spriteSize, transIndex); + + for (;;) { + byte cmd1, cmd2, count, pixel; + + if (newLine) { + outp = lineStart + getWidth(); + lineStart = outp; + newLine = false; + } + + cmd1 = source->readByte(); + + if (cmd1 == 0xFC) + break; + else if (cmd1 == 0xFF) + newLine = true; + else if (cmd1 == 0xFD) { + while (!newLine) { + count = source->readByte(); + if (count == 0xFF) { + newLine = true; + } else { + pixel = source->readByte(); + while (count--) + *outp++ = (pixel == 0xFD) ? getTransparencyIndex() : pixel; + } + } + } else { + while (!newLine) { + cmd2 = source->readByte(); + if (cmd2 == 0xFF) { + newLine = true; + } else if (cmd2 == 0xFE) { + count = source->readByte(); + pixel = source->readByte(); + while (count--) + *outp++ = (pixel == 0xFD) ? getTransparencyIndex() : pixel; + } else { + *outp++ = (cmd2 == 0xFD) ? getTransparencyIndex() : cmd2; + } + } + } + } + + // Do a final iteration over the sprite to convert it's pixels to + // the final positions in the main palette + for (outp = getData(); spriteSize > 0; --spriteSize, ++outp) { + if (*outp != transIndex) + *outp = palette[*outp]._palIndex; + } +} + +byte MSprite::getTransparencyIndex() const { + return TRANSPARENT_COLOR_INDEX; +} + +/*------------------------------------------------------------------------*/ + +MADSEngine *SpriteSlot::_vm = nullptr; + +SpriteSlot::SpriteSlot() { + _flags = IMG_STATIC; + _seqIndex = 0; + _spritesIndex = 0; + _frameNumber = 0; + _depth = 0; + _scale = 0; +} + +SpriteSlot::SpriteSlot(SpriteFlags type, int seqIndex) { + _flags = type; + _seqIndex = seqIndex; + _spritesIndex = 0; + _frameNumber = 0; + _depth = 0; + _scale = 0; +} + +bool SpriteSlot::operator==(const SpriteSlotSubset &other) const { + return (_spritesIndex == other._spritesIndex) && (_frameNumber == other._frameNumber) && + (_position == other._position) && (_depth == other._depth) && + (_scale == other._scale); +} + +void SpriteSlot::copy(const SpriteSlotSubset &other) { + _spritesIndex = other._spritesIndex; + _frameNumber = other._frameNumber; + _position = other._position; + _depth = other._depth; + _scale = other._scale; +} + +/*------------------------------------------------------------------------*/ + +SpriteSlots::SpriteSlots(MADSEngine *vm) : _vm(vm) { + SpriteSlot::_vm = vm; +} + +void SpriteSlots::reset(bool flag) { + _vm->_game->_scene._textDisplay.reset(); + + if (flag) + _vm->_game->_scene._sprites.clear(); + + Common::Array<SpriteSlot>::clear(); + push_back(SpriteSlot(IMG_REFRESH, -1)); +} + +void SpriteSlots::deleteEntry(int index) { + remove_at(index); +} + +void SpriteSlots::setDirtyAreas() { + Scene &scene = _vm->_game->_scene; + + for (uint i = 0; i < size(); ++i) { + if ((*this)[i]._flags >= IMG_STATIC) { + scene._dirtyAreas[i].setSpriteSlot(&(*this)[i]); + + scene._dirtyAreas[i]._textActive = ((*this)[i]._flags <= IMG_STATIC) ? 0 : 1; + (*this)[i]._flags = IMG_STATIC; + } + } +} + +void SpriteSlots::fullRefresh(bool clearAll) { + if (clearAll) + Common::Array<SpriteSlot>::clear(); + + push_back(SpriteSlot(IMG_REFRESH, -1)); +} + +void SpriteSlots::deleteTimer(int seqIndex) { + for (uint idx = 0; idx < size(); ++idx) { + SpriteSlot &slot = (*this)[idx]; + if (slot._seqIndex == seqIndex) { + slot._flags = IMG_ERASE; + return; + } + } +} + +int SpriteSlots::add() { + SpriteSlot ss; + push_back(ss); + return size() - 1; +} + +void SpriteSlots::drawBackground() { + Scene &scene = _vm->_game->_scene; + + // Initial draw loop for any active sprites in the background + for (uint i = 0; i < size(); ++i) { + SpriteSlot &spriteSlot = (*this)[i]; + DirtyArea &dirtyArea = scene._dirtyAreas[i]; + + if (spriteSlot._flags >= IMG_STATIC) { + // Foreground sprite, so we can ignore it + dirtyArea._active = false; + } else { + dirtyArea._active = true; + dirtyArea.setSpriteSlot(&spriteSlot); + + if (spriteSlot._flags == IMG_DELTA) { + // Background object, so need to draw it + assert(spriteSlot._frameNumber > 0); + SpriteAsset *asset = scene._sprites[spriteSlot._spritesIndex]; + MSprite *frame = asset->getFrame(spriteSlot._frameNumber - 1); + + Common::Point pt = spriteSlot._position; + if (spriteSlot._scale != -1) { + // Adjust the drawing position + pt.x -= frame->w / 2; + pt.y -= frame->h / 2; + } + + + if (spriteSlot._depth <= 1) { + frame->copyTo(&scene._backgroundSurface, pt, frame->getTransparencyIndex()); + } else if (scene._depthStyle == 0) { + scene._backgroundSurface.copyFrom(frame, pt, spriteSlot._depth, &scene._depthSurface, + 100, frame->getTransparencyIndex()); + } else { + error("Unsupported depth style"); + } + } + } + } + + // Mark any remaning sprite slot dirty areas as inactive + for (uint i = size(); i < SPRITE_SLOTS_MAX_SIZE; ++i) + scene._dirtyAreas[i]._active = false; + + // Flag any active text display + for (uint i = 0; i < scene._textDisplay.size(); ++i) { + TextDisplay &textDisplay = scene._textDisplay[i]; + DirtyArea &dirtyArea = scene._dirtyAreas[i + SPRITE_SLOTS_MAX_SIZE]; + + if (textDisplay._expire >= 0 || !textDisplay._active) { + dirtyArea._active = false; + } else { + dirtyArea._active = true; + dirtyArea.setTextDisplay(&textDisplay); + } + } +} + +void SpriteSlots::drawSprites(MSurface *s) { + DepthList depthList; + Scene &scene = _vm->_game->_scene; + + // Get a list of sprite object depths for active objects + for (uint i = 0; i < size(); ++i) { + SpriteSlot &spriteSlot = (*this)[i]; + if (spriteSlot._flags >= IMG_STATIC) { + DepthEntry rec(16 - spriteSlot._depth, i); + depthList.push_back(rec); + } + } + + // Sort the list in order of the depth + Common::sort(depthList.begin(), depthList.end(), sortHelper); + + // Loop through each of the objects + DepthList::iterator i; + for (i = depthList.begin(); i != depthList.end(); ++i) { + DepthEntry &de = *i; + SpriteSlot &slot = (*this)[de.index]; + assert(slot._spritesIndex < (int)scene._sprites.size()); + SpriteAsset &spriteSet = *scene._sprites[slot._spritesIndex]; + + // Get the sprite frame + int frameNumber = ABS(slot._frameNumber); + bool flipped = slot._frameNumber < 0; + + assert(frameNumber > 0); + MSprite *sprite = spriteSet.getFrame(frameNumber - 1); + + MSurface *spr = sprite; + if (flipped) { + // Create a flipped copy of the sprite temporarily + spr = sprite->flipHorizontal(); + } + + if ((slot._scale < 100) && (slot._scale != -1)) { + // Minimalized drawing + s->copyFrom(spr, slot._position, slot._depth, &scene._depthSurface, + slot._scale, sprite->getTransparencyIndex()); + } else { + int xp, yp; + + if (slot._scale == -1) { + xp = slot._position.x - scene._posAdjust.x; + yp = slot._position.y - scene._posAdjust.y; + } else { + xp = slot._position.x - (spr->w / 2) - scene._posAdjust.x; + yp = slot._position.y - spr->h - scene._posAdjust.y + 1; + } + + if (slot._depth > 1) { + // Draw the frame with depth processing + s->copyFrom(spr, Common::Point(xp, yp), slot._depth, &scene._depthSurface, + 100, sprite->getTransparencyIndex()); + } else { + // No depth, so simply draw the image + spr->copyTo(s, Common::Point(xp, yp), sprite->getTransparencyIndex()); + } + } + + // Free sprite if it was a flipped one + if (flipped) + delete spr; + } +} + +void SpriteSlots::cleanUp() { + for (int i = (int)size() - 1; i >= 0; --i) { + if ((*this)[i]._flags < IMG_STATIC) + remove_at(i); + } +} + +/*------------------------------------------------------------------------*/ + +SpriteSets::~SpriteSets() { + clear(); +} + +int SpriteSets::add(SpriteAsset *asset, int idx) { + if (idx) + idx = idx + 49; + else + idx = size(); + + if (idx >= (int)size()) + resize(idx + 1); + + if ((*this)[idx]) { + delete (*this)[idx]; + } else { + ++_assetCount; + } + + (*this)[idx] = asset; + return idx; +} + +int SpriteSets::addSprites(const Common::String &resName, int flags) { + return add(new SpriteAsset(_vm, resName, flags)); +} + +void SpriteSets::clear() { + for (uint i = 0; i < size(); ++i) + delete (*this)[i]; + + _assetCount = 0; + Common::Array<SpriteAsset *>::clear(); +} + +void SpriteSets::remove(int idx) { + if (idx >= 0) { + if (idx < ((int)size() - 1)) { + delete (*this)[idx]; + (*this)[idx] = nullptr; + } else { + while (size() > 0 && (*this)[size() - 1] == nullptr) { + remove_at(size() - 1); + } + } + + if (_assetCount > 0) + --_assetCount; + } +} + +} // End of namespace MADS diff --git a/engines/mads/sprites.h b/engines/mads/sprites.h new file mode 100644 index 0000000000..324122e348 --- /dev/null +++ b/engines/mads/sprites.h @@ -0,0 +1,239 @@ +/* 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. + * + */ + +#ifndef MADS_SPRITES_H +#define MADS_SPRITES_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "mads/assets.h" +#include "mads/msurface.h" + +namespace MADS { + +enum SpriteFlags { + IMG_STATIC = 0, // Item should remain fixed on the screen + IMG_UPDATE = 1, // Item needs to be redrawn + IMG_ERASE = -1, // Erase image and remove it + IMG_REFRESH = -2, // Full refresh + IMG_OVERPRINT = -3, // Interface overprint + IMG_DELTA = -4, // Delta change + IMG_FULL_UPDATE = -5, // Interface refresh + IMG_UPDATE_ONLY = -20 // Update the active screen area only +}; + +class MADSEngine; + +struct BGR8 { + uint8 b, g, r; +}; + +typedef struct { + int32 x; // x position relative to GrBuff(0, 0) + int32 y; // y position relative to GrBuff(0, 0) + int32 scale_x; // x scale factor (can be negative for reverse draw) + int32 scale_y; // y scale factor (can't be negative) + uint8* depth_map; // depth code array for destination (doesn't care if srcDepth is 0) + BGR8* Pal; // palette for shadow draw (doesn't care if SHADOW bit is not set in Src.encoding) + uint8* ICT; // Inverse Color Table (doesn't care if SHADOW bit is not set in Src.encoding) + uint8 depth; // depth code for source (0 if no depth processing) +} DrawRequestX; + +typedef struct { + uint32 Pack; + uint32 Stream; + long hot_x; + long hot_y; + uint32 Width; + uint32 Height; + uint32 Comp; + uint32 Reserved[8]; + uint8* data; +} RendCell; + +#define SS_HEADER_NUM_FIELDS 14 +struct SpriteSeriesHeader { + uint32 header; + uint32 size; + uint32 packing; + uint32 frameRate; + uint32 pixSpeed; + uint32 maxWidth; + uint32 maxHeight; + uint32 reserved3; + uint32 reserved4; + uint32 reserved5; + uint32 reserved6; + uint32 reserved7; + uint32 reserved8; + uint32 count; +}; + +#define SF_HEADER_NUM_FIELDS 15 +struct SpriteFrameHeader { + uint32 pack; + uint32 stream; + uint32 x; + uint32 y; + uint32 width; + uint32 height; + uint32 comp; + uint32 reserved1; + uint32 reserved2; + uint32 reserved3; + uint32 reserved4; + uint32 reserved5; + uint32 reserved6; + uint32 reserved7; + uint32 reserved8; +}; + +class MSprite : public MSurface { +private: + void loadSprite(Common::SeekableReadStream *source, const Common::Array<RGB6> &palette); +public: + MSprite(); + MSprite(Common::SeekableReadStream *source, const Common::Array<RGB6> &palette, + const Common::Rect &bounds); + virtual ~MSprite(); + + Common::Point _offset; + + byte getTransparencyIndex() const; +}; + +class SpriteSlotSubset { +public: + int _spritesIndex; + int _frameNumber; + Common::Point _position; + int _depth; + int _scale; +}; + +class SpriteSlot : public SpriteSlotSubset { +private: + static MADSEngine *_vm; + friend class SpriteSlots; +public: + SpriteFlags _flags; + int _seqIndex; +public: + SpriteSlot(); + SpriteSlot(SpriteFlags type, int seqIndex); + + void setup(int dirtyAreaIndex); + bool operator==(const SpriteSlotSubset &other) const; + void copy(const SpriteSlotSubset &other); +}; + +class SpriteSlots : public Common::Array<SpriteSlot> { +private: + MADSEngine *_vm; +public: + SpriteSlots(MADSEngine *vm); + + /** + * Clears any pending slot data and schedules a full screen refresh. + * @param flag Also reset sprite list + */ + void reset(bool flag = true); + + /** + * Delete a sprite entry + * @param index Specifies the index in the array + */ + void deleteEntry(int index); + + /** + * Setup dirty areas for the sprite slots + */ + void setDirtyAreas(); + + /** + * Adds a full screen refresh to the sprite slots + */ + void fullRefresh(bool clearAll = false); + + /** + * Delete a timer entry with the given Id + */ + void deleteTimer(int seqIndex); + + /** + * Add a new slot entry and return it's index + */ + int add(); + + /** + * Draw any sprites into the background of the scene + */ + void drawBackground(); + + /** + * Draw any sprites into the foreground of the scene + */ + void drawSprites(MSurface *s); + + void cleanUp(); +}; + +class SpriteSets : public Common::Array<SpriteAsset *> { +private: + MADSEngine *_vm; +public: + int _assetCount; + + /** + * Constructor + */ + SpriteSets(MADSEngine *vm) : _vm(vm), _assetCount(0) {} + + /** + * Destructor + */ + ~SpriteSets(); + + /** + * Clears the current list, freeing any laoded assets + */ + void clear(); + + /** + * Add a sprite asset to the list + */ + int add(SpriteAsset *asset, int idx = 0); + + /** + * Adds a sprite asset to the list by name + */ + int addSprites(const Common::String &resName, int flags = 0); + + /** + * Remove an asset from the list + */ + void remove(int idx); +}; + +} // End of namespace MADS + +#endif /* MADS_SPRITES_H */ diff --git a/engines/mads/staticres.cpp b/engines/mads/staticres.cpp new file mode 100644 index 0000000000..189e5f72e7 --- /dev/null +++ b/engines/mads/staticres.cpp @@ -0,0 +1,58 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 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. + * + */ + +#include "common/scummsys.h" +#include "mads/staticres.h" + +namespace MADS { + +const char *const kArticleList[9] = { + nullptr, "with", "to", "at", "from", "on", "in", "under", "behind" +}; + +const char *const kCheatingEnabledDesc[3] = { + "CHEATING ENABLED", + "(For your convenience).", + nullptr +}; + +const char *const kLookAroundStr = "Look around"; +const char *const kToStr = "to "; +const char *const kUseStr = "Use "; +const char *const kWalkToStr = "Walk to "; +const char *const kFenceStr = "fence"; +const char *const kOverStr = "over"; + +const char *const kGameReleaseInfoStr = "ScummVM rev: 8.43 14-Sept-92"; +const char *const kGameReleaseTitleStr = "GAME RELASE VERSION INFO"; + +const uint32 DEFAULT_VGA_LOW_PALETTE[16] = { + 0x000000, 0x0000a8, 0x00a800, 0x00a8a8, 0xa80000, 0xa800a8, 0xa85400, 0xa8a8a8, + 0x545454, 0x5454fc, 0x54fc54, 0x54fcfc, 0xfc5454, 0xfc54fc, 0xfcfc54, 0xfcfcfc +}; + +const uint32 DEFAULT_VGA_HIGH_PALETTE[16] = { + 0x2c402c, 0x2c4030, 0x2c4034, 0x2c403c, 0x2c4040, 0x2c3c40, 0x2c3440, 0x2c3040, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000 +}; + +} // End of namespace MADS diff --git a/engines/mads/staticres.h b/engines/mads/staticres.h new file mode 100644 index 0000000000..560fd12e67 --- /dev/null +++ b/engines/mads/staticres.h @@ -0,0 +1,47 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 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. + * + */ + +#ifndef MADS_STATICRES_H +#define MADS_STATICRES_H + +namespace MADS { + +extern const char *const kArticleList[9]; + +extern const char *const kCheatingEnabledDesc[3]; + +extern const char *const kLookAroundStr; +extern const char *const kToStr; +extern const char *const kUseStr; +extern const char *const kWalkToStr; +extern const char *const kFenceStr; +extern const char *const kOverStr; + +extern const char *const kGameReleaseInfoStr; +extern const char *const kGameReleaseTitleStr; + +extern const uint32 DEFAULT_VGA_LOW_PALETTE[16]; +extern const uint32 DEFAULT_VGA_HIGH_PALETTE[16]; + +} // End of namespace MADS + +#endif /* MADS_STATICRES_H */ diff --git a/engines/mads/user_interface.cpp b/engines/mads/user_interface.cpp new file mode 100644 index 0000000000..e410d173d7 --- /dev/null +++ b/engines/mads/user_interface.cpp @@ -0,0 +1,1096 @@ +/* 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. + * + */ + +#include "common/scummsys.h" +#include "mads/mads.h" +#include "mads/compression.h" +#include "mads/user_interface.h" +#include "mads/nebular/game_nebular.h" + +namespace MADS { + +UISlot::UISlot() { + _flags = IMG_STATIC; + _segmentId = 0; + _spritesIndex = 0; + _frameNumber = 0; + _width = _height = 0; +} + +/*------------------------------------------------------------------------*/ + +void UISlots::fullRefresh() { + UISlot slot; + slot._flags = IMG_REFRESH; + slot._segmentId = -1; + + push_back(slot); +} + +void UISlots::add(const Common::Rect &bounds) { + assert(size() < 50); + + UISlot ie; + ie._flags = IMG_OVERPRINT; + ie._segmentId = IMG_TEXT_UPDATE; + ie._position = Common::Point(bounds.left, bounds.top); + ie._width = bounds.width(); + ie._height = bounds.height(); + + push_back(ie); +} + +void UISlots::add(const AnimFrameEntry &frameEntry) { + assert(size() < 50); + + UISlot ie; + ie._flags = IMG_UPDATE; + ie._segmentId = frameEntry._seqIndex; + ie._spritesIndex = frameEntry._spriteSlot._spritesIndex; + ie._frameNumber = frameEntry._spriteSlot._frameNumber; + ie._position = frameEntry._spriteSlot._position; + + push_back(ie); +} + +void UISlots::draw(bool updateFlag, bool delFlag) { + Scene &scene = _vm->_game->_scene; + UserInterface &userInterface = scene._userInterface; + DirtyArea *dirtyAreaPtr = nullptr; + + // Loop through setting up the dirty areas + for (uint idx = 0; idx < size(); ++idx) { + DirtyArea &dirtyArea = userInterface._dirtyAreas[idx]; + UISlot &slot = (*this)[idx]; + + if (slot._flags >= IMG_STATIC) { + dirtyArea._active = false; + } else { + dirtyArea.setUISlot(&slot); + dirtyArea._textActive = true; + if (slot._segmentId == IMG_SPINNING_OBJECT && slot._flags == IMG_FULL_UPDATE) { + dirtyArea._active = false; + dirtyAreaPtr = &dirtyArea; + } + } + } + + userInterface._dirtyAreas.merge(1, userInterface._uiSlots.size()); + if (dirtyAreaPtr) + dirtyAreaPtr->_active = true; + + // Copy parts of the user interface background that need to be erased + for (uint idx = 0; idx < size(); ++idx) { + DirtyArea &dirtyArea = userInterface._dirtyAreas[idx]; + UISlot &slot = (*this)[idx]; + + if (dirtyArea._active && dirtyArea._bounds.width() > 0 + && dirtyArea._bounds.height() > 0 && slot._flags > -20) { + + if (slot._flags >= IMG_ERASE) { + // Merge area + userInterface.mergeFrom(&userInterface._surface, dirtyArea._bounds, + Common::Point(dirtyArea._bounds.left, dirtyArea._bounds.top)); + } else { + // Copy area + userInterface._surface.copyTo(&userInterface, dirtyArea._bounds, + Common::Point(dirtyArea._bounds.left, dirtyArea._bounds.top)); + } + } + } + + for (uint idx = 0; idx < size(); ++idx) { + DirtyArea &dirtyArea = userInterface._dirtyAreas[idx]; + UISlot &slot = (*this)[idx]; + + int slotType = slot._flags; + if (slotType >= IMG_STATIC) { + dirtyArea.setUISlot(&slot); + if (!updateFlag) + slotType &= ~0x40; + + dirtyArea._textActive = slotType > 0; + slot._flags &= 0x40; + } + } + + userInterface._dirtyAreas.merge(1, userInterface._uiSlots.size()); + + for (uint idx = 0; idx < size(); ++idx) { + DirtyArea *dirtyArea = &userInterface._dirtyAreas[idx]; + UISlot &slot = (*this)[idx]; + + if (slot._flags >= IMG_STATIC && !(slot._flags & 0x40)) { + if (!dirtyArea->_active) { + do { + dirtyArea = dirtyArea->_mergedArea; + } while (!dirtyArea->_active); + } + + if (dirtyArea->_textActive) { + SpriteAsset *asset = scene._sprites[slot._spritesIndex]; + + // Get the frame details + int frameNumber = ABS(slot._frameNumber); + bool flipped = slot._frameNumber < 0; + + if (slot._segmentId == IMG_SPINNING_OBJECT) { + MSprite *sprite = asset->getFrame(frameNumber); + sprite->copyTo(&userInterface, slot._position, + sprite->getTransparencyIndex()); + } else { + MSprite *sprite = asset->getFrame(frameNumber - 1); + + if (flipped) { + MSurface *spr = sprite->flipHorizontal(); + userInterface.mergeFrom(spr, spr->getBounds(), slot._position, + sprite->getTransparencyIndex()); + delete spr; + } else { + userInterface.mergeFrom(sprite, sprite->getBounds(), slot._position, + sprite->getTransparencyIndex()); + } + } + } + } + } + + // Mark areas of the screen surface for updating + if (updateFlag) { + for (uint idx = 0; idx < size(); ++idx) { + DirtyArea &dirtyArea = userInterface._dirtyAreas[idx]; + + if (dirtyArea._active && dirtyArea._textActive && + dirtyArea._bounds.width() > 0 && dirtyArea._bounds.height() > 0) { + // Flag area of screen as needing update + Common::Rect r = dirtyArea._bounds; + r.translate(0, scene._interfaceY); + _vm->_screen.copyRectToScreen(r); + } + } + } + + // Post-processing to remove slots no longer needed + for (int idx = (int)size() - 1; idx >= 0; --idx) { + UISlot &slot = (*this)[idx]; + + if (slot._flags < IMG_STATIC) { + if (delFlag || updateFlag) + remove_at(idx); + else if (slot._flags > -20) + slot._flags -= 20; + } else { + if (updateFlag) + slot._flags &= ~0x40; + else + slot._flags |= 0x40; + } + } +} + +/*------------------------------------------------------------------------*/ + +MADSEngine *Conversation::_vm; + +void Conversation::init(MADSEngine *vm) { + _vm = vm; +} + +void Conversation::setup(int globalId, ...) { + va_list va; + va_start(va, globalId); + + // Load the list of conversation quotes + _quotes.clear(); + int quoteId = va_arg(va, int); + while (quoteId > 0) { + _quotes.push_back(quoteId); + quoteId = va_arg(va, int); + } + va_end(va); + + if (quoteId < 0) { + // For an ending value of -1, also initial the bitflags for the global + // associated with the conversation entry, which enables all the quote Ids + _vm->_game->globals()[globalId] = (int16)0xffff; + } + + _globalId = globalId; +} + +void Conversation::set(int quoteId, ...) { + _vm->_game->globals()[_globalId] = 0; + + va_list va; + va_start(va, quoteId); + + // Loop through handling each quote + while (quoteId > 0) { + for (uint idx = 0; idx < _quotes.size(); ++idx) { + if (_quotes[idx] == quoteId) { + // Found index, so set that bit in the global keeping track of conversation state + _vm->_game->globals()[_globalId] |= 1 << idx; + break; + } + } + + quoteId = va_arg(va, int); + } + va_end(va); +} + +int Conversation::read(int quoteId) { + uint16 flags = _vm->_game->globals()[_globalId]; + int count = 0; + + for (uint idx = 0; idx < _quotes.size(); ++idx) { + if (flags & (1 << idx)) + ++count; + + if (_quotes[idx] == quoteId) + return flags & (1 << idx); + } + + // Could not find it, simply return number of active quotes + return count; +} + +void Conversation::write(int quoteId, bool flag) { + for (uint idx = 0; idx < _quotes.size(); ++idx) { + if (_quotes[idx] == quoteId) { + // Found index, so set or clear the flag + if (flag) { + // Set bit + _vm->_game->globals()[_globalId] |= 1 << idx; + } else { + // Clear bit + _vm->_game->globals()[_globalId] &= ~(1 << idx); + } + return; + } + } +} + +void Conversation::start() { + UserInterface &userInterface = _vm->_game->_scene._userInterface; + userInterface.emptyConversationList(); + + // Loop through each of the quotes loaded into the conversation + for (uint idx = 0; idx < _quotes.size(); ++idx) { + // Check whether the given quote is enabled or not + if (_vm->_game->globals()[_globalId] & (1 << idx)) { + // Quote enabled, so add it to the list of talk selections + Common::String msg = _vm->_game->getQuote(_quotes[idx]); + userInterface.addConversationMessage(_quotes[idx], msg); + } + } + + userInterface.setup(kInputConversation); +} + +/*------------------------------------------------------------------------*/ + +UserInterface::UserInterface(MADSEngine *vm) : _vm(vm), _dirtyAreas(vm), + _uiSlots(vm) { + _invSpritesIndex = -1; + _invFrameNumber = 1; + _scrollMilli = 0; + _scrollFlag = false; + _category = CAT_NONE; + _inventoryTopIndex = 0; + _selectedInvIndex = -1; + _selectedActionIndex = 0; + _selectedItemVocabIdx = -1; + _scrollbarActive = SCROLLBAR_NONE; + _scrollbarOldActive = SCROLLBAR_NONE; + _scrollbarStrokeType = SCROLLBAR_NONE; + _scrollbarQuickly = false; + _scrollbarMilliTime = 0; + _scrollbarElevator = _scrollbarOldElevator = 0; + _highlightedCommandIndex = -1; + _highlightedInvIndex = -1; + _highlightedItemVocabIndex = -1; + _dirtyAreas.resize(50); + _inventoryChanged = false; + _noSegmentsActive = 0; + _someSegmentsActive = 0; + _rectP = nullptr; + + Common::fill(&_categoryIndexes[0], &_categoryIndexes[7], 0); + + // Map the user interface to the bottom of the game's screen surface + byte *pData = _vm->_screen.getBasePtr(0, MADS_SCENE_HEIGHT); + setPixels(pData, MADS_SCREEN_WIDTH, MADS_INTERFACE_HEIGHT); + + _surface.setSize(MADS_SCREEN_WIDTH, MADS_INTERFACE_HEIGHT); +} + +void UserInterface::load(const Common::String &resName) { + File f(resName); + MadsPack madsPack(&f); + + // Load in the palette + Common::SeekableReadStream *palStream = madsPack.getItemStream(0); + + uint32 *gamePalP = &_vm->_palette->_palFlags[0]; + byte *palP = &_vm->_palette->_mainPalette[0]; + + for (int i = 0; i < 16; ++i, gamePalP++, palP += 3) { + RGB6 rgb; + rgb.load(palStream); + palP[0] = rgb.r; + palP[1] = rgb.g; + palP[2] = rgb.b; + *gamePalP |= 1; + } + delete palStream; + + // Read in the surface data + Common::SeekableReadStream *pixelsStream = madsPack.getItemStream(1); + pixelsStream->read(_surface.getData(), MADS_SCREEN_WIDTH * MADS_INTERFACE_HEIGHT); + delete pixelsStream; +} + +void UserInterface::setup(InputMode inputMode) { + Scene &scene = _vm->_game->_scene; + + if (_vm->_game->_screenObjects._inputMode != inputMode) { + Common::String resName = _vm->_game->_aaName; + + // Strip off any extension + const char *p = strchr(resName.c_str(), '.'); + if (p) { + resName = Common::String(resName.c_str(), p); + } + + // Add on suffix if necessary + if (inputMode != kInputBuildingSentences) + resName += "A"; + + resName += ".INT"; + + load(resName); + _surface.copyTo(this); + } + _vm->_game->_screenObjects._inputMode = inputMode; + + scene._userInterface._uiSlots.clear(); + scene._userInterface._uiSlots.fullRefresh(); + _vm->_game->_screenObjects._baseTime = _vm->_events->getFrameCounter(); + _highlightedCommandIndex = -1; + _highlightedItemVocabIndex = -1; + _highlightedInvIndex = -1; + + if (_vm->_game->_kernelMode == KERNEL_ACTIVE_CODE) + scene._userInterface._uiSlots.draw(false, false); + + scene._action.clear(); + drawTextElements(); + loadElements(); + scene._dynamicHotspots.refresh(); +} + +void UserInterface::drawTextElements() { + if (_vm->_game->_screenObjects._inputMode) { + drawConversationList(); + } else { + // Draw the actions + drawActions(); + drawInventoryList(); + drawItemVocabList(); + } +} + +void UserInterface::mergeFrom(MSurface *src, const Common::Rect &srcBounds, + const Common::Point &destPos, int transparencyIndex) { + // Validation of the rectangle and position + int destX = destPos.x, destY = destPos.y; + if ((destX >= w) || (destY >= h)) + return; + + Common::Rect copyRect = srcBounds; + if (destX < 0) { + copyRect.left += -destX; + destX = 0; + } else if (destX + copyRect.width() > w) { + copyRect.right -= destX + copyRect.width() - w; + } + if (destY < 0) { + copyRect.top += -destY; + destY = 0; + } else if (destY + copyRect.height() > h) { + copyRect.bottom -= destY + copyRect.height() - h; + } + + if (!copyRect.isValidRect()) + return; + + // Copy the specified area + + byte *data = src->getData(); + byte *srcPtr = data + (src->getWidth() * copyRect.top + copyRect.left); + byte *destPtr = (byte *)this->pixels + (destY * getWidth()) + destX; + + for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) { + // Process each line of the area + for (int xCtr = 0; xCtr < copyRect.width(); ++xCtr) { + // Check for the range used for the user interface background, + // which are the only pixels that can be replaced + if ((destPtr[xCtr] >= 8 && destPtr[xCtr] <= 15) && (int)srcPtr[xCtr] != transparencyIndex) + destPtr[xCtr] = srcPtr[xCtr]; + } + + srcPtr += src->getWidth(); + destPtr += getWidth(); + } +} + +void UserInterface::drawActions() { + for (int idx = 0; idx < 10; ++idx) { + writeVocab(CAT_COMMAND, idx); + } +} + +void UserInterface::drawInventoryList() { + int endIndex = MIN((int)_vm->_game->_objects._inventoryList.size(), _inventoryTopIndex + 5); + for (int idx = _inventoryTopIndex; idx < endIndex; ++idx) { + writeVocab(CAT_INV_LIST, idx); + } +} + +void UserInterface::drawItemVocabList() { + if (_selectedInvIndex >= 0) { + InventoryObject &io = _vm->_game->_objects[ + _vm->_game->_objects._inventoryList[_selectedInvIndex]]; + for (int idx = 0; idx < io._vocabCount; ++idx) { + writeVocab(CAT_INV_VOCAB, idx); + } + } +} + +void UserInterface::drawScrolller() { + if (_scrollbarActive) + writeVocab(CAT_INV_SCROLLER, _scrollbarActive); + writeVocab(CAT_INV_SCROLLER, 4); +} + +void UserInterface::updateInventoryScroller() { + ScreenObjects &screenObjects = _vm->_game->_screenObjects; + Common::Array<int> &inventoryList = _vm->_game->_objects._inventoryList; + + if (screenObjects._inputMode != kInputBuildingSentences) + return; + + _scrollbarActive = SCROLLBAR_NONE; + + if ((screenObjects._category == CAT_INV_SCROLLER) || (screenObjects._category != CAT_INV_SCROLLER + && _scrollbarOldActive == SCROLLBAR_ELEVATOR && _vm->_events->_mouseStatusCopy)) { + if (_vm->_events->_mouseStatusCopy || _vm->_easyMouse) { + if ((_vm->_events->_mouseClicked || (_vm->_easyMouse && !_vm->_events->_mouseStatusCopy)) + && (screenObjects._category == CAT_INV_SCROLLER)) + _scrollbarStrokeType = (ScrollbarActive)screenObjects._spotId; + + if (screenObjects._spotId == _scrollbarStrokeType || _scrollbarOldActive == SCROLLBAR_ELEVATOR) { + _scrollbarActive = _scrollbarStrokeType; + uint32 currentMilli = g_system->getMillis(); + uint32 timeInc = _scrollbarQuickly ? 100 : 380; + + if (_vm->_events->_mouseStatus && (_scrollbarMilliTime + timeInc) <= currentMilli) { + _scrollbarQuickly = _vm->_events->_vD2 < 1; + _scrollbarMilliTime = currentMilli; + + switch (_scrollbarStrokeType) { + case SCROLLBAR_UP: + // Scroll up + if (_inventoryTopIndex > 0 && inventoryList.size() > 0) { + --_inventoryTopIndex; + _inventoryChanged = true; + } + break; + + case SCROLLBAR_DOWN: + // Scroll down + if (_inventoryTopIndex < ((int)inventoryList.size() - 1) && inventoryList.size() > 1) { + ++_inventoryTopIndex; + _inventoryChanged = true; + } + break; + + case SCROLLBAR_ELEVATOR: { + // Inventory slider + int newIndex = CLIP((int)_vm->_events->currentPos().y - 170, 0, 17) + * inventoryList.size() / 10; + if (newIndex >= (int)inventoryList.size()) + newIndex = inventoryList.size() - 1; + + if (inventoryList.size() > 0) { + _inventoryChanged = newIndex != _inventoryTopIndex; + _inventoryTopIndex = newIndex; + } + break; + } + + default: + break; + } + + if (_inventoryChanged) { + int dummy; + updateSelection(CAT_INV_LIST, 0, &dummy); + } + } + } + } + } + + if (_scrollbarActive != _scrollbarOldActive || _scrollbarElevator != _scrollbarOldElevator) + scrollbarChanged(); + + _scrollbarOldActive = _scrollbarActive; + _scrollbarOldElevator = _scrollbarElevator; +} + +void UserInterface::scrollbarChanged() { + Common::Rect r(73, 4, 73 + 9, 4 + 38); + _uiSlots.add(r); + _uiSlots.draw(false, false); + drawScrolller(); + updateRect(r); +} + +void UserInterface::writeVocab(ScrCategory category, int id) { + Common::Rect bounds; + if (!getBounds(category, id, bounds)) + return; + + Scene &scene = _vm->_game->_scene; + Font *font = nullptr; + + int vocabId; + Common::String vocabStr; + switch (category) { + case CAT_COMMAND: + font = _vm->_font->getFont(FONT_INTERFACE); + vocabId = scene._verbList[id]._id; + if (id == _highlightedCommandIndex) { + _vm->_font->setColorMode(SELMODE_HIGHLIGHTED); + } else { + _vm->_font->setColorMode(id == _selectedActionIndex ? SELMODE_SELECTED : SELMODE_UNSELECTED); + } + vocabStr = scene.getVocab(vocabId); + vocabStr.setChar(toupper(vocabStr[0]), 0); + font->writeString(this, vocabStr, Common::Point(bounds.left, bounds.top)); + break; + + case CAT_INV_LIST: + font = _vm->_font->getFont(FONT_INTERFACE); + vocabId = _vm->_game->_objects.getItem(id)._descId; + if (id == _highlightedInvIndex) { + _vm->_font->setColorMode(SELMODE_HIGHLIGHTED); + } else { + _vm->_font->setColorMode(id == _selectedInvIndex ? SELMODE_SELECTED : SELMODE_UNSELECTED); + } + + vocabStr = scene.getVocab(vocabId); + vocabStr.setChar(toupper(vocabStr[0]), 0); + font->writeString(this, vocabStr, Common::Point(bounds.left, bounds.top)); + break; + + case CAT_TALK_ENTRY: + font = _vm->_font->getFont(FONT_INTERFACE); + font->setColorMode(id == _highlightedCommandIndex ? SELMODE_HIGHLIGHTED : SELMODE_UNSELECTED); + font->writeString(this, _talkStrings[id], Common::Point(bounds.left, bounds.top)); + break; + + case CAT_INV_SCROLLER: + font = _vm->_font->getFont(FONT_MISC); + + switch (id) { + case 1: + vocabStr = "a"; + break; + case 2: + vocabStr = "b"; + break; + case 3: + vocabStr = "d"; + break; + case 4: + vocabStr = "c"; + break; + default: + break; + } + + font->setColorMode((id == 4) || (_scrollbarActive == SCROLLBAR_ELEVATOR) ? + SELMODE_HIGHLIGHTED : SELMODE_UNSELECTED); + font->writeString(this, vocabStr, Common::Point(bounds.left, bounds.top)); + break; + default: + // Item specific verbs + font = _vm->_font->getFont(FONT_INTERFACE); + vocabId = _vm->_game->_objects.getItem(_selectedInvIndex)._vocabList[id]._vocabId; + if (id == _highlightedItemVocabIndex) { + _vm->_font->setColorMode(SELMODE_HIGHLIGHTED); + } else { + _vm->_font->setColorMode(id == _selectedInvIndex ? SELMODE_SELECTED : SELMODE_UNSELECTED); + vocabStr = scene.getVocab(vocabId); + vocabStr.setChar(toupper(vocabStr[0]), 0); + font->writeString(this, vocabStr, Common::Point(bounds.left, bounds.top)); + break; + } + break; + } +} + +void UserInterface::loadElements() { + Scene &scene = _vm->_game->_scene; + Common::Rect bounds; + _vm->_game->_screenObjects.clear(); + + if (_vm->_game->_screenObjects._inputMode == kInputBuildingSentences) { + // Set up screen objects for the inventory scroller + for (int idx = 1; idx <= 3; ++idx) { + getBounds(CAT_INV_SCROLLER, idx, bounds); + moveRect(bounds); + + _vm->_game->_screenObjects.add(bounds, LAYER_GUI, CAT_INV_SCROLLER, idx); + } + + // Set up actions + _categoryIndexes[CAT_COMMAND - 1] = _vm->_game->_screenObjects.size() + 1; + for (int idx = 0; idx < 10; ++idx) { + getBounds(CAT_COMMAND, idx, bounds); + moveRect(bounds); + + _vm->_game->_screenObjects.add(bounds, LAYER_GUI, CAT_COMMAND, idx); + } + + // Set up inventory list + _categoryIndexes[CAT_INV_LIST - 1] = _vm->_game->_screenObjects.size() + 1; + for (int idx = 0; idx < 5; ++idx) { + getBounds(CAT_INV_LIST, idx, bounds); + moveRect(bounds); + + _vm->_game->_screenObjects.add(bounds, LAYER_GUI, CAT_INV_LIST, idx); + } + + // Set up the inventory vocab list + _categoryIndexes[CAT_INV_VOCAB - 1] = _vm->_game->_screenObjects.size() + 1; + for (int idx = 0; idx < 5; ++idx) { + getBounds(CAT_INV_VOCAB, idx, bounds); + moveRect(bounds); + + _vm->_game->_screenObjects.add(bounds, LAYER_GUI, CAT_INV_VOCAB, idx); + } + + // Set up the inventory item picture + _categoryIndexes[CAT_INV_ANIM - 1] = _vm->_game->_screenObjects.size() + 1; + _vm->_game->_screenObjects.add(Common::Rect(160, 159, 231, 194), LAYER_GUI, + CAT_INV_ANIM, 0); + } + + if (_vm->_game->_screenObjects._inputMode == kInputBuildingSentences || + _vm->_game->_screenObjects._inputMode == kInputLimitedSentences) { + _categoryIndexes[CAT_HOTSPOT - 1] = _vm->_game->_screenObjects.size() + 1; + for (int hotspotIdx = scene._hotspots.size() - 1; hotspotIdx >= 0; --hotspotIdx) { + Hotspot &hs = scene._hotspots[hotspotIdx]; + _vm->_game->_screenObjects.add(hs._bounds, LAYER_GUI, CAT_HOTSPOT, hotspotIdx); + } + } + + if (_vm->_game->_screenObjects._inputMode == kInputConversation) { + // setup areas for talk entries + _categoryIndexes[CAT_TALK_ENTRY - 1] = _vm->_game->_screenObjects.size() + 1; + for (int idx = 0; idx < 5; ++idx) { + getBounds(CAT_TALK_ENTRY, idx, bounds); + moveRect(bounds); + + _vm->_game->_screenObjects.add(bounds, LAYER_GUI, CAT_TALK_ENTRY, idx); + } + } + + // Store the number of UI elements loaded for easy nuking/refreshing hotspots added later + _vm->_game->_screenObjects._uiCount = _vm->_game->_screenObjects.size(); +} + +bool UserInterface::getBounds(ScrCategory category, int v, Common::Rect &bounds) { + int heightMultiplier, widthMultiplier; + int leftStart, yOffset, widthAmt; + + switch (category) { + case CAT_COMMAND: + heightMultiplier = v % 5; + widthMultiplier = v / 5; + leftStart = 2; + yOffset = 3; + widthAmt = 32; + break; + + case CAT_INV_LIST: + if (v < _inventoryTopIndex || v >= (_inventoryTopIndex + 5)) + return false; + + heightMultiplier = v - _inventoryTopIndex; + widthMultiplier = 0; + leftStart = 90; + yOffset = 3; + widthAmt = 69; + break; + + case CAT_TALK_ENTRY: + heightMultiplier = v; + widthMultiplier = 0; + leftStart = 2; + yOffset = 3; + widthAmt = 310; + break; + + case CAT_INV_SCROLLER: + heightMultiplier = 0; + widthMultiplier = 0; + yOffset = 0; + widthAmt = 9; + leftStart = (v != 73) ? 73 : 75; + break; + + default: + heightMultiplier = v; + widthMultiplier = 0; + leftStart = 240; + yOffset = 3; + widthAmt = 80; + break; + } + + bounds.left = (widthMultiplier > 0) ? widthMultiplier * widthAmt + leftStart : leftStart; + bounds.setWidth(widthAmt); + bounds.top = heightMultiplier * 8 + yOffset; + bounds.setHeight(8); + + if (category == CAT_INV_SCROLLER) { + switch (v) { + case SCROLLBAR_UP: + // Arrow up + bounds.top = 4; + bounds.setHeight(7); + break; + case SCROLLBAR_DOWN: + // Arrow down + bounds.top = 35; + bounds.setHeight(7); + break; + case SCROLLBAR_ELEVATOR: + // Scroller + bounds.top = 12; + bounds.setHeight(22); + break; + case SCROLLBAR_THUMB: + // Thumb + bounds.top = _scrollbarElevator + 14; + bounds.setHeight(1); + break; + default: + break; + } + } + + return true; +} + +void UserInterface::moveRect(Common::Rect &bounds) { + bounds.translate(0, MADS_SCENE_HEIGHT); +} + +void UserInterface::drawConversationList() { + for (uint idx = 0; idx < _talkStrings.size(); ++idx) { + writeVocab(CAT_TALK_ENTRY, idx); + } +} + +void UserInterface::emptyConversationList() { + _talkStrings.clear(); + _talkIds.clear(); +} + +void UserInterface::addConversationMessage(int vocabId, const Common::String &msg) { + assert(_talkStrings.size() < 5); + + _talkStrings.push_back(msg); + _talkIds.push_back(vocabId); +} + +void UserInterface::loadInventoryAnim(int objectId) { + Scene &scene = _vm->_game->_scene; + noInventoryAnim(); + + if (_vm->_invObjectsAnimated) { + Common::String resName = Common::String::format("*OB%.3dI", objectId); + SpriteAsset *asset = new SpriteAsset(_vm, resName, 8); + _invSpritesIndex = scene._sprites.add(asset, 1); + if (_invSpritesIndex >= 0) { + _invFrameNumber = 1; + } + } +} + +void UserInterface::noInventoryAnim() { + Scene &scene = _vm->_game->_scene; + + if (_invSpritesIndex >= 0) { + scene._sprites.remove(_invSpritesIndex); + _vm->_game->_screenObjects._baseTime = _vm->_events->getFrameCounter(); + _invSpritesIndex = -1; + } + + if (_vm->_game->_screenObjects._inputMode == kInputBuildingSentences) + refresh(); +} + +void UserInterface::refresh() { + _uiSlots.clear(); + _uiSlots.fullRefresh(); + _uiSlots.draw(false, false); + + drawTextElements(); +} + +void UserInterface::inventoryAnim() { + Scene &scene = _vm->_game->_scene; + if (_vm->_game->_screenObjects._inputMode == kInputConversation || + _vm->_game->_screenObjects._inputMode == kInputLimitedSentences || + _invSpritesIndex < 0) + return; + + // Move to the next frame number in the sequence, resetting if at the end + SpriteAsset *asset = scene._sprites[_invSpritesIndex]; + if (++_invFrameNumber > asset->getCount()) + _invFrameNumber = 1; + + // Loop through the slots list for inventory animation entry + for (uint i = 0; i < _uiSlots.size(); ++i) { + if (_uiSlots[i]._segmentId == IMG_SPINNING_OBJECT) + _uiSlots[i]._flags = IMG_FULL_UPDATE; + } + + // Add a new slot entry for the inventory animation + UISlot slot; + slot._flags = IMG_UPDATE; + slot._segmentId = IMG_SPINNING_OBJECT; + slot._frameNumber = _invFrameNumber; + slot._spritesIndex = _invSpritesIndex; + slot._position = Common::Point(160, 3); + + _uiSlots.push_back(slot); +} + +void UserInterface::doBackgroundAnimation() { + Scene &scene = _vm->_game->_scene; + Common::Array<AnimUIEntry> &uiEntries = scene._animationData->_uiEntries; + Common::Array<AnimFrameEntry> &frameEntries = scene._animationData->_frameEntries; + + _noSegmentsActive = !_someSegmentsActive; + _someSegmentsActive = false; + + for (int idx = 0; idx < (int)uiEntries.size(); ++idx) { + AnimUIEntry &uiEntry = uiEntries[idx]; + + if (uiEntry._counter < 0) { + if (uiEntry._counter == -1) { + int probabilityRandom = _vm->getRandomNumber(1, 30000); + int probability = uiEntry._probability; + if (uiEntry._probability > 30000) { + if (_noSegmentsActive) { + probability -= 30000; + } else { + probability = -1; + } + } + if (probabilityRandom <= probability) { + uiEntry._counter = uiEntry._firstImage; + _someSegmentsActive = true; + } + } else { + uiEntry._counter = uiEntry._firstImage; + _someSegmentsActive = true; + } + } else { + for (int idx2 = 0; idx2 < ANIM_SPAWN_COUNT; idx2++) { + if (uiEntry._spawnFrame[idx2] == (uiEntry._counter - uiEntry._firstImage)) { + int tempIndex = uiEntry._spawn[idx2]; + if (idx >= tempIndex) { + uiEntries[tempIndex]._counter = uiEntries[tempIndex]._firstImage; + } else { + uiEntries[tempIndex]._counter = -2; + } + _someSegmentsActive = true; + } + } + + ++uiEntry._counter; + if (uiEntry._counter > uiEntry._lastImage) { + uiEntry._counter = -1; + } else { + _someSegmentsActive = true; + } + } + } + + for (uint idx = 0; idx < uiEntries.size(); ++idx) { + int imgScan = uiEntries[idx]._counter; + if (imgScan >= 0) { + _uiSlots.add(frameEntries[imgScan]); + } + } +} + +void UserInterface::categoryChanged() { + _highlightedInvIndex = -1; + _vm->_events->initVars(); + _category = CAT_NONE; +} + +void UserInterface::selectObject(int invIndex) { + if (_selectedInvIndex != invIndex || _inventoryChanged) { + int oldVocabCount = _selectedInvIndex < 0 ? 0 : _vm->_game->_objects.getItem(_selectedInvIndex)._vocabCount; + int newVocabCount = invIndex < 0 ? 0 : _vm->_game->_objects.getItem(invIndex)._vocabCount; + int maxVocab = MAX(oldVocabCount, newVocabCount); + + updateSelection(CAT_INV_LIST, invIndex, &_selectedInvIndex); + _highlightedItemVocabIndex = -1; + _selectedItemVocabIdx = -1; + + if (maxVocab) { + assert(_uiSlots.size() < 50); + int vocabHeight = maxVocab * 8; + + Common::Rect bounds(240, 3, 240 + 80, 3 + vocabHeight); + _uiSlots.add(bounds); + _uiSlots.draw(false, false); + drawItemVocabList(); + updateRect(bounds); + } + } + + if (invIndex == -1) { + noInventoryAnim(); + } else { + loadInventoryAnim(_vm->_game->_objects._inventoryList[invIndex]); + _vm->_palette->setPalette(_vm->_palette->_mainPalette, 7, 1); + _vm->_palette->setPalette(_vm->_palette->_mainPalette, 246, 2); + } +} + +void UserInterface::updateSelection(ScrCategory category, int newIndex, int *idx) { + Game &game = *_vm->_game; + Common::Array<int> &invList = game._objects._inventoryList; + Common::Rect bounds; + + if (category == CAT_INV_LIST && _inventoryChanged) { + *idx = newIndex; + bounds = Common::Rect(90, 3, 90 + 69, 3 + 40); + _uiSlots.add(bounds); + _uiSlots.draw(false, false); + drawInventoryList(); + updateRect(bounds); + _inventoryChanged = false; + + if (invList.size() < 2) { + _scrollbarElevator = 0; + } else { + int v = _inventoryTopIndex * 18 / (invList.size() - 1); + _scrollbarElevator = MIN(v, 17); + } + } else { + int oldIndex = *idx; + *idx = newIndex; + + if (oldIndex >= 0) { + writeVocab(category, oldIndex); + + if (getBounds(category, oldIndex, bounds)) + updateRect(bounds); + } + + if (newIndex >= 0) { + writeVocab(category, newIndex); + + if (getBounds(category, newIndex, bounds)) + updateRect(bounds); + } + } +} + +void UserInterface::updateRect(const Common::Rect &bounds) { + Common::Rect r = bounds; + r.translate(0, MADS_SCENE_HEIGHT); + _vm->_screen.copyRectToScreen(r); +} + +void UserInterface::scrollerChanged() { + warning("TODO: scrollerChanged"); +} + +void UserInterface::scrollInventory() { + Common::Array<int> &invList = _vm->_game->_objects._inventoryList; + + if (_vm->_events->_mouseButtons) { + int yp = _vm->_events->currentPos().y; + if (yp < MADS_SCENE_HEIGHT || yp == (MADS_SCREEN_HEIGHT - 1)) { + uint32 timeDiff = _scrollFlag ? 100 : 380; + uint32 currentMilli = g_system->getMillis(); + _vm->_game->_screenObjects._v8332A = -1; + + if (currentMilli >= (_scrollMilli + timeDiff)) { + _scrollMilli = currentMilli; + _scrollFlag = true; + + if (yp == (MADS_SCREEN_HEIGHT - 1)) { + if (_inventoryTopIndex < ((int)invList.size() - 1)) { + ++_inventoryTopIndex; + _inventoryChanged = true; + } + } else { + if (_inventoryTopIndex > 0) { + --_inventoryTopIndex; + _inventoryChanged = true; + } + } + } + } + } + + _vm->_game->_screenObjects._v8332A = 0; +} + +void UserInterface::synchronize(Common::Serializer &s) { + InventoryObjects &invObjects = _vm->_game->_objects; + + if (s.isLoading()) { + _selectedInvIndex = invObjects._inventoryList.empty() ? -1 : 0; + } + + for (int i = 0; i < 8; ++i) + s.syncAsSint16LE(_categoryIndexes[i]); +} + +} // End of namespace MADS diff --git a/engines/mads/user_interface.h b/engines/mads/user_interface.h new file mode 100644 index 0000000000..827fa3041f --- /dev/null +++ b/engines/mads/user_interface.h @@ -0,0 +1,306 @@ +/* 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. + * + */ + +#ifndef MADS_USER_INTERFACE_H +#define MADS_USER_INTERFACE_H + +#include "common/scummsys.h" +#include "common/rect.h" +#include "common/str.h" +#include "mads/msurface.h" +#include "mads/screen.h" + +namespace MADS { + +enum { IMG_SPINNING_OBJECT = 200, IMG_TEXT_UPDATE = 201 }; + +enum ScrollbarActive { + SCROLLBAR_NONE = 0, // No state + SCROLLBAR_UP = 1, // Up butotn + SCROLLBAR_DOWN = 2, // Down button + SCROLLBAR_ELEVATOR = 3, // Elevator bar + SCROLLBAR_THUMB = 4 // Scrollbar thumb +}; + +class AnimFrameEntry; +class MADSEngine; + +class UISlot { +public: + int _flags; + int _segmentId; + int _spritesIndex; + int _frameNumber; + Common::Point _position; + + // Only used for IMG_OVERPRINT + int _width; + int _height; + + UISlot(); +}; + +/** + * Sprite list for the user interface + */ +class UISlots : public Common::Array<UISlot> { +private: + MADSEngine *_vm; +public: + /** + * Constructor + */ + UISlots(MADSEngine *vm) : _vm(vm) {} + + /** + * Add an overprint (text) entry to the list + */ + void add(const Common::Rect &bounds); + + /** + * Loads the data from an aimation frame entry + */ + void add(const AnimFrameEntry &frameEntry); + + /** + * Adds a special entry for full refresh of the user interface + */ + void fullRefresh(); + + /** + * Draw all the sprites in the list on the user interface. + * @param updateFlag Flag drawn areas to be updated on physical screen + * @param delFlag Controls how used slots are deleted after drawing + */ + void draw(bool updateFlag, bool delFlag); +}; + +class Conversation { +private: + static MADSEngine *_vm; +public: + static void init(MADSEngine *vm); +public: + int _globalId; + Common::Array<int> _quotes; + + /** + * Set up a conversation sequence + */ + void setup(int globalId, ...); + + /** + * Activates the passed set of quotes in the given conversation node + */ + void set(int quoteId, ...); + + /** + * Returns the bit for a given quote to indicate whether it's active or not or, + * if 0 is passed, returns the number of currently active quotes + */ + int read(int quoteId); + + /** + * Activates or deactivates the specified quote in the given conversation node + */ + void write(int quoteId, bool flag); + + /** + * Starts the conversation + */ + void start(); +}; + +class UserInterface : public MSurface { + friend class UISlots; +private: + MADSEngine *_vm; + int _invSpritesIndex; + int _invFrameNumber; + uint32 _scrollMilli; + bool _scrollFlag; + int _noSegmentsActive; + int _someSegmentsActive; + ScrollbarActive _scrollbarStrokeType; + + /** + * Loads the elements of the user interface + */ + void loadElements(); + + /** + * Returns the area within the user interface a given element falls + */ + bool getBounds(ScrCategory category, int invIndex, Common::Rect &bounds); + + /** + * Reposition a bounding rectangle to physical co-ordinates + */ + void moveRect(Common::Rect &bounds); + + /** + * Draw options during a conversation. + */ + void drawConversationList(); + + /** + * Draw the action list + */ + void drawActions(); + + /** + * Draw the inventory list + */ + void drawInventoryList(); + + /** + * Draw the inventory item vocab list + */ + void drawItemVocabList(); + + /** + * Draw the inventory scroller + */ + void drawScrolller(); + + /** + * Called when the inventory scrollbar has changed + */ + void scrollbarChanged(); + + /** + * Draw a UI textual element + */ + void writeVocab(ScrCategory category, int id); + + void refresh(); + + void updateRect(const Common::Rect &bounds); +public: + MSurface _surface; + UISlots _uiSlots; + DirtyAreas _dirtyAreas; + ScrCategory _category; + Common::Rect *_rectP; + int _inventoryTopIndex; + int _selectedInvIndex; + int _selectedActionIndex; + int _selectedItemVocabIdx; + ScrollbarActive _scrollbarActive, _scrollbarOldActive; + int _highlightedCommandIndex; + int _highlightedInvIndex; + int _highlightedItemVocabIndex; + bool _inventoryChanged; + int _categoryIndexes[8]; + Common::StringArray _talkStrings; + Common::Array<int> _talkIds; + bool _scrollbarQuickly; + uint32 _scrollbarMilliTime; + int _scrollbarElevator, _scrollbarOldElevator; +public: + /** + * Constructor + */ + UserInterface(MADSEngine *vm); + + /** + * Loads an interface from a specified resource + */ + void load(const Common::String &resName); + + /** + * Set up the interface + */ + void setup(InputMode inputMode); + + void drawTextElements(); + + /** + * Merges a sub-section of another surface into the user interface without + * destroying any on-screen text + * @param src Source surface + * @param srcBounds Area to copy/merge from + * @param destPos Destination position to draw in current surface + * @param transparencyIndex Transparency color + */ + void mergeFrom(MSurface *src, const Common::Rect &srcBounds, const Common::Point &destPos, + int transparencyIndex = -1); + + /** + * Loads the animation sprite data for a given inventory object + */ + void loadInventoryAnim(int objectId); + + /** + * Resets the inventory animation when no inventory item is selected + */ + void noInventoryAnim(); + + /** + * Handles any animation that occurs in the background of the user interface + */ + void doBackgroundAnimation(); + + /** + * Handles queuing a new frame of an inventory animation for drawing + */ + void inventoryAnim(); + + void categoryChanged(); + + /** + * Select an item from the inventory list + * @param invIndex Index in the inventory list of the item to select + */ + void selectObject(int invIndex); + + void updateSelection(ScrCategory category, int newIndex, int *idx); + + void scrollerChanged(); + + void scrollInventory(); + + /** + * Checks for the mouse being on the user interface inventory scroller, + * and update the scroller highlight and selected inventory object as necessary + */ + void updateInventoryScroller(); + + /** + * Empties the current conversation talk list + */ + void emptyConversationList(); + + /** + * Add a msesage to the list of conversation items to select from + */ + void addConversationMessage(int vocabId, const Common::String &msg); + + /** + * Synchronize the data + */ + void synchronize(Common::Serializer &s); +}; + +} // End of namespace MADS + +#endif /* MADS_USER_INTERFACE_H */ diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp index 2e83eb3328..d49f3e8637 100644 --- a/engines/mohawk/console.cpp +++ b/engines/mohawk/console.cpp @@ -49,20 +49,20 @@ namespace Mohawk { #ifdef ENABLE_MYST MystConsole::MystConsole(MohawkEngine_Myst *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("changeCard", WRAP_METHOD(MystConsole, Cmd_ChangeCard)); - DCmd_Register("curCard", WRAP_METHOD(MystConsole, Cmd_CurCard)); - DCmd_Register("var", WRAP_METHOD(MystConsole, Cmd_Var)); - DCmd_Register("curStack", WRAP_METHOD(MystConsole, Cmd_CurStack)); - DCmd_Register("changeStack", WRAP_METHOD(MystConsole, Cmd_ChangeStack)); - DCmd_Register("drawImage", WRAP_METHOD(MystConsole, Cmd_DrawImage)); - DCmd_Register("drawRect", WRAP_METHOD(MystConsole, Cmd_DrawRect)); - DCmd_Register("setResourceEnable", WRAP_METHOD(MystConsole, Cmd_SetResourceEnable)); - DCmd_Register("playSound", WRAP_METHOD(MystConsole, Cmd_PlaySound)); - DCmd_Register("stopSound", WRAP_METHOD(MystConsole, Cmd_StopSound)); - DCmd_Register("playMovie", WRAP_METHOD(MystConsole, Cmd_PlayMovie)); - DCmd_Register("disableInitOpcodes", WRAP_METHOD(MystConsole, Cmd_DisableInitOpcodes)); - DCmd_Register("cache", WRAP_METHOD(MystConsole, Cmd_Cache)); - DCmd_Register("resources", WRAP_METHOD(MystConsole, Cmd_Resources)); + registerCmd("changeCard", WRAP_METHOD(MystConsole, Cmd_ChangeCard)); + registerCmd("curCard", WRAP_METHOD(MystConsole, Cmd_CurCard)); + registerCmd("var", WRAP_METHOD(MystConsole, Cmd_Var)); + registerCmd("curStack", WRAP_METHOD(MystConsole, Cmd_CurStack)); + registerCmd("changeStack", WRAP_METHOD(MystConsole, Cmd_ChangeStack)); + registerCmd("drawImage", WRAP_METHOD(MystConsole, Cmd_DrawImage)); + registerCmd("drawRect", WRAP_METHOD(MystConsole, Cmd_DrawRect)); + registerCmd("setResourceEnable", WRAP_METHOD(MystConsole, Cmd_SetResourceEnable)); + registerCmd("playSound", WRAP_METHOD(MystConsole, Cmd_PlaySound)); + registerCmd("stopSound", WRAP_METHOD(MystConsole, Cmd_StopSound)); + registerCmd("playMovie", WRAP_METHOD(MystConsole, Cmd_PlayMovie)); + registerCmd("disableInitOpcodes", WRAP_METHOD(MystConsole, Cmd_DisableInitOpcodes)); + registerCmd("cache", WRAP_METHOD(MystConsole, Cmd_Cache)); + registerCmd("resources", WRAP_METHOD(MystConsole, Cmd_Resources)); } MystConsole::~MystConsole() { @@ -70,7 +70,7 @@ MystConsole::~MystConsole() { bool MystConsole::Cmd_ChangeCard(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: changeCard <card>\n"); + debugPrintf("Usage: changeCard <card>\n"); return true; } @@ -81,20 +81,20 @@ bool MystConsole::Cmd_ChangeCard(int argc, const char **argv) { } bool MystConsole::Cmd_CurCard(int argc, const char **argv) { - DebugPrintf("Current Card: %d\n", _vm->getCurCard()); + debugPrintf("Current Card: %d\n", _vm->getCurCard()); return true; } bool MystConsole::Cmd_Var(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: var <var> (<value>)\n"); + debugPrintf("Usage: var <var> (<value>)\n"); return true; } if (argc > 2) _vm->_scriptParser->setVarValue((uint16)atoi(argv[1]), (uint16)atoi(argv[2])); - DebugPrintf("%d = %d\n", (uint16)atoi(argv[1]), _vm->_scriptParser->getVar((uint16)atoi(argv[1]))); + debugPrintf("%d = %d\n", (uint16)atoi(argv[1]), _vm->_scriptParser->getVar((uint16)atoi(argv[1]))); return true; } @@ -130,19 +130,19 @@ static const uint16 default_start_card[12] = { }; bool MystConsole::Cmd_CurStack(int argc, const char **argv) { - DebugPrintf("Current Stack: %s\n", mystStackNames[_vm->getCurStack()]); + debugPrintf("Current Stack: %s\n", mystStackNames[_vm->getCurStack()]); return true; } bool MystConsole::Cmd_ChangeStack(int argc, const char **argv) { if (argc != 2 && argc != 3) { - DebugPrintf("Usage: changeStack <stack> [<card>]\n\n"); - DebugPrintf("Stacks:\n=======\n"); + debugPrintf("Usage: changeStack <stack> [<card>]\n\n"); + debugPrintf("Stacks:\n=======\n"); for (byte i = 0; i < ARRAYSIZE(mystStackNames); i++) - DebugPrintf(" %s\n", mystStackNames[i]); + debugPrintf(" %s\n", mystStackNames[i]); - DebugPrintf("\n"); + debugPrintf("\n"); return true; } @@ -156,7 +156,7 @@ bool MystConsole::Cmd_ChangeStack(int argc, const char **argv) { } if (!stackNum) { - DebugPrintf("\'%s\' is not a stack name!\n", argv[1]); + debugPrintf("\'%s\' is not a stack name!\n", argv[1]); return true; } @@ -177,7 +177,7 @@ bool MystConsole::Cmd_ChangeStack(int argc, const char **argv) { bool MystConsole::Cmd_DrawImage(int argc, const char **argv) { if (argc != 2 && argc != 6) { - DebugPrintf("Usage: drawImage <image> [<left> <top> <right> <bottom>]\n"); + debugPrintf("Usage: drawImage <image> [<left> <top> <right> <bottom>]\n"); return true; } @@ -195,8 +195,8 @@ bool MystConsole::Cmd_DrawImage(int argc, const char **argv) { bool MystConsole::Cmd_DrawRect(int argc, const char **argv) { if (argc != 5 && argc != 2) { - DebugPrintf("Usage: drawRect <left> <top> <right> <bottom>\n"); - DebugPrintf("Usage: drawRect <resource id>\n"); + debugPrintf("Usage: drawRect <left> <top> <right> <bottom>\n"); + debugPrintf("Usage: drawRect <resource id>\n"); return true; } @@ -213,7 +213,7 @@ bool MystConsole::Cmd_DrawRect(int argc, const char **argv) { bool MystConsole::Cmd_SetResourceEnable(int argc, const char **argv) { if (argc < 3) { - DebugPrintf("Usage: setResourceEnable <resource id> <bool>\n"); + debugPrintf("Usage: setResourceEnable <resource id> <bool>\n"); return true; } @@ -223,7 +223,7 @@ bool MystConsole::Cmd_SetResourceEnable(int argc, const char **argv) { bool MystConsole::Cmd_PlaySound(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: playSound <value>\n"); + debugPrintf("Usage: playSound <value>\n"); return true; } @@ -234,7 +234,7 @@ bool MystConsole::Cmd_PlaySound(int argc, const char **argv) { } bool MystConsole::Cmd_StopSound(int argc, const char **argv) { - DebugPrintf("Stopping Sound\n"); + debugPrintf("Stopping Sound\n"); _vm->_sound->stopSound(); @@ -243,8 +243,8 @@ bool MystConsole::Cmd_StopSound(int argc, const char **argv) { bool MystConsole::Cmd_PlayMovie(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: playMovie <name> [<stack>] [<left> <top>]\n"); - DebugPrintf("NOTE: The movie will play *once* in the background.\n"); + debugPrintf("Usage: playMovie <name> [<stack>] [<left> <top>]\n"); + debugPrintf("NOTE: The movie will play *once* in the background.\n"); return true; } @@ -258,7 +258,7 @@ bool MystConsole::Cmd_PlayMovie(int argc, const char **argv) { } if (!stackNum) { - DebugPrintf("\'%s\' is not a stack name!\n", argv[2]); + debugPrintf("\'%s\' is not a stack name!\n", argv[2]); return true; } } @@ -277,7 +277,7 @@ bool MystConsole::Cmd_PlayMovie(int argc, const char **argv) { bool MystConsole::Cmd_DisableInitOpcodes(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: disableInitOpcodes\n"); + debugPrintf("Usage: disableInitOpcodes\n"); return true; } @@ -289,7 +289,7 @@ bool MystConsole::Cmd_DisableInitOpcodes(int argc, const char **argv) { bool MystConsole::Cmd_Cache(int argc, const char **argv) { if (argc > 2) { - DebugPrintf("Usage: cache on/off - Omit parameter to get current state\n"); + debugPrintf("Usage: cache on/off - Omit parameter to get current state\n"); return true; } @@ -304,15 +304,15 @@ bool MystConsole::Cmd_Cache(int argc, const char **argv) { _vm->setCacheState(state); } - DebugPrintf("Cache: %s\n", state ? "Enabled" : "Disabled"); + debugPrintf("Cache: %s\n", state ? "Enabled" : "Disabled"); return true; } bool MystConsole::Cmd_Resources(int argc, const char **argv) { - DebugPrintf("Resources in card %d:\n", _vm->getCurCard()); + debugPrintf("Resources in card %d:\n", _vm->getCurCard()); for (uint i = 0; i < _vm->_resources.size(); i++) { - DebugPrintf("#%2d %s\n", i, _vm->_resources[i]->describe().c_str()); + debugPrintf("#%2d %s\n", i, _vm->_resources[i]->describe().c_str()); } return true; @@ -323,21 +323,21 @@ bool MystConsole::Cmd_Resources(int argc, const char **argv) { #ifdef ENABLE_RIVEN RivenConsole::RivenConsole(MohawkEngine_Riven *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("changeCard", WRAP_METHOD(RivenConsole, Cmd_ChangeCard)); - DCmd_Register("curCard", WRAP_METHOD(RivenConsole, Cmd_CurCard)); - DCmd_Register("var", WRAP_METHOD(RivenConsole, Cmd_Var)); - DCmd_Register("playSound", WRAP_METHOD(RivenConsole, Cmd_PlaySound)); - DCmd_Register("playSLST", WRAP_METHOD(RivenConsole, Cmd_PlaySLST)); - DCmd_Register("stopSound", WRAP_METHOD(RivenConsole, Cmd_StopSound)); - DCmd_Register("curStack", WRAP_METHOD(RivenConsole, Cmd_CurStack)); - DCmd_Register("changeStack", WRAP_METHOD(RivenConsole, Cmd_ChangeStack)); - DCmd_Register("hotspots", WRAP_METHOD(RivenConsole, Cmd_Hotspots)); - DCmd_Register("zipMode", WRAP_METHOD(RivenConsole, Cmd_ZipMode)); - DCmd_Register("dumpScript", WRAP_METHOD(RivenConsole, Cmd_DumpScript)); - DCmd_Register("listZipCards", WRAP_METHOD(RivenConsole, Cmd_ListZipCards)); - DCmd_Register("getRMAP", WRAP_METHOD(RivenConsole, Cmd_GetRMAP)); - DCmd_Register("combos", WRAP_METHOD(RivenConsole, Cmd_Combos)); - DCmd_Register("sliderState", WRAP_METHOD(RivenConsole, Cmd_SliderState)); + registerCmd("changeCard", WRAP_METHOD(RivenConsole, Cmd_ChangeCard)); + registerCmd("curCard", WRAP_METHOD(RivenConsole, Cmd_CurCard)); + registerCmd("var", WRAP_METHOD(RivenConsole, Cmd_Var)); + registerCmd("playSound", WRAP_METHOD(RivenConsole, Cmd_PlaySound)); + registerCmd("playSLST", WRAP_METHOD(RivenConsole, Cmd_PlaySLST)); + registerCmd("stopSound", WRAP_METHOD(RivenConsole, Cmd_StopSound)); + registerCmd("curStack", WRAP_METHOD(RivenConsole, Cmd_CurStack)); + registerCmd("changeStack", WRAP_METHOD(RivenConsole, Cmd_ChangeStack)); + registerCmd("hotspots", WRAP_METHOD(RivenConsole, Cmd_Hotspots)); + registerCmd("zipMode", WRAP_METHOD(RivenConsole, Cmd_ZipMode)); + registerCmd("dumpScript", WRAP_METHOD(RivenConsole, Cmd_DumpScript)); + registerCmd("listZipCards", WRAP_METHOD(RivenConsole, Cmd_ListZipCards)); + registerCmd("getRMAP", WRAP_METHOD(RivenConsole, Cmd_GetRMAP)); + registerCmd("combos", WRAP_METHOD(RivenConsole, Cmd_Combos)); + registerCmd("sliderState", WRAP_METHOD(RivenConsole, Cmd_SliderState)); } RivenConsole::~RivenConsole() { @@ -346,7 +346,7 @@ RivenConsole::~RivenConsole() { bool RivenConsole::Cmd_ChangeCard(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: changeCard <card>\n"); + debugPrintf("Usage: changeCard <card>\n"); return true; } @@ -358,19 +358,19 @@ bool RivenConsole::Cmd_ChangeCard(int argc, const char **argv) { } bool RivenConsole::Cmd_CurCard(int argc, const char **argv) { - DebugPrintf("Current Card: %d\n", _vm->getCurCard()); + debugPrintf("Current Card: %d\n", _vm->getCurCard()); return true; } bool RivenConsole::Cmd_Var(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: var <var name> (<value>)\n"); + debugPrintf("Usage: var <var name> (<value>)\n"); return true; } if (!_vm->_vars.contains(argv[1])) { - DebugPrintf("Unknown variable '%s'\n", argv[1]); + debugPrintf("Unknown variable '%s'\n", argv[1]); return true; } @@ -379,13 +379,13 @@ bool RivenConsole::Cmd_Var(int argc, const char **argv) { if (argc > 2) var = (uint32)atoi(argv[2]); - DebugPrintf("%s = %d\n", argv[1], var); + debugPrintf("%s = %d\n", argv[1], var); return true; } bool RivenConsole::Cmd_PlaySound(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: playSound <value>\n"); + debugPrintf("Usage: playSound <value>\n"); return true; } @@ -397,7 +397,7 @@ bool RivenConsole::Cmd_PlaySound(int argc, const char **argv) { bool RivenConsole::Cmd_PlaySLST(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: playSLST <slst index> <card, default = current>\n"); + debugPrintf("Usage: playSLST <slst index> <card, default = current>\n"); return true; } @@ -412,7 +412,7 @@ bool RivenConsole::Cmd_PlaySLST(int argc, const char **argv) { } bool RivenConsole::Cmd_StopSound(int argc, const char **argv) { - DebugPrintf("Stopping Sound\n"); + debugPrintf("Stopping Sound\n"); _vm->_sound->stopSound(); _vm->_sound->stopAllSLST(); @@ -420,58 +420,57 @@ bool RivenConsole::Cmd_StopSound(int argc, const char **argv) { } bool RivenConsole::Cmd_CurStack(int argc, const char **argv) { - DebugPrintf("Current Stack: %s\n", _vm->getStackName(_vm->getCurStack()).c_str()); + debugPrintf("Current Stack: %s\n", _vm->getStackName(_vm->getCurStack()).c_str()); return true; } bool RivenConsole::Cmd_ChangeStack(int argc, const char **argv) { - byte i; - if (argc < 3) { - DebugPrintf("Usage: changeStack <stack> <card>\n\n"); - DebugPrintf("Stacks:\n=======\n"); + debugPrintf("Usage: changeStack <stack> <card>\n\n"); + debugPrintf("Stacks:\n=======\n"); - for (i = 0; i <= tspit; i++) - DebugPrintf(" %s\n", _vm->getStackName(i).c_str()); + for (uint i = kStackFirst; i <= kStackLast; i++) + debugPrintf(" %s\n", _vm->getStackName(i).c_str()); - DebugPrintf("\n"); + debugPrintf("\n"); return true; } - byte stackNum = 0; + uint stack = kStackUnknown; - for (i = 1; i <= tspit + 1; i++) - if (!scumm_stricmp(argv[1], _vm->getStackName(i - 1).c_str())) { - stackNum = i; + for (uint i = kStackFirst; i <= kStackLast; i++) { + if (!scumm_stricmp(argv[1], _vm->getStackName(i).c_str())) { + stack = i; break; } + } - if (!stackNum) { - DebugPrintf("\'%s\' is not a stack name!\n", argv[1]); + if (stack == kStackUnknown) { + debugPrintf("\'%s\' is not a stack name!\n", argv[1]); return true; } - _vm->changeToStack(stackNum - 1); + _vm->changeToStack(stack); _vm->changeToCard((uint16)atoi(argv[2])); return false; } bool RivenConsole::Cmd_Hotspots(int argc, const char **argv) { - DebugPrintf("Current card (%d) has %d hotspots:\n", _vm->getCurCard(), _vm->getHotspotCount()); + debugPrintf("Current card (%d) has %d hotspots:\n", _vm->getCurCard(), _vm->getHotspotCount()); for (uint16 i = 0; i < _vm->getHotspotCount(); i++) { - DebugPrintf("Hotspot %d, index %d, BLST ID %d (", i, _vm->_hotspots[i].index, _vm->_hotspots[i].blstID); + debugPrintf("Hotspot %d, index %d, BLST ID %d (", i, _vm->_hotspots[i].index, _vm->_hotspots[i].blstID); if (_vm->_hotspots[i].enabled) - DebugPrintf("enabled"); + debugPrintf("enabled"); else - DebugPrintf("disabled"); + debugPrintf("disabled"); - DebugPrintf(") - (%d, %d, %d, %d)\n", _vm->_hotspots[i].rect.left, _vm->_hotspots[i].rect.top, _vm->_hotspots[i].rect.right, _vm->_hotspots[i].rect.bottom); - DebugPrintf(" Name = %s\n", _vm->getHotspotName(i).c_str()); + debugPrintf(") - (%d, %d, %d, %d)\n", _vm->_hotspots[i].rect.left, _vm->_hotspots[i].rect.top, _vm->_hotspots[i].rect.right, _vm->_hotspots[i].rect.bottom); + debugPrintf(" Name = %s\n", _vm->getHotspotName(i).c_str()); } return true; @@ -481,34 +480,33 @@ bool RivenConsole::Cmd_ZipMode(int argc, const char **argv) { uint32 &zipModeActive = _vm->_vars["azip"]; zipModeActive = !zipModeActive; - DebugPrintf("Zip Mode is "); - DebugPrintf(zipModeActive ? "Enabled" : "Disabled"); - DebugPrintf("\n"); + debugPrintf("Zip Mode is "); + debugPrintf(zipModeActive ? "Enabled" : "Disabled"); + debugPrintf("\n"); return true; } bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) { if (argc < 4) { - DebugPrintf("Usage: dumpScript <stack> <CARD or HSPT> <card>\n"); + debugPrintf("Usage: dumpScript <stack> <CARD or HSPT> <card>\n"); return true; } uint16 oldStack = _vm->getCurStack(); + uint newStack = kStackUnknown; - byte newStack = 0; - - for (byte i = 1; i <= tspit + 1; i++) - if (!scumm_stricmp(argv[1], _vm->getStackName(i - 1).c_str())) { + for (uint i = kStackFirst; i <= kStackLast; i++) { + if (!scumm_stricmp(argv[1], _vm->getStackName(i).c_str())) { newStack = i; break; } + } - if (!newStack) { - DebugPrintf("\'%s\' is not a stack name!\n", argv[1]); + if (newStack == kStackUnknown) { + debugPrintf("\'%s\' is not a stack name!\n", argv[1]); return true; } - newStack--; _vm->changeToStack(newStack); // Load in Variable Names @@ -594,7 +592,7 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) { delete hsptStream; } else { - DebugPrintf("%s doesn't have any scripts!\n", argv[2]); + debugPrintf("%s doesn't have any scripts!\n", argv[2]); } // See above for why this is printed via debugN @@ -602,18 +600,18 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) { _vm->changeToStack(oldStack); - DebugPrintf("Script dump complete.\n"); + debugPrintf("Script dump complete.\n"); return true; } bool RivenConsole::Cmd_ListZipCards(int argc, const char **argv) { if (_vm->_zipModeData.size() == 0) { - DebugPrintf("No zip card data.\n"); + debugPrintf("No zip card data.\n"); } else { - DebugPrintf("Listing zip cards:\n"); + debugPrintf("Listing zip cards:\n"); for (uint32 i = 0; i < _vm->_zipModeData.size(); i++) - DebugPrintf("ID = %d, Name = %s\n", _vm->_zipModeData[i].id, _vm->_zipModeData[i].name.c_str()); + debugPrintf("ID = %d, Name = %s\n", _vm->_zipModeData[i].id, _vm->_zipModeData[i].name.c_str()); } return true; @@ -621,7 +619,7 @@ bool RivenConsole::Cmd_ListZipCards(int argc, const char **argv) { bool RivenConsole::Cmd_GetRMAP(int argc, const char **argv) { uint32 rmapCode = _vm->getCurCardRMAP(); - DebugPrintf("RMAP for %s %d = %08x\n", _vm->getStackName(_vm->getCurStack()).c_str(), _vm->getCurCard(), rmapCode); + debugPrintf("RMAP for %s %d = %08x\n", _vm->getStackName(_vm->getCurStack()).c_str(), _vm->getCurCard(), rmapCode); return true; } @@ -635,20 +633,20 @@ bool RivenConsole::Cmd_Combos(int argc, const char **argv) { uint32 prisonCombo = _vm->_vars["pcorrectorder"]; uint32 domeCombo = _vm->_vars["adomecombo"]; - DebugPrintf("Telescope Combo:\n "); + debugPrintf("Telescope Combo:\n "); for (int i = 0; i < 5; i++) - DebugPrintf("%d ", _vm->_externalScriptHandler->getComboDigit(teleCombo, i)); + debugPrintf("%d ", _vm->_externalScriptHandler->getComboDigit(teleCombo, i)); - DebugPrintf("\nPrison Combo:\n "); + debugPrintf("\nPrison Combo:\n "); for (int i = 0; i < 5; i++) - DebugPrintf("%d ", _vm->_externalScriptHandler->getComboDigit(prisonCombo, i)); + debugPrintf("%d ", _vm->_externalScriptHandler->getComboDigit(prisonCombo, i)); - DebugPrintf("\nDome Combo:\n "); + debugPrintf("\nDome Combo:\n "); for (int i = 1; i <= 25; i++) if (domeCombo & (1 << (25 - i))) - DebugPrintf("%d ", i); + debugPrintf("%d ", i); - DebugPrintf("\n"); + debugPrintf("\n"); return true; } @@ -656,17 +654,17 @@ bool RivenConsole::Cmd_SliderState(int argc, const char **argv) { if (argc > 1) _vm->_externalScriptHandler->setDomeSliderState((uint32)atoi(argv[1])); - DebugPrintf("Dome Slider State = %08x\n", _vm->_externalScriptHandler->getDomeSliderState()); + debugPrintf("Dome Slider State = %08x\n", _vm->_externalScriptHandler->getDomeSliderState()); return true; } #endif // ENABLE_RIVEN LivingBooksConsole::LivingBooksConsole(MohawkEngine_LivingBooks *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("playSound", WRAP_METHOD(LivingBooksConsole, Cmd_PlaySound)); - DCmd_Register("stopSound", WRAP_METHOD(LivingBooksConsole, Cmd_StopSound)); - DCmd_Register("drawImage", WRAP_METHOD(LivingBooksConsole, Cmd_DrawImage)); - DCmd_Register("changePage", WRAP_METHOD(LivingBooksConsole, Cmd_ChangePage)); + registerCmd("playSound", WRAP_METHOD(LivingBooksConsole, Cmd_PlaySound)); + registerCmd("stopSound", WRAP_METHOD(LivingBooksConsole, Cmd_StopSound)); + registerCmd("drawImage", WRAP_METHOD(LivingBooksConsole, Cmd_DrawImage)); + registerCmd("changePage", WRAP_METHOD(LivingBooksConsole, Cmd_ChangePage)); } LivingBooksConsole::~LivingBooksConsole() { @@ -674,7 +672,7 @@ LivingBooksConsole::~LivingBooksConsole() { bool LivingBooksConsole::Cmd_PlaySound(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: playSound <value>\n"); + debugPrintf("Usage: playSound <value>\n"); return true; } @@ -684,7 +682,7 @@ bool LivingBooksConsole::Cmd_PlaySound(int argc, const char **argv) { } bool LivingBooksConsole::Cmd_StopSound(int argc, const char **argv) { - DebugPrintf("Stopping Sound\n"); + debugPrintf("Stopping Sound\n"); _vm->_sound->stopSound(); return true; @@ -692,7 +690,7 @@ bool LivingBooksConsole::Cmd_StopSound(int argc, const char **argv) { bool LivingBooksConsole::Cmd_DrawImage(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: drawImage <value>\n"); + debugPrintf("Usage: drawImage <value>\n"); return true; } @@ -703,13 +701,13 @@ bool LivingBooksConsole::Cmd_DrawImage(int argc, const char **argv) { bool LivingBooksConsole::Cmd_ChangePage(int argc, const char **argv) { if (argc < 2 || argc > 3) { - DebugPrintf("Usage: changePage <page>[.<subpage>] [<mode>]\n"); + debugPrintf("Usage: changePage <page>[.<subpage>] [<mode>]\n"); return true; } int page, subpage = 0; if (sscanf(argv[1], "%d.%d", &page, &subpage) == 0) { - DebugPrintf("Usage: changePage <page>[.<subpage>] [<mode>]\n"); + debugPrintf("Usage: changePage <page>[.<subpage>] [<mode>]\n"); return true; } LBMode mode = argc == 2 ? _vm->getCurMode() : (LBMode)atoi(argv[2]); @@ -720,21 +718,21 @@ bool LivingBooksConsole::Cmd_ChangePage(int argc, const char **argv) { if (_vm->loadPage(mode, page, subpage)) return false; } - DebugPrintf("no such page %d.%d\n", page, subpage); + debugPrintf("no such page %d.%d\n", page, subpage); return true; } #ifdef ENABLE_CSTIME CSTimeConsole::CSTimeConsole(MohawkEngine_CSTime *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("playSound", WRAP_METHOD(CSTimeConsole, Cmd_PlaySound)); - DCmd_Register("stopSound", WRAP_METHOD(CSTimeConsole, Cmd_StopSound)); - DCmd_Register("drawImage", WRAP_METHOD(CSTimeConsole, Cmd_DrawImage)); - DCmd_Register("drawSubimage", WRAP_METHOD(CSTimeConsole, Cmd_DrawSubimage)); - DCmd_Register("changeCase", WRAP_METHOD(CSTimeConsole, Cmd_ChangeCase)); - DCmd_Register("changeScene", WRAP_METHOD(CSTimeConsole, Cmd_ChangeScene)); - DCmd_Register("caseVariable", WRAP_METHOD(CSTimeConsole, Cmd_CaseVariable)); - DCmd_Register("invItem", WRAP_METHOD(CSTimeConsole, Cmd_InvItem)); + registerCmd("playSound", WRAP_METHOD(CSTimeConsole, Cmd_PlaySound)); + registerCmd("stopSound", WRAP_METHOD(CSTimeConsole, Cmd_StopSound)); + registerCmd("drawImage", WRAP_METHOD(CSTimeConsole, Cmd_DrawImage)); + registerCmd("drawSubimage", WRAP_METHOD(CSTimeConsole, Cmd_DrawSubimage)); + registerCmd("changeCase", WRAP_METHOD(CSTimeConsole, Cmd_ChangeCase)); + registerCmd("changeScene", WRAP_METHOD(CSTimeConsole, Cmd_ChangeScene)); + registerCmd("caseVariable", WRAP_METHOD(CSTimeConsole, Cmd_CaseVariable)); + registerCmd("invItem", WRAP_METHOD(CSTimeConsole, Cmd_InvItem)); } CSTimeConsole::~CSTimeConsole() { @@ -742,7 +740,7 @@ CSTimeConsole::~CSTimeConsole() { bool CSTimeConsole::Cmd_PlaySound(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: playSound <value>\n"); + debugPrintf("Usage: playSound <value>\n"); return true; } @@ -752,7 +750,7 @@ bool CSTimeConsole::Cmd_PlaySound(int argc, const char **argv) { } bool CSTimeConsole::Cmd_StopSound(int argc, const char **argv) { - DebugPrintf("Stopping Sound\n"); + debugPrintf("Stopping Sound\n"); _vm->_sound->stopSound(); return true; @@ -760,7 +758,7 @@ bool CSTimeConsole::Cmd_StopSound(int argc, const char **argv) { bool CSTimeConsole::Cmd_DrawImage(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: drawImage <value>\n"); + debugPrintf("Usage: drawImage <value>\n"); return true; } @@ -771,7 +769,7 @@ bool CSTimeConsole::Cmd_DrawImage(int argc, const char **argv) { bool CSTimeConsole::Cmd_DrawSubimage(int argc, const char **argv) { if (argc < 3) { - DebugPrintf("Usage: drawSubimage <value> <subimage>\n"); + debugPrintf("Usage: drawSubimage <value> <subimage>\n"); return true; } @@ -782,7 +780,7 @@ bool CSTimeConsole::Cmd_DrawSubimage(int argc, const char **argv) { bool CSTimeConsole::Cmd_ChangeCase(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: changeCase <value>\n"); + debugPrintf("Usage: changeCase <value>\n"); return true; } @@ -792,7 +790,7 @@ bool CSTimeConsole::Cmd_ChangeCase(int argc, const char **argv) { bool CSTimeConsole::Cmd_ChangeScene(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: changeScene <value>\n"); + debugPrintf("Usage: changeScene <value>\n"); return true; } @@ -802,12 +800,12 @@ bool CSTimeConsole::Cmd_ChangeScene(int argc, const char **argv) { bool CSTimeConsole::Cmd_CaseVariable(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: caseVariable <id> [<value>]\n"); + debugPrintf("Usage: caseVariable <id> [<value>]\n"); return true; } if (argc == 2) { - DebugPrintf("case variable %d has value %d\n", atoi(argv[1]), _vm->_caseVariable[atoi(argv[1])]); + debugPrintf("case variable %d has value %d\n", atoi(argv[1]), _vm->_caseVariable[atoi(argv[1])]); } else { _vm->_caseVariable[atoi(argv[1])] = atoi(argv[2]); } @@ -816,7 +814,7 @@ bool CSTimeConsole::Cmd_CaseVariable(int argc, const char **argv) { bool CSTimeConsole::Cmd_InvItem(int argc, const char **argv) { if (argc < 3) { - DebugPrintf("Usage: invItem <id> <0 or 1>\n"); + debugPrintf("Usage: invItem <id> <0 or 1>\n"); return true; } diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp index e1059bebaa..a7fe12b9e1 100644 --- a/engines/mohawk/riven.cpp +++ b/engines/mohawk/riven.cpp @@ -55,7 +55,7 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio _activatedSLST = false; _ignoreNextMouseUp = false; _extrasFile = 0; - _curStack = aspit; + _curStack = kStackUnknown; _hotspots = 0; removeTimer(); @@ -161,7 +161,7 @@ Common::Error MohawkEngine_Riven::run() { // Let's begin, shall we? if (getFeatures() & GF_DEMO) { // Start the demo off with the videos - changeToStack(aspit); + changeToStack(kStackAspit); changeToCard(6); } else if (ConfMan.hasKey("save_slot")) { // Load game from launcher/command line if requested @@ -172,12 +172,12 @@ Common::Error MohawkEngine_Riven::run() { // Attempt to load the game. On failure, just send us to the main menu. if (_saveLoad->loadGame(savedGamesList[gameToLoad]).getCode() != Common::kNoError) { - changeToStack(aspit); + changeToStack(kStackAspit); changeToCard(1); } } else { // Otherwise, start us off at aspit's card 1 (the main menu) - changeToStack(aspit); + changeToStack(kStackAspit); changeToCard(1); } @@ -255,16 +255,16 @@ void MohawkEngine_Riven::handleEvents() { case Common::KEYCODE_r: // Return to the main menu in the demo on ctrl+r if (event.kbd.flags & Common::KBD_CTRL && getFeatures() & GF_DEMO) { - if (_curStack != aspit) - changeToStack(aspit); + if (_curStack != kStackAspit) + changeToStack(kStackAspit); changeToCard(1); } break; case Common::KEYCODE_p: // Play the intro videos in the demo on ctrl+p if (event.kbd.flags & Common::KBD_CTRL && getFeatures() & GF_DEMO) { - if (_curStack != aspit) - changeToStack(aspit); + if (_curStack != kStackAspit) + changeToStack(kStackAspit); changeToCard(6); } break; @@ -343,20 +343,22 @@ struct RivenSpecialChange { uint32 startCardRMAP; byte targetStack; uint32 targetCardRMAP; -} rivenSpecialChange[] = { - { aspit, 0x1f04, ospit, 0x44ad }, // Trap Book - { bspit, 0x1c0e7, ospit, 0x2e76 }, // Dome Linking Book - { gspit, 0x111b1, ospit, 0x2e76 }, // Dome Linking Book - { jspit, 0x28a18, rspit, 0xf94 }, // Tay Linking Book - { jspit, 0x26228, ospit, 0x2e76 }, // Dome Linking Book - { ospit, 0x5f0d, pspit, 0x3bf0 }, // Return from 233rd Age - { ospit, 0x470a, jspit, 0x1508e }, // Return from 233rd Age - { ospit, 0x5c52, gspit, 0x10bea }, // Return from 233rd Age - { ospit, 0x5d68, bspit, 0x1adfd }, // Return from 233rd Age - { ospit, 0x5e49, tspit, 0xe87 }, // Return from 233rd Age - { pspit, 0x4108, ospit, 0x2e76 }, // Dome Linking Book - { rspit, 0x32d8, jspit, 0x1c474 }, // Return from Tay - { tspit, 0x21b69, ospit, 0x2e76 } // Dome Linking Book +}; + +static const RivenSpecialChange rivenSpecialChange[] = { + { kStackAspit, 0x1f04, kStackOspit, 0x44ad }, // Trap Book + { kStackBspit, 0x1c0e7, kStackOspit, 0x2e76 }, // Dome Linking Book + { kStackGspit, 0x111b1, kStackOspit, 0x2e76 }, // Dome Linking Book + { kStackJspit, 0x28a18, kStackRspit, 0xf94 }, // Tay Linking Book + { kStackJspit, 0x26228, kStackOspit, 0x2e76 }, // Dome Linking Book + { kStackOspit, 0x5f0d, kStackPspit, 0x3bf0 }, // Return from 233rd Age + { kStackOspit, 0x470a, kStackJspit, 0x1508e }, // Return from 233rd Age + { kStackOspit, 0x5c52, kStackGspit, 0x10bea }, // Return from 233rd Age + { kStackOspit, 0x5d68, kStackBspit, 0x1adfd }, // Return from 233rd Age + { kStackOspit, 0x5e49, kStackTspit, 0xe87 }, // Return from 233rd Age + { kStackPspit, 0x4108, kStackOspit, 0x2e76 }, // Dome Linking Book + { kStackRspit, 0x32d8, kStackJspit, 0x1c474 }, // Return from Tay + { kStackTspit, 0x21b69, kStackOspit, 0x2e76 } // Dome Linking Book }; void MohawkEngine_Riven::changeToCard(uint16 dest) { @@ -556,16 +558,16 @@ void MohawkEngine_Riven::checkInventoryClick() { // In the demo, check if we've clicked the exit button if (getFeatures() & GF_DEMO) { if (g_demoExitRect->contains(mousePos)) { - if (_curStack == aspit && _curCard == 1) { + if (_curStack == kStackAspit && _curCard == 1) { // From the main menu, go to the "quit" screen changeToCard(12); - } else if (_curStack == aspit && _curCard == 12) { + } else if (_curStack == kStackAspit && _curCard == 12) { // From the "quit" screen, just quit _gameOver = true; } else { // Otherwise, return to the main menu - if (_curStack != aspit) - changeToStack(aspit); + if (_curStack != kStackAspit) + changeToStack(kStackAspit); changeToCard(1); } } @@ -573,7 +575,7 @@ void MohawkEngine_Riven::checkInventoryClick() { } // No inventory shown on aspit - if (_curStack == aspit) + if (_curStack == kStackAspit) return; // Set the return stack/card id's. @@ -589,31 +591,31 @@ void MohawkEngine_Riven::checkInventoryClick() { if (!hasCathBook) { if (g_atrusJournalRect1->contains(mousePos)) { _gfx->hideInventory(); - changeToStack(aspit); + changeToStack(kStackAspit); changeToCard(5); } } else if (!hasTrapBook) { if (g_atrusJournalRect2->contains(mousePos)) { _gfx->hideInventory(); - changeToStack(aspit); + changeToStack(kStackAspit); changeToCard(5); } else if (g_cathJournalRect2->contains(mousePos)) { _gfx->hideInventory(); - changeToStack(aspit); + changeToStack(kStackAspit); changeToCard(6); } } else { if (g_atrusJournalRect3->contains(mousePos)) { _gfx->hideInventory(); - changeToStack(aspit); + changeToStack(kStackAspit); changeToCard(5); } else if (g_cathJournalRect3->contains(mousePos)) { _gfx->hideInventory(); - changeToStack(aspit); + changeToStack(kStackAspit); changeToCard(6); } else if (g_trapBookRect3->contains(mousePos)) { _gfx->hideInventory(); - changeToStack(aspit); + changeToStack(kStackAspit); changeToCard(7); } } @@ -735,16 +737,20 @@ Common::Error MohawkEngine_Riven::saveGameState(int slot, const Common::String & Common::String MohawkEngine_Riven::getStackName(uint16 stack) const { static const char *rivenStackNames[] = { - "aspit", - "bspit", - "gspit", - "jspit", + "<unknown>", "ospit", "pspit", "rspit", - "tspit" + "tspit", + "bspit", + "gspit", + "jspit", + "aspit" }; + // Sanity check. + assert(stack < ARRAYSIZE(rivenStackNames)); + return rivenStackNames[stack]; } diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h index c22b9f7f87..9c23d07c52 100644 --- a/engines/mohawk/riven.h +++ b/engines/mohawk/riven.h @@ -44,18 +44,20 @@ class RivenConsole; class RivenSaveLoad; class RivenOptionsDialog; -#define RIVEN_STACKS 8 - // Riven Stack Types enum { - aspit = 0, // Main Menu, Books, Setup - bspit = 1, // Book-Making Island - gspit = 2, // Garden Island - jspit = 3, // Jungle Island - ospit = 4, // 233rd Age (Gehn's Office) - pspit = 5, // Prison Island - rspit = 6, // Rebel Age (Tay) - tspit = 7 // Temple Island + kStackUnknown = 0, // Default value for ReturnStackID + kStackOspit = 1, // 233rd Age (Gehn's Office) + kStackPspit = 2, // Prison Island + kStackRspit = 3, // Temple Island + kStackTspit = 4, // Rebel Age (Tay) + kStackBspit = 5, // Book-Making Island + kStackGspit = 6, // Garden Island + kStackJspit = 7, // Jungle Island + kStackAspit = 8, // Main Menu, Books, Setup + + kStackFirst = kStackOspit, + kStackLast = kStackAspit }; // NAME Resource ID's diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp index 10dcfd9fa7..3d0bccc47f 100644 --- a/engines/mohawk/riven_external.cpp +++ b/engines/mohawk/riven_external.cpp @@ -405,7 +405,7 @@ void RivenExternal::drawDomeSliders(uint16 startHotspot) { // On pspit, the rect is different by two pixels // (alternatively, we could just use hotspot 3 here, but only on pspit is there a hotspot for this) - if (_vm->getCurStack() == pspit) + if (_vm->getCurStack() == kStackPspit) dstAreaRect.translate(-2, 0); // Find out bitmap id @@ -2016,8 +2016,8 @@ void RivenExternal::xorollcredittime(uint16 argc, uint16 *argv) { // WORKAROUND: The special change stuff only handles one destination and it would // be messy to modify the way that currently works. If we use the trap book on Tay, // we should be using the Tay end game sequences. - if (_vm->_vars["returnstackid"] == rspit) { - _vm->changeToStack(rspit); + if (_vm->_vars["returnstackid"] == kStackRspit) { + _vm->changeToStack(kStackRspit); _vm->changeToCard(2); return; } diff --git a/engines/mohawk/riven_graphics.cpp b/engines/mohawk/riven_graphics.cpp index 615b2fdadb..b44fbb828e 100644 --- a/engines/mohawk/riven_graphics.cpp +++ b/engines/mohawk/riven_graphics.cpp @@ -289,7 +289,7 @@ void RivenGraphics::showInventory() { drawInventoryImage(101, g_demoExitRect); } else { // We don't want to show the inventory on setup screens or in other journals. - if (_vm->getCurStack() == aspit) + if (_vm->getCurStack() == kStackAspit) return; // There are three books and three vars. We have three different diff --git a/engines/mohawk/riven_saveload.cpp b/engines/mohawk/riven_saveload.cpp index d97d0e174b..6af66f7a2d 100644 --- a/engines/mohawk/riven_saveload.cpp +++ b/engines/mohawk/riven_saveload.cpp @@ -38,56 +38,6 @@ Common::StringArray RivenSaveLoad::generateSaveGameList() { return _saveFileMan->listSavefiles("*.rvn"); } -// Note: The stack numbers we use do not match up to what the original executable, -// so, match them ;) -static uint16 mapOldStackIDToNew(uint16 oldID) { - switch (oldID) { - case 1: - return ospit; - case 2: - return pspit; - case 3: - return rspit; - case 4: - return tspit; - case 5: - return bspit; - case 6: - return gspit; - case 7: - return jspit; - case 8: - return aspit; - } - - error("Unknown old stack ID %d", oldID); - return 0; -} - -static uint16 mapNewStackIDToOld(uint16 newID) { - switch (newID) { - case aspit: - return 8; - case bspit: - return 5; - case gspit: - return 6; - case jspit: - return 7; - case ospit: - return 1; - case pspit: - return 2; - case rspit: - return 3; - case tspit: - return 4; - } - - error("Unknown new stack ID %d", newID); - return 0; -} - Common::Error RivenSaveLoad::loadGame(Common::String filename) { if (_vm->getFeatures() & GF_DEMO) // Don't load games in the demo return Common::kNoError; @@ -141,9 +91,6 @@ Common::Error RivenSaveLoad::loadGame(Common::String filename) { names->readUint16BE(); // Skip unknown values uint32 curNamesPos = names->pos(); - uint16 stackID = 0; - uint16 cardID = 0; - for (uint32 i = 0; i < namesCount && !names->eos(); i++) { names->seek(curNamesPos); names->seek(stringOffsets[i], SEEK_CUR); @@ -165,25 +112,18 @@ Common::Error RivenSaveLoad::loadGame(Common::String filename) { uint32 &var = _vm->_vars[name]; name.toLowercase(); - // Handle any special variables here // WORKAROUND: time variables are reset here for one main reason: // The save does not store any start point for the time, so we don't know the real time. // Because of this, in many cases, the original would just give a 'free' Ytram upon saving // since the time would be used in a new (improper) time frame. - if (name.equalsIgnoreCase("CurrentStackID")) // Remap to our definitions, store for later - stackID = mapOldStackIDToNew(rawVariables[i]); - else if (name.equalsIgnoreCase("CurrentCardID")) // Store for later - cardID = rawVariables[i]; - else if (name.equalsIgnoreCase("ReturnStackID") && var != 0) // if 0, the game did not use the variable yet - var = mapOldStackIDToNew(rawVariables[i]); - else if (name.contains("time")) // WORKAROUND: See above + if (name.contains("time")) var = 0; - else // Otherwise, just store it + else var = rawVariables[i]; } - _vm->changeToStack(stackID); - _vm->changeToCard(cardID); + _vm->changeToStack(_vm->_vars["CurrentStackID"]); + _vm->changeToCard(_vm->_vars["CurrentCardID"]); delete names; delete[] stringOffsets; @@ -224,14 +164,7 @@ Common::MemoryWriteStreamDynamic *RivenSaveLoad::genVARSSection() { for (RivenVariableMap::const_iterator it = _vm->_vars.begin(); it != _vm->_vars.end(); it++) { stream->writeUint32BE(0); // Unknown stream->writeUint32BE(0); // Unknown - - // Remap returnstackid here because we don't actually want to change - // our internal returnstackid. - uint32 variable = it->_value; - if (it->_key == "returnstackid") - variable = mapNewStackIDToOld(variable); - - stream->writeUint32BE(variable); + stream->writeUint32BE(it->_value); } return stream; @@ -290,7 +223,7 @@ Common::Error RivenSaveLoad::saveGame(Common::String filename) { filename += ".rvn"; // Convert class variables to variable numbers - _vm->_vars["currentstackid"] = mapNewStackIDToOld(_vm->getCurStack()); + _vm->_vars["currentstackid"] = _vm->getCurStack(); _vm->_vars["currentcardid"] = _vm->getCurCard(); Common::OutSaveFile *saveFile = _saveFileMan->openForSaving(filename); diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp index 06b6afdf30..29ee5cd50b 100644 --- a/engines/mohawk/riven_scripts.cpp +++ b/engines/mohawk/riven_scripts.cpp @@ -403,7 +403,7 @@ void RivenScript::stopSound(uint16 op, uint16 argc, uint16 *argv) { // would cause all ambient sounds not to play. An alternative // fix would be to stop all scripts on a stack change, but this // does fine for now. - if (_vm->getCurStack() == tspit && (_vm->getCurCardRMAP() == 0x6e9a || _vm->getCurCardRMAP() == 0xfeeb)) + if (_vm->getCurStack() == kStackTspit && (_vm->getCurCardRMAP() == 0x6e9a || _vm->getCurCardRMAP() == 0xfeeb)) return; // The argument is a bitflag for the setting. @@ -586,7 +586,7 @@ void RivenScript::activatePLST(uint16 op, uint16 argc, uint16 *argv) { void RivenScript::activateSLST(uint16 op, uint16 argc, uint16 *argv) { // WORKAROUND: Disable the SLST that is played during Riven's intro. // Riven X does this too (spoke this over with Jeff) - if (_vm->getCurStack() == tspit && _vm->getCurCardRMAP() == 0x6e9a && argv[0] == 2) + if (_vm->getCurStack() == kStackTspit && _vm->getCurCardRMAP() == 0x6e9a && argv[0] == 2) return; _vm->_sound->playSLST(argv[0], _vm->getCurCard()); diff --git a/engines/mohawk/riven_vars.cpp b/engines/mohawk/riven_vars.cpp index 1cd748d8d6..f09aba7f90 100644 --- a/engines/mohawk/riven_vars.cpp +++ b/engines/mohawk/riven_vars.cpp @@ -31,240 +31,240 @@ namespace Mohawk { static const char *variableNames[] = { // aspit - "aatrusbook", - "aatruspage", - "acathbook", - "acathpage", - "acathstate", - "adoit", - "adomecombo", - "agehn", - "ainventory", - "aova", - "apower", - "araw", - "atemp", - "atrap", - "atrapbook", - "auservolume", - "azip", + "aAtrusBook", + "aAtrusPage", + "aCathBook", + "aCathPage", + "aCathState", + "aDoIt", + "aDomeCombo", + "aGehn", + "aInventory", + "aOva", + "aPower", + "aRaw", + "aTemp", + "aTrap", + "aTrapBook", + "aUserVolume", + "aZip", // bspit - "bbacklock", - "bbait", - "bbigbridge", - "bbirds", - "bblrarm", - "bblrdoor", - "bblrgrt", - "bblrsw", - "bblrvalve", - "bblrwtr", - "bbook", - "bbrlever", - "bcavedoor", + "bBackLock", + "bBait", + "bBigBridge", + "bBirds", + "bBlrArm", + "bBlrDoor", + "bBlrGrt", + "bBlrSw", + "bBlrValve", + "bBlrWtr", + "bBook", + "bBrLever", + "bCaveDoor", "bcombo", - "bcpipegr", - "bcratergg", - "bdome", - "bdrwr", - "bfans", - "bfmdoor", - "bidvlv", - "blab", - "blabbackdr", - "blabbook", - "blabeye", - "blabfrontdr", - "blabpage", - "blever", - "bfrontlock", - "bheat", - "bmagcar", - "bpipdr", - "bprs", - "bstove", - "btrap", - "bvalve", - "bvise", - "bytram", - "bytramtime", - "bytrap", - "bytrapped", + "bCPipeGr", + "bCraterGg", + "bDome", + "bDrwr", + "bFans", + "bFMDoor", + "bIdVlv", + "bLab", + "bLabBackDr", + "bLabBook", + "bLabEye", + "bLabFrontDr", + "bLabPage", + "bLever", + "bFrontLock", + "bHeat", + "bMagCar", + "bPipDr", + "bPrs", + "bStove", + "bTrap", + "bValve", + "bVise", + "bYtram", + "bYtramTime", + "bYtrap", + "bYtrapped", // gspit - "gbook", - "gcathtime", - "gcathstate", - "gcombo", - "gdome", - "gemagcar", - "gimagecurr", + "gBook", + "gCathTime", + "gCathState", + "gCombo", + "gDome", + "gEmagCar", + "gImageCurr", "gimagemax", - "gimagerot", - "glkbtns", - "glkbridge", - "glkelev", - "glview", - "glviewmpos", - "glviewpos", - "gnmagrot", - "gnmagcar", - "gpinup", - "gpinpos", - "gpinsmpos", - "grview", - "grviewmpos", - "grviewpos", - "gscribe", - "gscribetime", - "gsubelev", - "gsubdr", - "gupmoov", - "gwhark", - "gwharktime", + "gImageRot", + "gLkBtns", + "gLkBridge", + "gLkElev", + "gLView", + "gLViewMPos", + "gLViewPos", + "gNmagRot", + "gNmagCar", + "gPinUp", + "gPinPos", + "gPinsMPos", + "gRView", + "gRViewMPos", + "gRViewPos", + "gScribe", + "gScribeTime", + "gSubElev", + "gSubDr", + "gUpMoov", + "gWhark", + "gWharkTime", // jspit - "jwmagcar", - "jbeetle", - "jbeetlepool", - "jbook", - "jbridge1", - "jbridge2", - "jbridge3", - "jbridge4", - "jbridge5", - "jccb", - "jcombo", - "jcrg", - "jdome", - "jdrain", - "jgallows", - "jgate", - "jgirl", - "jiconcorrectorder", - "jiconorder", - "jicons", - "jladder", - "jleftpos", - "jpeek", - "jplaybeetle", - "jprebel", - "jprisondr", - "jprisonsecdr", - "jrbook", - "jrightpos", - "jsouthpathdr", - "jschooldr", - "jsub", - "jsubdir", - "jsubhatch", - "jsubsw", - "jsunners", - "jsunnertime", - "jthronedr", - "jtunneldr", - "jtunnellamps", - "jvillagepeople", - "jwarning", - "jwharkpos", - "jwharkram", - "jwmouth", - "jwmagcar", - "jymagcar", + "jWMagCar", + "jBeetle", + "jBeetlePool", + "jBook", + "jBridge1", + "jBridge2", + "jBridge3", + "jBridge4", + "jBridge5", + "jCCB", + "jCombo", + "jCrg", + "jDome", + "jDrain", + "jGallows", + "jGate", + "jGirl", + "jIconCorrectOrder", + "jIconOrder", + "jIcons", + "jLadder", + "jLeftPos", + "jPeek", + "jPlayBeetle", + "jPRebel", + "jPrisonDr", + "jPrisonSecDr", + "jrBook", + "jRightPos", + "jSouthPathDr", + "jSchoolDr", + "jSub", + "jSubDir", + "jSubHatch", + "jSubSw", + "jSunners", + "jSunnerTime", + "jThroneDr", + "jTunnelDr", + "jTunnelLamps", + "jVillagePeople", + "jWarning", + "jWharkPos", + "jWharkRam", + "jWMouth", + "jWMagCar", + "jYMagCar", // ospit "oambient", - "obutton", + "oButton", "ocage", - "odeskbook", - "ogehnpage", - "omusicplayer", - "ostanddrawer", - "ostove", + "oDeskBook", + "oGehnPage", + "oMusicPlayer", + "oStandDrawer", + "oStove", // pspit - "pbook", - "pcage", - "pcathcheck", - "pcathstate", - "pcathtime", - "pcombo", - "pcorrectorder", + "pBook", + "pCage", + "pCathCheck", + "pCathState", + "pCathTime", + "pCombo", + "pCorrectOrder", "pdome", - "pelevcombo", - "pleftpos", - "prightpos", - "ptemp", - "pwharkpos", + "pElevCombo", + "pLeftPos", + "pRightPos", + "pTemp", + "pWharkPos", // rspit - "rrebel", - "rrebelview", - "rrichard", - "rvillagetime", + "rRebel", + "rRebelView", + "rRichard", + "rVillageTime", // tspit - "tbars", - "tbeetle", - "tblue", - "tbook", - "tbookvalve", - "tcage", - "tcombo", - "tcorrectorder", - "tcovercombo", - "tdl", - "tdome", - "tdomeelev", - "tdomeelevbtn", - "tgatebrhandle", - "tgatebridge", - "tgatestate", - "tgreen", - "tgridoor", - "tgrodoor", - "tgrmdoor", - "tguard", - "timagedoor", - "tmagcar", - "torange", - "tred", - "tsecdoor", - "tsubbridge", - "ttelecover", - "ttelehandle", - "ttelepin", - "ttelescope", - "ttelevalve", - "ttemple", - "ttempledoor", - "ttunneldoor", - "tviewer", - "tviolet", - "twabrvalve", - "twaffle", - "tyellow", + "tBars", + "tBeetle", + "tBlue", + "tBook", + "tBookValve", + "tCage", + "tCombo", + "tCorrectOrder", + "tCoverCombo", + "tDL", + "tDome", + "tDomeElev", + "tDomeElevBtn", + "tGateBrHandle", + "tGateBridge", + "tGateState", + "tGreen", + "tGRIDoor", + "tGRODoor", + "tGRMDoor", + "tGuard", + "tImageDoor", + "tMagCar", + "tOrange", + "tRed", + "tSecDoor", + "tSubBridge", + "tTeleCover", + "tTeleHandle", + "tTelePin", + "tTelescope", + "tTeleValve", + "tTemple", + "tTempleDoor", + "tTunnelDoor", + "tViewer", + "tViolet", + "tWaBrValve", + "tWaffle", + "tYellow", // Miscellaneous "elevbtn1", "elevbtn2", "elevbtn3", - "domecheck", - "transitionsenabled", - "transitionmode", - "waterenabled", - "rivenambients", - "stackvarsinitialized", - "doingsetupscreens", + "domeCheck", + "transitionsEnabled", + "transitionMode", + "waterEnabled", + "RivenAmbients", + "stackVarsInitialized", + "DoingSetupScreens", "all_book", - "playerhasbook", - "returnstackid", - "returncardid", - "newpos", - "themarble", - "currentstackid", - "currentcardid" + "playerHasBook", + "returnStackID", + "returnCardID", + "NewPos", + "theMarble", + "CurrentStackID", + "CurrentCardID" }; uint32 &MohawkEngine_Riven::getStackVar(uint32 index) { diff --git a/engines/mortevielle/debugger.cpp b/engines/mortevielle/debugger.cpp index c8f75918ab..b2c99b894a 100644 --- a/engines/mortevielle/debugger.cpp +++ b/engines/mortevielle/debugger.cpp @@ -27,9 +27,9 @@ namespace Mortevielle { Debugger::Debugger(MortevielleEngine *vm) : GUI::Debugger() { _vm = vm; - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("show_questions", WRAP_METHOD(Debugger, Cmd_showAllQuestions)); - DCmd_Register("reset_parano", WRAP_METHOD(Debugger, Cmd_resetParano)); + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("show_questions", WRAP_METHOD(Debugger, Cmd_showAllQuestions)); + registerCmd("reset_parano", WRAP_METHOD(Debugger, Cmd_resetParano)); } bool Debugger::Cmd_showAllQuestions(int argc, const char **argv) { diff --git a/engines/neverhood/console.cpp b/engines/neverhood/console.cpp index a4d1366880..91ab3e767a 100644 --- a/engines/neverhood/console.cpp +++ b/engines/neverhood/console.cpp @@ -34,13 +34,13 @@ namespace Neverhood { Console::Console(NeverhoodEngine *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("cheat", WRAP_METHOD(Console, Cmd_Cheat)); - DCmd_Register("checkresource", WRAP_METHOD(Console, Cmd_CheckResource)); - DCmd_Register("dumpresource", WRAP_METHOD(Console, Cmd_DumpResource)); - DCmd_Register("dumpvars", WRAP_METHOD(Console, Cmd_Dumpvars)); - DCmd_Register("playsound", WRAP_METHOD(Console, Cmd_PlaySound)); - DCmd_Register("scene", WRAP_METHOD(Console, Cmd_Scene)); - DCmd_Register("surfaces", WRAP_METHOD(Console, Cmd_Surfaces)); + registerCmd("cheat", WRAP_METHOD(Console, Cmd_Cheat)); + registerCmd("checkresource", WRAP_METHOD(Console, Cmd_CheckResource)); + registerCmd("dumpresource", WRAP_METHOD(Console, Cmd_DumpResource)); + registerCmd("dumpvars", WRAP_METHOD(Console, Cmd_Dumpvars)); + registerCmd("playsound", WRAP_METHOD(Console, Cmd_PlaySound)); + registerCmd("scene", WRAP_METHOD(Console, Cmd_Scene)); + registerCmd("surfaces", WRAP_METHOD(Console, Cmd_Surfaces)); } Console::~Console() { @@ -55,33 +55,33 @@ bool Console::Cmd_Scene(int argc, const char **argv) { const char *sceneTypes[] = { "normal", "smacker", "navigation" }; - DebugPrintf("Current module: %d, previous module: %d, scene %d (%s scene)\n", currentModule, previousModule, scenenNum, sceneTypes[sceneType]); + debugPrintf("Current module: %d, previous module: %d, scene %d (%s scene)\n", currentModule, previousModule, scenenNum, sceneTypes[sceneType]); if (sceneType == kSceneTypeNormal) { Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; // Normal scenes have a background and a cursor file hash - DebugPrintf("Background hash: 0x%x, cursor hash: 0x%x\n", scene->getBackgroundFileHash(), scene->getCursorFileHash()); + debugPrintf("Background hash: 0x%x, cursor hash: 0x%x\n", scene->getBackgroundFileHash(), scene->getCursorFileHash()); } else if (sceneType == kSceneTypeSmacker) { SmackerScene *scene = (SmackerScene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; // Smacker scenes have a file hash, or a list of hashes // TODO: Only the first file hash is shown - any additional hashes, found in // scenes with a list of hashes (two scenes in module 1100 and the making of // video) aren't shown yet - DebugPrintf("File hash: 0x%x\n", scene->getSmackerFileHash()); + debugPrintf("File hash: 0x%x\n", scene->getSmackerFileHash()); } else if (sceneType == kSceneTypeNavigation) { NavigationScene *scene = (NavigationScene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; // Navigation scenes have a navigation list and its index NavigationList *navigationList = _vm->_staticData->getNavigationList(scene->getNavigationListId()); int navigationIndex = scene->getGlobalVar(V_NAVIGATION_INDEX); NavigationItem curNavigation = (*navigationList)[navigationIndex]; - DebugPrintf("Navigation list ID: 0x%x, index: %d\n", scene->getNavigationListId(), navigationIndex); - DebugPrintf("File hash: 0x%x, cursor hash: 0x%x, Smacker hashes: [left: 0x%x, middle: 0x%x, right: 0x%x\n", + debugPrintf("Navigation list ID: 0x%x, index: %d\n", scene->getNavigationListId(), navigationIndex); + debugPrintf("File hash: 0x%x, cursor hash: 0x%x, Smacker hashes: [left: 0x%x, middle: 0x%x, right: 0x%x\n", curNavigation.fileHash, curNavigation.mouseCursorFileHash, curNavigation.leftSmackerFileHash, curNavigation.middleSmackerFileHash, curNavigation.rightSmackerFileHash); } - DebugPrintf("Use %s <module> <scene> to change scenes\n", argv[0]); - DebugPrintf("Modules are incremental by 100, from 1000 to 3000\n"); + debugPrintf("Use %s <module> <scene> to change scenes\n", argv[0]); + debugPrintf("Modules are incremental by 100, from 1000 to 3000\n"); } else { int newModule = atoi(argv[1]); int newScene = atoi(argv[2]); @@ -102,17 +102,17 @@ bool Console::Cmd_Surfaces(int argc, const char **argv) { bool Console::Cmd_Cheat(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Cheats for various puzzles in the game\n"); - DebugPrintf("Use %s <cheatname> to use a cheat.\n", argv[0]); - DebugPrintf("Cheats:\n-------\n"); - DebugPrintf(" buttons - enables all 3 buttons on the door in the purple building, module 3000, scene 9\n"); - DebugPrintf(" cannon - sets the correct cannon combination in module 3000, scene 8\n"); - DebugPrintf(" dice - shows the correct dice combination in the teddy bear puzzle, module 1100, scene 6\n"); - DebugPrintf(" memory - solves the memory puzzle, module 1400, scene 4\n"); - DebugPrintf(" music - shows the correct index in the radio music puzzle, module 2800, scene 1\n"); - DebugPrintf(" radio - enables the radio, module 3000, scene 9 - same as pulling the rightmost cord in the flytrap room\n"); - DebugPrintf(" symbols - solves the symbols puzzle, module 1600, scene 8. Only available in that room\n"); - DebugPrintf(" tubes - shows the correct test tube combination in module 2800, scenes 7 and 10\n"); + debugPrintf("Cheats for various puzzles in the game\n"); + debugPrintf("Use %s <cheatname> to use a cheat.\n", argv[0]); + debugPrintf("Cheats:\n-------\n"); + debugPrintf(" buttons - enables all 3 buttons on the door in the purple building, module 3000, scene 9\n"); + debugPrintf(" cannon - sets the correct cannon combination in module 3000, scene 8\n"); + debugPrintf(" dice - shows the correct dice combination in the teddy bear puzzle, module 1100, scene 6\n"); + debugPrintf(" memory - solves the memory puzzle, module 1400, scene 4\n"); + debugPrintf(" music - shows the correct index in the radio music puzzle, module 2800, scene 1\n"); + debugPrintf(" radio - enables the radio, module 3000, scene 9 - same as pulling the rightmost cord in the flytrap room\n"); + debugPrintf(" symbols - solves the symbols puzzle, module 1600, scene 8. Only available in that room\n"); + debugPrintf(" tubes - shows the correct test tube combination in module 2800, scenes 7 and 10\n"); return true; } @@ -127,7 +127,7 @@ bool Console::Cmd_Cheat(int argc, const char **argv) { scene->setSubVar(VA_LOCKS_DISABLED, 0x40119852, 1); // kScene3010ButtonNameHashes[1] scene->setSubVar(VA_LOCKS_DISABLED, 0x01180951, 1); // kScene3010ButtonNameHashes[2] - DebugPrintf("All 3 door buttons have been enabled\n"); + debugPrintf("All 3 door buttons have been enabled\n"); } else if (cheatName == "cannon") { Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; @@ -137,10 +137,10 @@ bool Console::Cmd_Cheat(int argc, const char **argv) { for (int i = 3; i < 6; i++) scene->setSubVar(VA_CURR_CANNON_SYMBOLS, i, scene->getSubVar(VA_GOOD_CANNON_SYMBOLS_2, i - 3)); - DebugPrintf("Puzzle solved\n"); + debugPrintf("Puzzle solved\n"); } else if (cheatName == "dice") { Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; - DebugPrintf("Good: (%d %d %d), current: (%d %d %d)\n", + debugPrintf("Good: (%d %d %d), current: (%d %d %d)\n", scene->getSubVar(VA_GOOD_DICE_NUMBERS, 0), scene->getSubVar(VA_GOOD_DICE_NUMBERS, 1), scene->getSubVar(VA_GOOD_DICE_NUMBERS, 2), scene->getSubVar(VA_CURR_DICE_NUMBERS, 0), scene->getSubVar(VA_CURR_DICE_NUMBERS, 1), scene->getSubVar(VA_CURR_DICE_NUMBERS, 2) ); @@ -162,15 +162,15 @@ bool Console::Cmd_Cheat(int argc, const char **argv) { } } - DebugPrintf("Puzzle solved\n"); + debugPrintf("Puzzle solved\n"); } else if (cheatName == "music") { Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; - DebugPrintf("Good music index: %d, current radio music index: %d\n", scene->getGlobalVar(V_CURR_RADIO_MUSIC_INDEX), scene->getGlobalVar(V_GOOD_RADIO_MUSIC_INDEX)); + debugPrintf("Good music index: %d, current radio music index: %d\n", scene->getGlobalVar(V_CURR_RADIO_MUSIC_INDEX), scene->getGlobalVar(V_GOOD_RADIO_MUSIC_INDEX)); } else if (cheatName == "radio") { Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; scene->setGlobalVar(V_RADIO_ENABLED, 1); - DebugPrintf("The radio has been enabled\n"); + debugPrintf("The radio has been enabled\n"); } else if (cheatName == "symbols") { if (moduleNum == 1600 && sceneNum == 8) { Scene1609 *scene = ((Scene1609 *)((Module1600 *)_vm->_gameModule->_childObject)->_childObject); @@ -183,14 +183,14 @@ bool Console::Cmd_Cheat(int argc, const char **argv) { scene->_symbolPosition = 11; scene->_countdown1 = 36; - DebugPrintf("Puzzle solved\n"); + debugPrintf("Puzzle solved\n"); } else { - DebugPrintf("Only available in module 1600, scene 8\n"); + debugPrintf("Only available in module 1600, scene 8\n"); } } else if (cheatName == "tubes") { Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; - DebugPrintf("Tube set 1: %d %d %d\n", scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2)); - DebugPrintf("Tube set 2: %d %d %d\n", scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 0), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 1), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 2)); + debugPrintf("Tube set 1: %d %d %d\n", scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2)); + debugPrintf("Tube set 2: %d %d %d\n", scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 0), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 1), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 2)); } return true; @@ -204,7 +204,7 @@ bool Console::Cmd_Dumpvars(int argc, const char **argv) { bool Console::Cmd_PlaySound(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: %s <sound hash>\n", argv[0]); + debugPrintf("Usage: %s <sound hash>\n", argv[0]); } else { uint32 soundHash = strtol(argv[1], NULL, 0); AudioResourceManSoundItem *soundItem = new AudioResourceManSoundItem(_vm, soundHash); @@ -223,17 +223,17 @@ bool Console::Cmd_CheckResource(int argc, const char **argv) { const char *resourceNames[] = { "unknown", "unknown", "bitmap", "palette", "animation", "data", "text", "sound", "music", "unknown", "video" }; if (argc < 2) { - DebugPrintf("Gets information about a resource\n"); - DebugPrintf("Usage: %s <resource hash>\n", argv[0]); + debugPrintf("Gets information about a resource\n"); + debugPrintf("Usage: %s <resource hash>\n", argv[0]); } else { uint32 resourceHash = strtol(argv[1], NULL, 0); ResourceHandle handle; _vm->_res->queryResource(resourceHash, handle); if (!handle.isValid()) { - DebugPrintf("Invalid resource hash\n"); + debugPrintf("Invalid resource hash\n"); } else { - DebugPrintf("Resource type: %d (%s). Size: %d bytes\n", handle.type(), resourceNames[handle.type()], handle.size()); + debugPrintf("Resource type: %d (%s). Size: %d bytes\n", handle.type(), resourceNames[handle.type()], handle.size()); } } @@ -242,8 +242,8 @@ bool Console::Cmd_CheckResource(int argc, const char **argv) { bool Console::Cmd_DumpResource(int argc, const char **argv) { if (argc < 3) { - DebugPrintf("Dumps a resource to disk\n"); - DebugPrintf("Usage: %s <resource hash> <output file>\n", argv[0]); + debugPrintf("Dumps a resource to disk\n"); + debugPrintf("Usage: %s <resource hash> <output file>\n", argv[0]); } else { uint32 resourceHash = strtol(argv[1], NULL, 0); const char *outFileName = argv[2]; @@ -251,7 +251,7 @@ bool Console::Cmd_DumpResource(int argc, const char **argv) { _vm->_res->queryResource(resourceHash, handle); if (!handle.isValid()) { - DebugPrintf("Invalid resource hash\n"); + debugPrintf("Invalid resource hash\n"); } else { _vm->_res->loadResource(handle, _vm->applyResourceFixes()); Common::DumpFile outFile; diff --git a/engines/neverhood/gamevars.cpp b/engines/neverhood/gamevars.cpp index 72b688c194..dcbe5583de 100644 --- a/engines/neverhood/gamevars.cpp +++ b/engines/neverhood/gamevars.cpp @@ -127,7 +127,7 @@ int16 GameVars::getSubVarIndex(int16 varIndex, uint32 subNameHash) { void GameVars::dumpVars(Console *con) { for (Common::Array<GameVar>::iterator it = _vars.begin(); it != _vars.end(); ++it) { GameVar gameVar = *it; - con->DebugPrintf("hash: %08X, var: %08X, first index: %3d, next index: %3d\n", gameVar.nameHash, gameVar.value, gameVar.firstIndex, gameVar.nextIndex); + con->debugPrintf("hash: %08X, var: %08X, first index: %3d, next index: %3d\n", gameVar.nameHash, gameVar.value, gameVar.firstIndex, gameVar.nextIndex); } } diff --git a/engines/neverhood/graphics.cpp b/engines/neverhood/graphics.cpp index 3d1724ed8a..939428ed19 100644 --- a/engines/neverhood/graphics.cpp +++ b/engines/neverhood/graphics.cpp @@ -47,6 +47,7 @@ BaseSurface::BaseSurface(NeverhoodEngine *vm, int priority, int16 width, int16 h } BaseSurface::~BaseSurface() { + _surface->free(); delete _surface; } diff --git a/engines/neverhood/modules/module1000.cpp b/engines/neverhood/modules/module1000.cpp index b19ba05b32..5e4d67d2bc 100644 --- a/engines/neverhood/modules/module1000.cpp +++ b/engines/neverhood/modules/module1000.cpp @@ -693,22 +693,18 @@ uint32 Scene1005::getTextIndex1() { uint32 Scene1005::getKloggsTextIndex() { uint32 textIndex = getGlobalVar(V_TEXT_COUNTING_INDEX1); if (textIndex + 1 > 10) { - setGlobalVar(V_TEXT_COUNTING_INDEX1, 0); textIndex = 0; - } else { - setGlobalVar(V_TEXT_COUNTING_INDEX1, textIndex + 1); } + setGlobalVar(V_TEXT_COUNTING_INDEX1, textIndex + 1); return textIndex + 40; } uint32 Scene1005::getTextIndex3() { uint32 textIndex = getGlobalVar(V_TEXT_COUNTING_INDEX2); - if (textIndex + 1 >= 10) { - setGlobalVar(V_TEXT_COUNTING_INDEX2, 0); + if (textIndex + 1 > 10) { textIndex = 0; - } else { - setGlobalVar(V_TEXT_COUNTING_INDEX2, textIndex + 1); } + setGlobalVar(V_TEXT_COUNTING_INDEX2, textIndex + 1); return textIndex + 30; } diff --git a/engines/neverhood/scene.cpp b/engines/neverhood/scene.cpp index 58056b65a9..1a8e74da38 100644 --- a/engines/neverhood/scene.cpp +++ b/engines/neverhood/scene.cpp @@ -148,7 +148,7 @@ void Scene::printSurfaces(Console *con) { NDrawRect drawRect = _surfaces[index]->getDrawRect(); NRect clipRect = _surfaces[index]->getClipRect(); int priority = _surfaces[index]->getPriority(); - con->DebugPrintf("%d ('%s'): Priority %d, draw rect (%d, %d, %d, %d), clip rect (%d, %d, %d, %d)\n", + con->debugPrintf("%d ('%s'): Priority %d, draw rect (%d, %d, %d, %d), clip rect (%d, %d, %d, %d)\n", index, _surfaces[index]->getName().c_str(), priority, drawRect.x, drawRect.y, drawRect.x2(), drawRect.y2(), clipRect.x1, clipRect.y1, clipRect.x2, clipRect.y2); diff --git a/engines/neverhood/staticdata.cpp b/engines/neverhood/staticdata.cpp index 552ea92604..03af44b2a5 100644 --- a/engines/neverhood/staticdata.cpp +++ b/engines/neverhood/staticdata.cpp @@ -28,6 +28,18 @@ StaticData::StaticData() { } StaticData::~StaticData() { + for (Common::HashMap<uint32, HitRectList*>::iterator i = _hitRectLists.begin(); i != _hitRectLists.end(); ++i) + delete i->_value; + for (Common::HashMap<uint32, RectList*>::iterator i = _rectLists.begin(); i != _rectLists.end(); ++i) + delete i->_value; + for (Common::HashMap<uint32, MessageList*>::iterator i = _messageLists.begin(); i != _messageLists.end(); ++i) + delete i->_value; + for (Common::HashMap<uint32, NavigationList*>::iterator i = _navigationLists.begin(); i != _navigationLists.end(); ++i) + delete i->_value; + for (Common::HashMap<uint32, HallOfRecordsInfo*>::iterator i = _hallOfRecordsInfoItems.begin(); i != _hallOfRecordsInfoItems.end(); ++i) + delete i->_value; + for (Common::HashMap<uint32, TrackInfo*>::iterator i = _trackInfoItems.begin(); i != _trackInfoItems.end(); ++i) + delete i->_value; } void StaticData::load(const char *filename) { @@ -69,6 +81,11 @@ void StaticData::load(const char *filename) { messageList->push_back(messageItem); } + if(_messageLists.contains(id)) { + warning("Duplicate id %d in _messageLists - freeing older entry", id); + delete _messageLists[id]; + } + _messageLists[id] = messageList; } @@ -98,6 +115,12 @@ void StaticData::load(const char *filename) { } rectList->push_back(rectItem); } + + if(_rectLists.contains(id)) { + warning("Duplicate id %d in _rectLists - freeing older entry", id); + delete _rectLists[id]; + } + _rectLists[id] = rectList; } @@ -117,6 +140,12 @@ void StaticData::load(const char *filename) { hitRect.type = fd.readUint16LE(); hitRectList->push_back(hitRect); } + + if(_hitRectLists.contains(id)) { + warning("Duplicate id %d in _hitRectLists - freeing older entry", id); + delete _hitRectLists[id]; + } + _hitRectLists[id] = hitRectList; } @@ -138,6 +167,12 @@ void StaticData::load(const char *filename) { navigationItem.mouseCursorFileHash = fd.readUint32LE(); navigationList->push_back(navigationItem); } + + if(_navigationLists.contains(id)) { + warning("Duplicate id %d in _navigationLists - freeing older entry", id); + delete _navigationLists[id]; + } + _navigationLists[id] = navigationList; } @@ -153,6 +188,12 @@ void StaticData::load(const char *filename) { hallOfRecordsInfo->bgFilename3 = fd.readUint32LE(); hallOfRecordsInfo->xPosIndex = fd.readByte(); hallOfRecordsInfo->count = fd.readByte(); + + if(_hallOfRecordsInfoItems.contains(id)) { + warning("Duplicate id %d in _hallOfRecordsInfoItems - freeing older entry", id); + delete _hallOfRecordsInfoItems[id]; + } + _hallOfRecordsInfoItems[id] = hallOfRecordsInfo; } @@ -172,6 +213,12 @@ void StaticData::load(const char *filename) { trackInfo->mouseCursorFilename = fd.readUint32LE(); trackInfo->which1 = fd.readUint16LE(); trackInfo->which2 = fd.readUint16LE(); + + if(_trackInfoItems.contains(id)) { + warning("Duplicate id %d in _trackInfoItems - freeing older entry", id); + delete _trackInfoItems[id]; + } + _trackInfoItems[id] = trackInfo; } diff --git a/engines/parallaction/debug.cpp b/engines/parallaction/debug.cpp index 1fea73a326..a7087c64d7 100644 --- a/engines/parallaction/debug.cpp +++ b/engines/parallaction/debug.cpp @@ -33,18 +33,18 @@ Debugger::Debugger(Parallaction *vm) : GUI::Debugger() { _vm = vm; - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("location", WRAP_METHOD(Debugger, Cmd_Location)); - DCmd_Register("give", WRAP_METHOD(Debugger, Cmd_Give)); - DCmd_Register("zones", WRAP_METHOD(Debugger, Cmd_Zones)); - DCmd_Register("animations", WRAP_METHOD(Debugger, Cmd_Animations)); - DCmd_Register("globalflags",WRAP_METHOD(Debugger, Cmd_GlobalFlags)); - DCmd_Register("toggleglobalflag",WRAP_METHOD(Debugger, Cmd_ToggleGlobalFlag)); - DCmd_Register("localflags", WRAP_METHOD(Debugger, Cmd_LocalFlags)); - DCmd_Register("locations", WRAP_METHOD(Debugger, Cmd_Locations)); - DCmd_Register("gfxobjects", WRAP_METHOD(Debugger, Cmd_GfxObjects)); - DCmd_Register("programs", WRAP_METHOD(Debugger, Cmd_Programs)); - DCmd_Register("showmouse", WRAP_METHOD(Debugger, Cmd_ShowMouse)); + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("location", WRAP_METHOD(Debugger, Cmd_Location)); + registerCmd("give", WRAP_METHOD(Debugger, Cmd_Give)); + registerCmd("zones", WRAP_METHOD(Debugger, Cmd_Zones)); + registerCmd("animations", WRAP_METHOD(Debugger, Cmd_Animations)); + registerCmd("globalflags",WRAP_METHOD(Debugger, Cmd_GlobalFlags)); + registerCmd("toggleglobalflag",WRAP_METHOD(Debugger, Cmd_ToggleGlobalFlag)); + registerCmd("localflags", WRAP_METHOD(Debugger, Cmd_LocalFlags)); + registerCmd("locations", WRAP_METHOD(Debugger, Cmd_Locations)); + registerCmd("gfxobjects", WRAP_METHOD(Debugger, Cmd_GfxObjects)); + registerCmd("programs", WRAP_METHOD(Debugger, Cmd_Programs)); + registerCmd("showmouse", WRAP_METHOD(Debugger, Cmd_ShowMouse)); } @@ -81,7 +81,7 @@ bool Debugger::Cmd_Location(int argc, const char **argv) { break; case 1: - DebugPrintf("location <location name> [character name]\n"); + debugPrintf("location <location name> [character name]\n"); } @@ -90,13 +90,13 @@ bool Debugger::Cmd_Location(int argc, const char **argv) { bool Debugger::Cmd_Locations(int argc, const char **argv) { - DebugPrintf("+------------------------------+---------+\n" + debugPrintf("+------------------------------+---------+\n" "| location name | flags |\n" "+------------------------------+---------+\n"); for (uint i = 0; i < _vm->_numLocations; i++) { - DebugPrintf("|%-30s| %08x|\n", _vm->_locationNames[i], _vm->_localFlags[i]); + debugPrintf("|%-30s| %08x|\n", _vm->_locationNames[i], _vm->_localFlags[i]); } - DebugPrintf("+------------------------------+---------+\n"); + debugPrintf("+------------------------------+---------+\n"); return true; } @@ -105,14 +105,14 @@ bool Debugger::Cmd_GlobalFlags(int argc, const char **argv) { uint32 flags = g_globalFlags; - DebugPrintf("+------------------------------+---------+\n" + debugPrintf("+------------------------------+---------+\n" "| flag name | value |\n" "+------------------------------+---------+\n"); for (uint i = 0; i < _vm->_globalFlagsNames->count(); i++) { const char *value = ((flags & (1 << i)) == 0) ? "OFF" : "ON"; - DebugPrintf("|%-30s| %-6s|\n", _vm->_globalFlagsNames->item(i), value); + debugPrintf("|%-30s| %-6s|\n", _vm->_globalFlagsNames->item(i), value); } - DebugPrintf("+------------------------------+---------+\n"); + debugPrintf("+------------------------------+---------+\n"); return true; } @@ -125,7 +125,7 @@ bool Debugger::Cmd_ToggleGlobalFlag(int argc, const char **argv) { case 2: i = _vm->_globalFlagsNames->lookup(argv[1]); if (i == Table::notFound) { - DebugPrintf("invalid flag '%s'\n", argv[1]); + debugPrintf("invalid flag '%s'\n", argv[1]); } else { i--; if ((g_globalFlags & (1 << i)) == 0) @@ -136,7 +136,7 @@ bool Debugger::Cmd_ToggleGlobalFlag(int argc, const char **argv) { break; default: - DebugPrintf("toggleglobalflag <flag name>\n"); + debugPrintf("toggleglobalflag <flag name>\n"); } @@ -147,14 +147,14 @@ bool Debugger::Cmd_LocalFlags(int argc, const char **argv) { uint32 flags = _vm->getLocationFlags(); - DebugPrintf("+------------------------------+---------+\n" + debugPrintf("+------------------------------+---------+\n" "| flag name | value |\n" "+------------------------------+---------+\n"); for (uint i = 0; i < _vm->_localFlagNames->count(); i++) { const char *value = ((flags & (1 << i)) == 0) ? "OFF" : "ON"; - DebugPrintf("|%-30s| %-6s|\n", _vm->_localFlagNames->item(i), value); + debugPrintf("|%-30s| %-6s|\n", _vm->_localFlagNames->item(i), value); } - DebugPrintf("+------------------------------+---------+\n"); + debugPrintf("+------------------------------+---------+\n"); return true; } @@ -162,13 +162,13 @@ bool Debugger::Cmd_LocalFlags(int argc, const char **argv) { bool Debugger::Cmd_Give(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("give <item name>\n"); + debugPrintf("give <item name>\n"); } else { int index = _vm->_objectsNames->lookup(argv[1]); if (index != Table::notFound) _vm->addInventoryItem(index + 4); else - DebugPrintf("invalid item name '%s'\n", argv[1]); + debugPrintf("invalid item name '%s'\n", argv[1]); } return true; @@ -181,15 +181,15 @@ bool Debugger::Cmd_Zones(int argc, const char **argv) { ZoneList::iterator e = _vm->_location._zones.end(); Common::Rect r; - DebugPrintf("+--------------------+---+---+---+---+--------+--------+\n" + debugPrintf("+--------------------+---+---+---+---+--------+--------+\n" "| name | l | t | r | b | type | flag |\n" "+--------------------+---+---+---+---+--------+--------+\n"); for ( ; b != e; ++b) { ZonePtr z = *b; z->getRect(r); - DebugPrintf("|%-20s|%3i|%3i|%3i|%3i|%8x|%8x|\n", z->_name, r.left, r.top, r.right, r.bottom, z->_type, z->_flags ); + debugPrintf("|%-20s|%3i|%3i|%3i|%3i|%8x|%8x|\n", z->_name, r.left, r.top, r.right, r.bottom, z->_type, z->_flags ); } - DebugPrintf("+--------------------+---+---+---+---+--------+--------+\n"); + debugPrintf("+--------------------+---+---+---+---+--------+--------+\n"); return true; @@ -260,15 +260,15 @@ bool Debugger::Cmd_Animations(int argc, const char **argv) { AnimationList::iterator e = _vm->_location._animations.end(); Common::String flags; - DebugPrintf("+--------------------+----+----+----+---+--------+----------------------------------------+\n" + debugPrintf("+--------------------+----+----+----+---+--------+----------------------------------------+\n" "| name | x | y | z | f | type | flags | \n" "+--------------------+----+----+----+---+--------+----------------------------------------+\n"); for ( ; b != e; ++b) { AnimationPtr a = *b; flags = decodeZoneFlags(a->_flags); - DebugPrintf("|%-20s|%4i|%4i|%4i|%3i|%8x|%-40s|\n", a->_name, a->getX(), a->getY(), a->getZ(), a->getF(), a->_type, flags.c_str() ); + debugPrintf("|%-20s|%4i|%4i|%4i|%3i|%8x|%-40s|\n", a->_name, a->getX(), a->getY(), a->getZ(), a->getF(), a->_type, flags.c_str() ); } - DebugPrintf("+--------------------+---+---+---+---+--------+----------------------------------------+\n"); + debugPrintf("+--------------------+---+---+---+---+--------+----------------------------------------+\n"); return true; @@ -278,7 +278,7 @@ bool Debugger::Cmd_GfxObjects(int argc, const char **argv) { const char *objType[] = { "DOOR", "GET", "ANIM" }; - DebugPrintf("+--------------------+-----+-----+-----+-----+-----+-------+-----+--------+\n" + debugPrintf("+--------------------+-----+-----+-----+-----+-----+-------+-----+--------+\n" "| name | x | y | w | h | z | layer | f | type |\n" "+--------------------+-----+-----+-----+-----+-----+-------+-----+--------+\n"); @@ -289,11 +289,11 @@ bool Debugger::Cmd_GfxObjects(int argc, const char **argv) { for ( ; b != e; ++b) { GfxObj *obj = *b; obj->getRect(obj->frame, r); - DebugPrintf("|%-20s|%5i|%5i|%5i|%5i|%5i|%7i|%5i|%8s|\n", obj->getName(), r.left, r.top, r.width(), r.height(), + debugPrintf("|%-20s|%5i|%5i|%5i|%5i|%5i|%7i|%5i|%8s|\n", obj->getName(), r.left, r.top, r.width(), r.height(), obj->z, obj->layer, obj->frame, objType[obj->type]); } - DebugPrintf("+--------------------+-----+-----+-----+-----+-----+-------+-----+--------+\n"); + debugPrintf("+--------------------+-----+-----+-----+-----+-----+-------+-----+--------+\n"); return true; } @@ -307,14 +307,14 @@ bool Debugger::Cmd_Programs(int argc, const char** argv) { int i = 1; - DebugPrintf("+---+--------------------+--------+----------+\n" + debugPrintf("+---+--------------------+--------+----------+\n" "| # | bound animation | size | status |\n" "+---+--------------------+--------+----------+\n"); for ( ; b != e; b++, i++) { ProgramPtr p = *b; - DebugPrintf("|%3i|%-20s|%8i|%-10s|\n", i, p->_anim->_name, p->_instructions.size(), status[p->_status] ); + debugPrintf("|%3i|%-20s|%8i|%-10s|\n", i, p->_anim->_name, p->_instructions.size(), status[p->_status] ); } - DebugPrintf("+---+--------------------+--------+----------+\n"); + debugPrintf("+---+--------------------+--------+----------+\n"); return true; } diff --git a/engines/parallaction/debug.h b/engines/parallaction/debug.h index 887d08e945..551d746edf 100644 --- a/engines/parallaction/debug.h +++ b/engines/parallaction/debug.h @@ -22,7 +22,6 @@ private: Parallaction *_vm; MouseTriState _mouseState; - bool Cmd_DebugLevel(int argc, const char **argv); bool Cmd_Location(int argc, const char **argv); bool Cmd_Give(int argc, const char **argv); bool Cmd_Zones(int argc, const char **argv); diff --git a/engines/pegasus/console.cpp b/engines/pegasus/console.cpp index 64bd0ba5f2..e5a0cfec98 100644 --- a/engines/pegasus/console.cpp +++ b/engines/pegasus/console.cpp @@ -28,11 +28,11 @@ namespace Pegasus { PegasusConsole::PegasusConsole(PegasusEngine *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("die", WRAP_METHOD(PegasusConsole, Cmd_Die)); + registerCmd("die", WRAP_METHOD(PegasusConsole, Cmd_Die)); // These functions are non-demo specific if (!_vm->isDemo()) - DCmd_Register("jump", WRAP_METHOD(PegasusConsole, Cmd_Jump)); + registerCmd("jump", WRAP_METHOD(PegasusConsole, Cmd_Jump)); } PegasusConsole::~PegasusConsole() { @@ -40,7 +40,7 @@ PegasusConsole::~PegasusConsole() { bool PegasusConsole::Cmd_Die(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: die <death reason>\n"); + debugPrintf("Usage: die <death reason>\n"); return true; } @@ -54,7 +54,7 @@ bool PegasusConsole::Cmd_Die(int argc, const char **argv) { if (invalidReason) { - DebugPrintf("Invalid death reason %d\n", reason); + debugPrintf("Invalid death reason %d\n", reason); return true; } @@ -65,14 +65,14 @@ bool PegasusConsole::Cmd_Die(int argc, const char **argv) { bool PegasusConsole::Cmd_Jump(int argc, const char **argv) { if (!g_interface) { // TODO - DebugPrintf("Cannot jump without interface set up\n"); + debugPrintf("Cannot jump without interface set up\n"); return true; } // TODO: Default room/direction for each neighborhood if (argc < 4) { - DebugPrintf("Usage: jump <neighborhood> <room> <direction>\n"); + debugPrintf("Usage: jump <neighborhood> <room> <direction>\n"); return true; } @@ -82,14 +82,14 @@ bool PegasusConsole::Cmd_Jump(int argc, const char **argv) { if ((neighborhood < kCaldoriaID || neighborhood > kNoradDeltaID || neighborhood == kFinalTSAID) && neighborhood != kNoradSubChaseID) { - DebugPrintf("Invalid neighborhood %d", neighborhood); + debugPrintf("Invalid neighborhood %d", neighborhood); return true; } // No real way to check room validity at this point if (direction > kWest) { - DebugPrintf("Invalid direction %d", direction); + debugPrintf("Invalid direction %d", direction); return true; } diff --git a/engines/queen/debug.cpp b/engines/queen/debug.cpp index 3706806ac2..125ddf30c6 100644 --- a/engines/queen/debug.cpp +++ b/engines/queen/debug.cpp @@ -36,15 +36,15 @@ namespace Queen { Debugger::Debugger(QueenEngine *vm) : _vm(vm), _flags(0) { - DCmd_Register("areas", WRAP_METHOD(Debugger, Cmd_Areas)); - DCmd_Register("asm", WRAP_METHOD(Debugger, Cmd_Asm)); - DCmd_Register("bob", WRAP_METHOD(Debugger, Cmd_Bob)); - DCmd_Register("bobs", WRAP_METHOD(Debugger, Cmd_PrintBobs)); - DCmd_Register("gs", WRAP_METHOD(Debugger, Cmd_GameState)); - DCmd_Register("info", WRAP_METHOD(Debugger, Cmd_Info)); - DCmd_Register("items", WRAP_METHOD(Debugger, Cmd_Items)); - DCmd_Register("room", WRAP_METHOD(Debugger, Cmd_Room)); - DCmd_Register("song", WRAP_METHOD(Debugger, Cmd_Song)); + registerCmd("areas", WRAP_METHOD(Debugger, Cmd_Areas)); + registerCmd("asm", WRAP_METHOD(Debugger, Cmd_Asm)); + registerCmd("bob", WRAP_METHOD(Debugger, Cmd_Bob)); + registerCmd("bobs", WRAP_METHOD(Debugger, Cmd_PrintBobs)); + registerCmd("gs", WRAP_METHOD(Debugger, Cmd_GameState)); + registerCmd("info", WRAP_METHOD(Debugger, Cmd_Info)); + registerCmd("items", WRAP_METHOD(Debugger, Cmd_Items)); + registerCmd("room", WRAP_METHOD(Debugger, Cmd_Room)); + registerCmd("song", WRAP_METHOD(Debugger, Cmd_Song)); } Debugger::~Debugger() {} // we need this here for __SYMBIAN32__ @@ -73,14 +73,14 @@ bool Debugger::Cmd_Asm(int argc, const char **argv) { _vm->logic()->executeSpecialMove(sm); return false; } else { - DebugPrintf("Usage: %s smnum\n", argv[0]); + debugPrintf("Usage: %s smnum\n", argv[0]); } return true; } bool Debugger::Cmd_Areas(int argc, const char **argv) { _flags ^= DF_DRAW_AREAS; - DebugPrintf("Room areas display %s\n", (_flags & DF_DRAW_AREAS) != 0 ? "on" : "off"); + debugPrintf("Room areas display %s\n", (_flags & DF_DRAW_AREAS) != 0 ? "on" : "off"); return true; } @@ -88,36 +88,36 @@ bool Debugger::Cmd_Bob(int argc, const char **argv) { if (argc >= 3 && isNumeric(argv[1])) { int bobNum = atoi(argv[1]); if (bobNum >= Graphics::MAX_BOBS_NUMBER) { - DebugPrintf("Bob %d is out of range (range: 0 - %d)\n", bobNum, Graphics::MAX_BOBS_NUMBER); + debugPrintf("Bob %d is out of range (range: 0 - %d)\n", bobNum, Graphics::MAX_BOBS_NUMBER); } else { int param = 0; if (argc > 3 && isNumeric(argv[3])) { param = atoi(argv[3]); } else { - DebugPrintf("Invalid parameter for bob command '%s'\n", argv[2]); + debugPrintf("Invalid parameter for bob command '%s'\n", argv[2]); } BobSlot *bob = _vm->graphics()->bob(bobNum); if (!strcmp(argv[2], "toggle")) { bob->active = !bob->active; - DebugPrintf("bob[%d].active = %d\n", bobNum, bob->active); + debugPrintf("bob[%d].active = %d\n", bobNum, bob->active); } else if (!strcmp(argv[2], "x")) { bob->x = param; - DebugPrintf("bob[%d].x = %d\n", bobNum, bob->x); + debugPrintf("bob[%d].x = %d\n", bobNum, bob->x); } else if (!strcmp(argv[2], "y")) { bob->y = param; - DebugPrintf("bob[%d].y = %d\n", bobNum, bob->y); + debugPrintf("bob[%d].y = %d\n", bobNum, bob->y); } else if (!strcmp(argv[2], "frame")) { bob->frameNum = param; - DebugPrintf("bob[%d].frameNum = %d\n", bobNum, bob->frameNum); + debugPrintf("bob[%d].frameNum = %d\n", bobNum, bob->frameNum); } else if (!strcmp(argv[2], "speed")) { bob->speed = param; - DebugPrintf("bob[%d].speed = %d\n", bobNum, bob->speed); + debugPrintf("bob[%d].speed = %d\n", bobNum, bob->speed); } else { - DebugPrintf("Unknown bob command '%s'\n", argv[2]); + debugPrintf("Unknown bob command '%s'\n", argv[2]); } } } else { - DebugPrintf("Usage: %s bobnum command parameter\n", argv[0]); + debugPrintf("Usage: %s bobnum command parameter\n", argv[0]); } return true; } @@ -126,26 +126,26 @@ bool Debugger::Cmd_GameState(int argc, const char **argv) { uint16 slot; if ((argc == 2 || argc == 3) && isNumeric(argv[1])) { slot = atoi(argv[1]); - DebugPrintf("GAMESTATE[%d] ", slot); - DebugPrintf("%s %d\n", (argc == 2) ? "is" : "was", _vm->logic()->gameState(slot)); + debugPrintf("GAMESTATE[%d] ", slot); + debugPrintf("%s %d\n", (argc == 2) ? "is" : "was", _vm->logic()->gameState(slot)); if (argc == 3) { if (isNumeric(argv[1])) { _vm->logic()->gameState(slot, atoi(argv[2])); - DebugPrintf("now %d\n", _vm->logic()->gameState(slot)); + debugPrintf("now %d\n", _vm->logic()->gameState(slot)); } else { - DebugPrintf("Usage: %s slotnum <value>\n", argv[0]); + debugPrintf("Usage: %s slotnum <value>\n", argv[0]); } } } else { - DebugPrintf("Usage: %s slotnum <value>\n", argv[0]); + debugPrintf("Usage: %s slotnum <value>\n", argv[0]); } return true; } bool Debugger::Cmd_Info(int argc, const char **argv) { - DebugPrintf("Version: %s\n", _vm->resource()->getJASVersion()); - DebugPrintf("Audio compression: %d\n", _vm->resource()->getCompression()); + debugPrintf("Version: %s\n", _vm->resource()->getJASVersion()); + debugPrintf("Audio compression: %d\n", _vm->resource()->getCompression()); return true; } @@ -156,24 +156,24 @@ bool Debugger::Cmd_Items(int argc, const char **argv) { item->name = ABS(item->name); ++item; } - DebugPrintf("Enabled all inventory items\n"); + debugPrintf("Enabled all inventory items\n"); return true; } bool Debugger::Cmd_PrintBobs(int argc, const char**argv) { int i; BobSlot *bob = _vm->graphics()->bob(0); - DebugPrintf("+------------------------------------+\n"); - DebugPrintf("|# | x| y|f|scl|frm|a|m|spd| ex| ey|\n"); - DebugPrintf("+--+---+---+-+---+---+-+-+---+---+---+\n"); + debugPrintf("+------------------------------------+\n"); + debugPrintf("|# | x| y|f|scl|frm|a|m|spd| ex| ey|\n"); + debugPrintf("+--+---+---+-+---+---+-+-+---+---+---+\n"); for (i = 0; i < Graphics::MAX_BOBS_NUMBER; ++i, ++bob) { if (bob->active) { - DebugPrintf("|%2d|%3d|%3d|%1d|%3d|%3d|%1d|%1d|%3d|%3d|%3d|\n", + debugPrintf("|%2d|%3d|%3d|%1d|%3d|%3d|%1d|%1d|%3d|%3d|%3d|\n", i, bob->x, bob->y, bob->xflip, bob->scale, bob->frameNum, bob->animating, bob->moving, bob->speed, bob->endx, bob->endy); } } - DebugPrintf("+--------------------------------+\n"); + debugPrintf("+--------------------------------+\n"); return true; } @@ -185,7 +185,7 @@ bool Debugger::Cmd_Room(int argc, const char **argv) { _vm->logic()->entryObj(_vm->logic()->roomData(roomNum) + 1); return false; } else { - DebugPrintf("Current room: %d (%s), use '%s <roomnum>' to switch\n", + debugPrintf("Current room: %d (%s), use '%s <roomnum>' to switch\n", _vm->logic()->currentRoom(), _vm->logic()->roomName(_vm->logic()->currentRoom()), argv[0]); @@ -197,9 +197,9 @@ bool Debugger::Cmd_Song(int argc, const char **argv) { if (argc == 2 && isNumeric(argv[1])) { int16 songNum = atoi(argv[1]); _vm->sound()->playSong(songNum); - DebugPrintf("Playing song %d\n", songNum); + debugPrintf("Playing song %d\n", songNum); } else { - DebugPrintf("Usage: %s songnum\n", argv[0]); + debugPrintf("Usage: %s songnum\n", argv[0]); } return true; } diff --git a/engines/saga/actor_walk.cpp b/engines/saga/actor_walk.cpp index a5345261c5..04741da2cd 100644 --- a/engines/saga/actor_walk.cpp +++ b/engines/saga/actor_walk.cpp @@ -1378,7 +1378,7 @@ void Actor::cmdActorWalkTo(int argc, const char **argv) { location.fromScreenPoint(movePoint); if (!validActorId(actorId)) { - _vm->_console->DebugPrintf("Actor::cmActorWalkTo Invalid actorId 0x%X.\n", actorId); + _vm->_console->debugPrintf("Actor::cmActorWalkTo Invalid actorId 0x%X.\n", actorId); return; } diff --git a/engines/saga/animation.cpp b/engines/saga/animation.cpp index 9e0bcf52ad..25119c6407 100644 --- a/engines/saga/animation.cpp +++ b/engines/saga/animation.cpp @@ -914,14 +914,14 @@ void Anim::animInfo() { animCount = getAnimationCount(); - _vm->_console->DebugPrintf("There are %d animations loaded:\n", animCount); + _vm->_console->debugPrintf("There are %d animations loaded:\n", animCount); for (i = 0; i < MAX_ANIMATIONS; i++) { if (_animations[i] == NULL) { continue; } - _vm->_console->DebugPrintf("%02d: Frames: %u Flags: %u\n", i, _animations[i]->maxFrame, _animations[i]->flags); + _vm->_console->debugPrintf("%02d: Frames: %u Flags: %u\n", i, _animations[i]->maxFrame, _animations[i]->flags); } } @@ -929,10 +929,10 @@ void Anim::animInfo() { void Anim::cutawayInfo() { uint16 i; - _vm->_console->DebugPrintf("There are %d cutaways loaded:\n", _cutawayList.size()); + _vm->_console->debugPrintf("There are %d cutaways loaded:\n", _cutawayList.size()); for (i = 0; i < _cutawayList.size(); i++) { - _vm->_console->DebugPrintf("%02d: Bg res: %u Anim res: %u Cycles: %u Framerate: %u\n", i, + _vm->_console->debugPrintf("%02d: Bg res: %u Anim res: %u Cycles: %u Framerate: %u\n", i, _cutawayList[i].backgroundResourceId, _cutawayList[i].animResourceId, _cutawayList[i].cycles, _cutawayList[i].frameRate); } diff --git a/engines/saga/console.cpp b/engines/saga/console.cpp index eab615b33f..0b801eef3e 100644 --- a/engines/saga/console.cpp +++ b/engines/saga/console.cpp @@ -35,15 +35,15 @@ namespace Saga { Console::Console(SagaEngine *vm) : GUI::Debugger() { _vm = vm; - DCmd_Register("continue", WRAP_METHOD(Console, Cmd_Exit)); + registerCmd("continue", WRAP_METHOD(Console, cmdExit)); // Actor commands - DCmd_Register("actor_walk_to", WRAP_METHOD(Console, cmdActorWalkTo)); + registerCmd("actor_walk_to", WRAP_METHOD(Console, cmdActorWalkTo)); // Animation commands - DCmd_Register("anim_info", WRAP_METHOD(Console, cmdAnimInfo)); - DCmd_Register("cutaway_info", WRAP_METHOD(Console, cmdCutawayInfo)); - DCmd_Register("play_cutaway", WRAP_METHOD(Console, cmdPlayCutaway)); + registerCmd("anim_info", WRAP_METHOD(Console, cmdAnimInfo)); + registerCmd("cutaway_info", WRAP_METHOD(Console, cmdCutawayInfo)); + registerCmd("play_cutaway", WRAP_METHOD(Console, cmdPlayCutaway)); // Game stuff @@ -60,28 +60,28 @@ Console::Console(SagaEngine *vm) : GUI::Debugger() { #endif // Scene commands - DCmd_Register("current_scene", WRAP_METHOD(Console, cmdCurrentScene)); - DCmd_Register("current_chapter", WRAP_METHOD(Console, cmdCurrentChapter)); - DCmd_Register("scene_change", WRAP_METHOD(Console, cmdSceneChange)); - DCmd_Register("chapter_change", WRAP_METHOD(Console, cmdChapterChange)); + registerCmd("current_scene", WRAP_METHOD(Console, cmdCurrentScene)); + registerCmd("current_chapter", WRAP_METHOD(Console, cmdCurrentChapter)); + registerCmd("scene_change", WRAP_METHOD(Console, cmdSceneChange)); + registerCmd("chapter_change", WRAP_METHOD(Console, cmdChapterChange)); - DCmd_Register("action_map_info", WRAP_METHOD(Console, cmdActionMapInfo)); - DCmd_Register("object_map_info", WRAP_METHOD(Console, cmdObjectMapInfo)); + registerCmd("action_map_info", WRAP_METHOD(Console, cmdActionMapInfo)); + registerCmd("object_map_info", WRAP_METHOD(Console, cmdObjectMapInfo)); // Script commands - DCmd_Register("wake_up_threads", WRAP_METHOD(Console, cmdWakeUpThreads)); + registerCmd("wake_up_threads", WRAP_METHOD(Console, cmdWakeUpThreads)); // Panel commands - DCmd_Register("current_panel_mode", WRAP_METHOD(Console, cmdCurrentPanelMode)); - DCmd_Register("set_panel_mode", WRAP_METHOD(Console, cmdSetPanelMode)); + registerCmd("current_panel_mode", WRAP_METHOD(Console, cmdCurrentPanelMode)); + registerCmd("set_panel_mode", WRAP_METHOD(Console, cmdSetPanelMode)); // Font commands - DCmd_Register("set_font_mapping", WRAP_METHOD(Console, cmdSetFontMapping)); + registerCmd("set_font_mapping", WRAP_METHOD(Console, cmdSetFontMapping)); // Global flags commands - DCmd_Register("global_flags_info", WRAP_METHOD(Console, cmdGlobalFlagsInfo)); - DCmd_Register("set_global_flag", WRAP_METHOD(Console, cmdSetGlobalFlag)); - DCmd_Register("clear_global_flag", WRAP_METHOD(Console, cmdClearGlobalFlag)); + registerCmd("global_flags_info", WRAP_METHOD(Console, cmdGlobalFlagsInfo)); + registerCmd("set_global_flag", WRAP_METHOD(Console, cmdSetGlobalFlag)); + registerCmd("clear_global_flag", WRAP_METHOD(Console, cmdClearGlobalFlag)); } Console::~Console() { @@ -89,7 +89,7 @@ Console::~Console() { bool Console::cmdActorWalkTo(int argc, const char **argv) { if (argc != 4) - DebugPrintf("Usage: %s <Actor id> <lx> <ly>\n", argv[0]); + debugPrintf("Usage: %s <Actor id> <lx> <ly>\n", argv[0]); else _vm->_actor->cmdActorWalkTo(argc, argv); return true; @@ -110,7 +110,7 @@ bool Console::cmdCutawayInfo(int argc, const char **argv) { bool Console::cmdPlayCutaway(int argc, const char **argv) { #ifdef ENABLE_IHNM if (argc != 2) - DebugPrintf("Usage: %s <Cutaway number>\n", argv[0]); + debugPrintf("Usage: %s <Cutaway number>\n", argv[0]); else _vm->_anim->playCutaway(atoi(argv[1]), false); #endif @@ -118,19 +118,19 @@ bool Console::cmdPlayCutaway(int argc, const char **argv) { } bool Console::cmdCurrentScene(int argc, const char **argv) { - DebugPrintf("Current Scene is: %i, scene resource id: %i\n", + debugPrintf("Current Scene is: %i, scene resource id: %i\n", _vm->_scene->currentSceneNumber(), _vm->_scene->currentSceneResourceId()); return true; } bool Console::cmdCurrentChapter(int argc, const char **argv) { - DebugPrintf("Current Chapter is: %i\n", _vm->_scene->currentChapterNumber()); + debugPrintf("Current Chapter is: %i\n", _vm->_scene->currentChapterNumber()); return true; } bool Console::cmdSceneChange(int argc, const char **argv) { if (argc != 2) - DebugPrintf("Usage: %s <Scene number>\n", argv[0]); + debugPrintf("Usage: %s <Scene number>\n", argv[0]); else _vm->_scene->cmdSceneChange(argc, argv); return true; @@ -138,7 +138,7 @@ bool Console::cmdSceneChange(int argc, const char **argv) { bool Console::cmdChapterChange(int argc, const char **argv) { if (argc != 3) - DebugPrintf("Usage: %s <Chapter number> <Scene number>\n", argv[0]); + debugPrintf("Usage: %s <Chapter number> <Scene number>\n", argv[0]); else { _vm->_scene->setChapterNumber(atoi(argv[2])); _vm->_scene->cmdSceneChange(argc, argv); @@ -158,9 +158,9 @@ bool Console::cmdObjectMapInfo(int argc, const char **argv) { bool Console::cmdWakeUpThreads(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Usage: %s <wait type>\n", argv[0]); - DebugPrintf("e.g.: 1 for kWaitTypeDelay, 2 for kWaitTypeSpeech, 10 for kWaitTypeWaitFrames"); - DebugPrintf("Refer to saga/script.h for additional types"); + debugPrintf("Usage: %s <wait type>\n", argv[0]); + debugPrintf("e.g.: 1 for kWaitTypeDelay, 2 for kWaitTypeSpeech, 10 for kWaitTypeWaitFrames"); + debugPrintf("Refer to saga/script.h for additional types"); } else { _vm->_script->wakeUpThreads(atoi(argv[1])); } @@ -168,13 +168,13 @@ bool Console::cmdWakeUpThreads(int argc, const char **argv) { } bool Console::cmdCurrentPanelMode(int argc, const char **argv) { - DebugPrintf("Current Panel Mode is: %i\n", _vm->_interface->getMode()); + debugPrintf("Current Panel Mode is: %i\n", _vm->_interface->getMode()); return true; } bool Console::cmdSetPanelMode(int argc, const char **argv) { if (argc != 2) - DebugPrintf("Usage: %s <Panel mode number>\n", argv[0]); + debugPrintf("Usage: %s <Panel mode number>\n", argv[0]); else _vm->_interface->setMode(atoi(argv[1])); return true; @@ -182,8 +182,8 @@ bool Console::cmdSetPanelMode(int argc, const char **argv) { bool Console::cmdSetFontMapping(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Sets font mapping\nUsage: %s <Font mapping flag>\n", argv[0]); - DebugPrintf("Mapping flags:\n0 - default game behavior\n1 - force font mapping\n2 - ignore font mapping\n"); + debugPrintf("Sets font mapping\nUsage: %s <Font mapping flag>\n", argv[0]); + debugPrintf("Mapping flags:\n0 - default game behavior\n1 - force font mapping\n2 - ignore font mapping\n"); } else { _vm->_font->setFontMapping(atoi(argv[1])); } @@ -191,7 +191,7 @@ bool Console::cmdSetFontMapping(int argc, const char **argv) { } bool Console::cmdGlobalFlagsInfo(int argc, const char **argv) { - DebugPrintf("Global flags status for IHNM:\n"); + debugPrintf("Global flags status for IHNM:\n"); // Global flags in IHNM: // 00: Tested when Gorrister's chapter ends. 0: Gorrister failed, 1: Gorrister won @@ -232,9 +232,9 @@ bool Console::cmdGlobalFlagsInfo(int argc, const char **argv) { for (i = 0; i < 32; i += 8) { for (k = i; k < i + 8; k ++) { flagStatus = _vm->_globalFlags & (1 << k) ? 1 : 0; - _vm->_console->DebugPrintf("%02d: %u |", k, flagStatus); + _vm->_console->debugPrintf("%02d: %u |", k, flagStatus); } - _vm->_console->DebugPrintf("\n"); + _vm->_console->debugPrintf("\n"); } return true; @@ -242,13 +242,13 @@ bool Console::cmdGlobalFlagsInfo(int argc, const char **argv) { bool Console::cmdSetGlobalFlag(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Usage: %s <Global flag number>\nValid flag numbers are 0 - 31\n", argv[0]); + debugPrintf("Usage: %s <Global flag number>\nValid flag numbers are 0 - 31\n", argv[0]); } else { int flagNumber = atoi(argv[1]); if (flagNumber >= 0 && flagNumber <= 31) { _vm->_globalFlags |= (1 << flagNumber); } else { - DebugPrintf("Valid flag numbers are 0 - 31\n"); + debugPrintf("Valid flag numbers are 0 - 31\n"); } } return true; @@ -256,13 +256,13 @@ bool Console::cmdSetGlobalFlag(int argc, const char **argv) { bool Console::cmdClearGlobalFlag(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Usage: %s <Global flag number>\nValid flag numbers are 0 - 31\n", argv[0]); + debugPrintf("Usage: %s <Global flag number>\nValid flag numbers are 0 - 31\n", argv[0]); } else { int flagNumber = atoi(argv[1]); if (flagNumber >= 0 && flagNumber <= 31) { _vm->_globalFlags &= ~(1 << flagNumber); } else { - DebugPrintf("Valid flag numbers are 0 - 31\n"); + debugPrintf("Valid flag numbers are 0 - 31\n"); } } return true; diff --git a/engines/saga/objectmap.cpp b/engines/saga/objectmap.cpp index f27c888a61..ad5167209c 100644 --- a/engines/saga/objectmap.cpp +++ b/engines/saga/objectmap.cpp @@ -231,7 +231,7 @@ int ObjectMap::hitTest(const Point& testPoint) { } void ObjectMap::cmdInfo() { - _vm->_console->DebugPrintf("%d zone(s) loaded.\n\n", _hitZoneList.size()); + _vm->_console->debugPrintf("%d zone(s) loaded.\n\n", _hitZoneList.size()); } } // End of namespace Saga diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp index 7f77cbab38..04776bd5dc 100644 --- a/engines/saga/scene.cpp +++ b/engines/saga/scene.cpp @@ -1220,7 +1220,7 @@ void Scene::cmdSceneChange(int argc, const char **argv) { scene_num = atoi(argv[1]); if ((scene_num < 1) || (uint(scene_num) >= _sceneLUT.size())) { - _vm->_console->DebugPrintf("Invalid scene number.\n"); + _vm->_console->debugPrintf("Invalid scene number.\n"); return; } diff --git a/engines/saga/sfuncs.cpp b/engines/saga/sfuncs.cpp index 91e39c54b6..cb963e23ac 100644 --- a/engines/saga/sfuncs.cpp +++ b/engines/saga/sfuncs.cpp @@ -139,7 +139,7 @@ void Script::setupITEScriptFuncList() { void Script::sfPutString(SCRIPTFUNC_PARAMS) { const char *str = thread->_strings->getString(thread->pop()); - _vm->_console->DebugPrintf("sfPutString: %s\n",str); + _vm->_console->debugPrintf("sfPutString: %s\n",str); debug(0, "sfPutString: %s", str); } diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 1bc0dd067c..1c4228eb7d 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -79,148 +79,151 @@ Console::Console(SciEngine *engine) : GUI::Debugger(), assert(_engine->_gamestate); // Variables - DVar_Register("sleeptime_factor", &g_debug_sleeptime_factor, DVAR_INT, 0); - DVar_Register("gc_interval", &engine->_gamestate->scriptGCInterval, DVAR_INT, 0); - DVar_Register("simulated_key", &g_debug_simulated_key, DVAR_INT, 0); - DVar_Register("track_mouse_clicks", &g_debug_track_mouse_clicks, DVAR_BOOL, 0); - DVar_Register("script_abort_flag", &_engine->_gamestate->abortScriptProcessing, DVAR_INT, 0); + registerVar("sleeptime_factor", &g_debug_sleeptime_factor); + registerVar("gc_interval", &engine->_gamestate->scriptGCInterval); + registerVar("simulated_key", &g_debug_simulated_key); + registerVar("track_mouse_clicks", &g_debug_track_mouse_clicks); + // FIXME: This actually passes an enum type instead of an integer but no + // precaution is taken to assure that all assigned values are in the range + // of the enum type. We should handle this more carefully... + registerVar("script_abort_flag", (int *)&_engine->_gamestate->abortScriptProcessing); // General - DCmd_Register("help", WRAP_METHOD(Console, cmdHelp)); + registerCmd("help", WRAP_METHOD(Console, cmdHelp)); // Kernel -// DCmd_Register("classes", WRAP_METHOD(Console, cmdClasses)); // TODO - DCmd_Register("opcodes", WRAP_METHOD(Console, cmdOpcodes)); - DCmd_Register("selector", WRAP_METHOD(Console, cmdSelector)); - DCmd_Register("selectors", WRAP_METHOD(Console, cmdSelectors)); - DCmd_Register("functions", WRAP_METHOD(Console, cmdKernelFunctions)); - DCmd_Register("class_table", WRAP_METHOD(Console, cmdClassTable)); +// registerCmd("classes", WRAP_METHOD(Console, cmdClasses)); // TODO + registerCmd("opcodes", WRAP_METHOD(Console, cmdOpcodes)); + registerCmd("selector", WRAP_METHOD(Console, cmdSelector)); + registerCmd("selectors", WRAP_METHOD(Console, cmdSelectors)); + registerCmd("functions", WRAP_METHOD(Console, cmdKernelFunctions)); + registerCmd("class_table", WRAP_METHOD(Console, cmdClassTable)); // Parser - DCmd_Register("suffixes", WRAP_METHOD(Console, cmdSuffixes)); - DCmd_Register("parse_grammar", WRAP_METHOD(Console, cmdParseGrammar)); - DCmd_Register("parser_nodes", WRAP_METHOD(Console, cmdParserNodes)); - DCmd_Register("parser_words", WRAP_METHOD(Console, cmdParserWords)); - DCmd_Register("sentence_fragments", WRAP_METHOD(Console, cmdSentenceFragments)); - DCmd_Register("parse", WRAP_METHOD(Console, cmdParse)); - DCmd_Register("set_parse_nodes", WRAP_METHOD(Console, cmdSetParseNodes)); - DCmd_Register("said", WRAP_METHOD(Console, cmdSaid)); + registerCmd("suffixes", WRAP_METHOD(Console, cmdSuffixes)); + registerCmd("parse_grammar", WRAP_METHOD(Console, cmdParseGrammar)); + registerCmd("parser_nodes", WRAP_METHOD(Console, cmdParserNodes)); + registerCmd("parser_words", WRAP_METHOD(Console, cmdParserWords)); + registerCmd("sentence_fragments", WRAP_METHOD(Console, cmdSentenceFragments)); + registerCmd("parse", WRAP_METHOD(Console, cmdParse)); + registerCmd("set_parse_nodes", WRAP_METHOD(Console, cmdSetParseNodes)); + registerCmd("said", WRAP_METHOD(Console, cmdSaid)); // Resources - DCmd_Register("diskdump", WRAP_METHOD(Console, cmdDiskDump)); - DCmd_Register("hexdump", WRAP_METHOD(Console, cmdHexDump)); - DCmd_Register("resource_id", WRAP_METHOD(Console, cmdResourceId)); - DCmd_Register("resource_info", WRAP_METHOD(Console, cmdResourceInfo)); - DCmd_Register("resource_types", WRAP_METHOD(Console, cmdResourceTypes)); - DCmd_Register("list", WRAP_METHOD(Console, cmdList)); - DCmd_Register("hexgrep", WRAP_METHOD(Console, cmdHexgrep)); - DCmd_Register("verify_scripts", WRAP_METHOD(Console, cmdVerifyScripts)); + registerCmd("diskdump", WRAP_METHOD(Console, cmdDiskDump)); + registerCmd("hexdump", WRAP_METHOD(Console, cmdHexDump)); + registerCmd("resource_id", WRAP_METHOD(Console, cmdResourceId)); + registerCmd("resource_info", WRAP_METHOD(Console, cmdResourceInfo)); + registerCmd("resource_types", WRAP_METHOD(Console, cmdResourceTypes)); + registerCmd("list", WRAP_METHOD(Console, cmdList)); + registerCmd("hexgrep", WRAP_METHOD(Console, cmdHexgrep)); + registerCmd("verify_scripts", WRAP_METHOD(Console, cmdVerifyScripts)); // Game - DCmd_Register("save_game", WRAP_METHOD(Console, cmdSaveGame)); - DCmd_Register("restore_game", WRAP_METHOD(Console, cmdRestoreGame)); - DCmd_Register("restart_game", WRAP_METHOD(Console, cmdRestartGame)); - DCmd_Register("version", WRAP_METHOD(Console, cmdGetVersion)); - DCmd_Register("room", WRAP_METHOD(Console, cmdRoomNumber)); - DCmd_Register("quit", WRAP_METHOD(Console, cmdQuit)); - DCmd_Register("list_saves", WRAP_METHOD(Console, cmdListSaves)); + registerCmd("save_game", WRAP_METHOD(Console, cmdSaveGame)); + registerCmd("restore_game", WRAP_METHOD(Console, cmdRestoreGame)); + registerCmd("restart_game", WRAP_METHOD(Console, cmdRestartGame)); + registerCmd("version", WRAP_METHOD(Console, cmdGetVersion)); + registerCmd("room", WRAP_METHOD(Console, cmdRoomNumber)); + registerCmd("quit", WRAP_METHOD(Console, cmdQuit)); + registerCmd("list_saves", WRAP_METHOD(Console, cmdListSaves)); // Graphics - DCmd_Register("show_map", WRAP_METHOD(Console, cmdShowMap)); - DCmd_Register("set_palette", WRAP_METHOD(Console, cmdSetPalette)); - DCmd_Register("draw_pic", WRAP_METHOD(Console, cmdDrawPic)); - DCmd_Register("draw_cel", WRAP_METHOD(Console, cmdDrawCel)); - DCmd_Register("undither", WRAP_METHOD(Console, cmdUndither)); - DCmd_Register("pic_visualize", WRAP_METHOD(Console, cmdPicVisualize)); - DCmd_Register("play_video", WRAP_METHOD(Console, cmdPlayVideo)); - DCmd_Register("animate_list", WRAP_METHOD(Console, cmdAnimateList)); - DCmd_Register("al", WRAP_METHOD(Console, cmdAnimateList)); // alias - DCmd_Register("window_list", WRAP_METHOD(Console, cmdWindowList)); - DCmd_Register("wl", WRAP_METHOD(Console, cmdWindowList)); // alias - DCmd_Register("plane_list", WRAP_METHOD(Console, cmdPlaneList)); - DCmd_Register("pl", WRAP_METHOD(Console, cmdPlaneList)); // alias - DCmd_Register("plane_items", WRAP_METHOD(Console, cmdPlaneItemList)); - DCmd_Register("pi", WRAP_METHOD(Console, cmdPlaneItemList)); // alias - DCmd_Register("saved_bits", WRAP_METHOD(Console, cmdSavedBits)); - DCmd_Register("show_saved_bits", WRAP_METHOD(Console, cmdShowSavedBits)); + registerCmd("show_map", WRAP_METHOD(Console, cmdShowMap)); + registerCmd("set_palette", WRAP_METHOD(Console, cmdSetPalette)); + registerCmd("draw_pic", WRAP_METHOD(Console, cmdDrawPic)); + registerCmd("draw_cel", WRAP_METHOD(Console, cmdDrawCel)); + registerCmd("undither", WRAP_METHOD(Console, cmdUndither)); + registerCmd("pic_visualize", WRAP_METHOD(Console, cmdPicVisualize)); + registerCmd("play_video", WRAP_METHOD(Console, cmdPlayVideo)); + registerCmd("animate_list", WRAP_METHOD(Console, cmdAnimateList)); + registerCmd("al", WRAP_METHOD(Console, cmdAnimateList)); // alias + registerCmd("window_list", WRAP_METHOD(Console, cmdWindowList)); + registerCmd("wl", WRAP_METHOD(Console, cmdWindowList)); // alias + registerCmd("plane_list", WRAP_METHOD(Console, cmdPlaneList)); + registerCmd("pl", WRAP_METHOD(Console, cmdPlaneList)); // alias + registerCmd("plane_items", WRAP_METHOD(Console, cmdPlaneItemList)); + registerCmd("pi", WRAP_METHOD(Console, cmdPlaneItemList)); // alias + registerCmd("saved_bits", WRAP_METHOD(Console, cmdSavedBits)); + registerCmd("show_saved_bits", WRAP_METHOD(Console, cmdShowSavedBits)); // Segments - DCmd_Register("segment_table", WRAP_METHOD(Console, cmdPrintSegmentTable)); - DCmd_Register("segtable", WRAP_METHOD(Console, cmdPrintSegmentTable)); // alias - DCmd_Register("segment_info", WRAP_METHOD(Console, cmdSegmentInfo)); - DCmd_Register("seginfo", WRAP_METHOD(Console, cmdSegmentInfo)); // alias - DCmd_Register("segment_kill", WRAP_METHOD(Console, cmdKillSegment)); - DCmd_Register("segkill", WRAP_METHOD(Console, cmdKillSegment)); // alias + registerCmd("segment_table", WRAP_METHOD(Console, cmdPrintSegmentTable)); + registerCmd("segtable", WRAP_METHOD(Console, cmdPrintSegmentTable)); // alias + registerCmd("segment_info", WRAP_METHOD(Console, cmdSegmentInfo)); + registerCmd("seginfo", WRAP_METHOD(Console, cmdSegmentInfo)); // alias + registerCmd("segment_kill", WRAP_METHOD(Console, cmdKillSegment)); + registerCmd("segkill", WRAP_METHOD(Console, cmdKillSegment)); // alias // Garbage collection - DCmd_Register("gc", WRAP_METHOD(Console, cmdGCInvoke)); - DCmd_Register("gc_objects", WRAP_METHOD(Console, cmdGCObjects)); - DCmd_Register("gc_reachable", WRAP_METHOD(Console, cmdGCShowReachable)); - DCmd_Register("gc_freeable", WRAP_METHOD(Console, cmdGCShowFreeable)); - DCmd_Register("gc_normalize", WRAP_METHOD(Console, cmdGCNormalize)); + registerCmd("gc", WRAP_METHOD(Console, cmdGCInvoke)); + registerCmd("gc_objects", WRAP_METHOD(Console, cmdGCObjects)); + registerCmd("gc_reachable", WRAP_METHOD(Console, cmdGCShowReachable)); + registerCmd("gc_freeable", WRAP_METHOD(Console, cmdGCShowFreeable)); + registerCmd("gc_normalize", WRAP_METHOD(Console, cmdGCNormalize)); // Music/SFX - DCmd_Register("songlib", WRAP_METHOD(Console, cmdSongLib)); - DCmd_Register("songinfo", WRAP_METHOD(Console, cmdSongInfo)); - DCmd_Register("is_sample", WRAP_METHOD(Console, cmdIsSample)); - DCmd_Register("startsound", WRAP_METHOD(Console, cmdStartSound)); - DCmd_Register("togglesound", WRAP_METHOD(Console, cmdToggleSound)); - DCmd_Register("stopallsounds", WRAP_METHOD(Console, cmdStopAllSounds)); - DCmd_Register("sfx01_header", WRAP_METHOD(Console, cmdSfx01Header)); - DCmd_Register("sfx01_track", WRAP_METHOD(Console, cmdSfx01Track)); - DCmd_Register("show_instruments", WRAP_METHOD(Console, cmdShowInstruments)); - DCmd_Register("map_instrument", WRAP_METHOD(Console, cmdMapInstrument)); + registerCmd("songlib", WRAP_METHOD(Console, cmdSongLib)); + registerCmd("songinfo", WRAP_METHOD(Console, cmdSongInfo)); + registerCmd("is_sample", WRAP_METHOD(Console, cmdIsSample)); + registerCmd("startsound", WRAP_METHOD(Console, cmdStartSound)); + registerCmd("togglesound", WRAP_METHOD(Console, cmdToggleSound)); + registerCmd("stopallsounds", WRAP_METHOD(Console, cmdStopAllSounds)); + registerCmd("sfx01_header", WRAP_METHOD(Console, cmdSfx01Header)); + registerCmd("sfx01_track", WRAP_METHOD(Console, cmdSfx01Track)); + registerCmd("show_instruments", WRAP_METHOD(Console, cmdShowInstruments)); + registerCmd("map_instrument", WRAP_METHOD(Console, cmdMapInstrument)); // Script - DCmd_Register("addresses", WRAP_METHOD(Console, cmdAddresses)); - DCmd_Register("registers", WRAP_METHOD(Console, cmdRegisters)); - DCmd_Register("dissect_script", WRAP_METHOD(Console, cmdDissectScript)); - DCmd_Register("backtrace", WRAP_METHOD(Console, cmdBacktrace)); - DCmd_Register("bt", WRAP_METHOD(Console, cmdBacktrace)); // alias - DCmd_Register("trace", WRAP_METHOD(Console, cmdTrace)); - DCmd_Register("t", WRAP_METHOD(Console, cmdTrace)); // alias - DCmd_Register("s", WRAP_METHOD(Console, cmdTrace)); // alias - DCmd_Register("stepover", WRAP_METHOD(Console, cmdStepOver)); - DCmd_Register("p", WRAP_METHOD(Console, cmdStepOver)); // alias - DCmd_Register("step_ret", WRAP_METHOD(Console, cmdStepRet)); - DCmd_Register("pret", WRAP_METHOD(Console, cmdStepRet)); // alias - DCmd_Register("step_event", WRAP_METHOD(Console, cmdStepEvent)); - DCmd_Register("se", WRAP_METHOD(Console, cmdStepEvent)); // alias - DCmd_Register("step_global", WRAP_METHOD(Console, cmdStepGlobal)); - DCmd_Register("sg", WRAP_METHOD(Console, cmdStepGlobal)); // alias - DCmd_Register("step_callk", WRAP_METHOD(Console, cmdStepCallk)); - DCmd_Register("snk", WRAP_METHOD(Console, cmdStepCallk)); // alias - DCmd_Register("disasm", WRAP_METHOD(Console, cmdDisassemble)); - DCmd_Register("disasm_addr", WRAP_METHOD(Console, cmdDisassembleAddress)); - DCmd_Register("find_callk", WRAP_METHOD(Console, cmdFindKernelFunctionCall)); - DCmd_Register("send", WRAP_METHOD(Console, cmdSend)); - DCmd_Register("go", WRAP_METHOD(Console, cmdGo)); - DCmd_Register("logkernel", WRAP_METHOD(Console, cmdLogKernel)); + registerCmd("addresses", WRAP_METHOD(Console, cmdAddresses)); + registerCmd("registers", WRAP_METHOD(Console, cmdRegisters)); + registerCmd("dissect_script", WRAP_METHOD(Console, cmdDissectScript)); + registerCmd("backtrace", WRAP_METHOD(Console, cmdBacktrace)); + registerCmd("bt", WRAP_METHOD(Console, cmdBacktrace)); // alias + registerCmd("trace", WRAP_METHOD(Console, cmdTrace)); + registerCmd("t", WRAP_METHOD(Console, cmdTrace)); // alias + registerCmd("s", WRAP_METHOD(Console, cmdTrace)); // alias + registerCmd("stepover", WRAP_METHOD(Console, cmdStepOver)); + registerCmd("p", WRAP_METHOD(Console, cmdStepOver)); // alias + registerCmd("step_ret", WRAP_METHOD(Console, cmdStepRet)); + registerCmd("pret", WRAP_METHOD(Console, cmdStepRet)); // alias + registerCmd("step_event", WRAP_METHOD(Console, cmdStepEvent)); + registerCmd("se", WRAP_METHOD(Console, cmdStepEvent)); // alias + registerCmd("step_global", WRAP_METHOD(Console, cmdStepGlobal)); + registerCmd("sg", WRAP_METHOD(Console, cmdStepGlobal)); // alias + registerCmd("step_callk", WRAP_METHOD(Console, cmdStepCallk)); + registerCmd("snk", WRAP_METHOD(Console, cmdStepCallk)); // alias + registerCmd("disasm", WRAP_METHOD(Console, cmdDisassemble)); + registerCmd("disasm_addr", WRAP_METHOD(Console, cmdDisassembleAddress)); + registerCmd("find_callk", WRAP_METHOD(Console, cmdFindKernelFunctionCall)); + registerCmd("send", WRAP_METHOD(Console, cmdSend)); + registerCmd("go", WRAP_METHOD(Console, cmdGo)); + registerCmd("logkernel", WRAP_METHOD(Console, cmdLogKernel)); // Breakpoints - DCmd_Register("bp_list", WRAP_METHOD(Console, cmdBreakpointList)); - DCmd_Register("bplist", WRAP_METHOD(Console, cmdBreakpointList)); // alias - DCmd_Register("bl", WRAP_METHOD(Console, cmdBreakpointList)); // alias - DCmd_Register("bp_del", WRAP_METHOD(Console, cmdBreakpointDelete)); - DCmd_Register("bpdel", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias - DCmd_Register("bc", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias - DCmd_Register("bp_method", WRAP_METHOD(Console, cmdBreakpointMethod)); - DCmd_Register("bpx", WRAP_METHOD(Console, cmdBreakpointMethod)); // alias - DCmd_Register("bp_read", WRAP_METHOD(Console, cmdBreakpointRead)); - DCmd_Register("bpr", WRAP_METHOD(Console, cmdBreakpointRead)); // alias - DCmd_Register("bp_write", WRAP_METHOD(Console, cmdBreakpointWrite)); - DCmd_Register("bpw", WRAP_METHOD(Console, cmdBreakpointWrite)); // alias - DCmd_Register("bp_kernel", WRAP_METHOD(Console, cmdBreakpointKernel)); - DCmd_Register("bpk", WRAP_METHOD(Console, cmdBreakpointKernel)); // alias - DCmd_Register("bp_function", WRAP_METHOD(Console, cmdBreakpointFunction)); - DCmd_Register("bpe", WRAP_METHOD(Console, cmdBreakpointFunction)); // alias + registerCmd("bp_list", WRAP_METHOD(Console, cmdBreakpointList)); + registerCmd("bplist", WRAP_METHOD(Console, cmdBreakpointList)); // alias + registerCmd("bl", WRAP_METHOD(Console, cmdBreakpointList)); // alias + registerCmd("bp_del", WRAP_METHOD(Console, cmdBreakpointDelete)); + registerCmd("bpdel", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias + registerCmd("bc", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias + registerCmd("bp_method", WRAP_METHOD(Console, cmdBreakpointMethod)); + registerCmd("bpx", WRAP_METHOD(Console, cmdBreakpointMethod)); // alias + registerCmd("bp_read", WRAP_METHOD(Console, cmdBreakpointRead)); + registerCmd("bpr", WRAP_METHOD(Console, cmdBreakpointRead)); // alias + registerCmd("bp_write", WRAP_METHOD(Console, cmdBreakpointWrite)); + registerCmd("bpw", WRAP_METHOD(Console, cmdBreakpointWrite)); // alias + registerCmd("bp_kernel", WRAP_METHOD(Console, cmdBreakpointKernel)); + registerCmd("bpk", WRAP_METHOD(Console, cmdBreakpointKernel)); // alias + registerCmd("bp_function", WRAP_METHOD(Console, cmdBreakpointFunction)); + registerCmd("bpe", WRAP_METHOD(Console, cmdBreakpointFunction)); // alias // VM - DCmd_Register("script_steps", WRAP_METHOD(Console, cmdScriptSteps)); - DCmd_Register("vm_varlist", WRAP_METHOD(Console, cmdVMVarlist)); - DCmd_Register("vmvarlist", WRAP_METHOD(Console, cmdVMVarlist)); // alias - DCmd_Register("vl", WRAP_METHOD(Console, cmdVMVarlist)); // alias - DCmd_Register("vm_vars", WRAP_METHOD(Console, cmdVMVars)); - DCmd_Register("vmvars", WRAP_METHOD(Console, cmdVMVars)); // alias - DCmd_Register("vv", WRAP_METHOD(Console, cmdVMVars)); // alias - DCmd_Register("stack", WRAP_METHOD(Console, cmdStack)); - DCmd_Register("value_type", WRAP_METHOD(Console, cmdValueType)); - DCmd_Register("view_listnode", WRAP_METHOD(Console, cmdViewListNode)); - DCmd_Register("view_reference", WRAP_METHOD(Console, cmdViewReference)); - DCmd_Register("vr", WRAP_METHOD(Console, cmdViewReference)); // alias - DCmd_Register("view_object", WRAP_METHOD(Console, cmdViewObject)); - DCmd_Register("vo", WRAP_METHOD(Console, cmdViewObject)); // alias - DCmd_Register("active_object", WRAP_METHOD(Console, cmdViewActiveObject)); - DCmd_Register("acc_object", WRAP_METHOD(Console, cmdViewAccumulatorObject)); + registerCmd("script_steps", WRAP_METHOD(Console, cmdScriptSteps)); + registerCmd("vm_varlist", WRAP_METHOD(Console, cmdVMVarlist)); + registerCmd("vmvarlist", WRAP_METHOD(Console, cmdVMVarlist)); // alias + registerCmd("vl", WRAP_METHOD(Console, cmdVMVarlist)); // alias + registerCmd("vm_vars", WRAP_METHOD(Console, cmdVMVars)); + registerCmd("vmvars", WRAP_METHOD(Console, cmdVMVars)); // alias + registerCmd("vv", WRAP_METHOD(Console, cmdVMVars)); // alias + registerCmd("stack", WRAP_METHOD(Console, cmdStack)); + registerCmd("value_type", WRAP_METHOD(Console, cmdValueType)); + registerCmd("view_listnode", WRAP_METHOD(Console, cmdViewListNode)); + registerCmd("view_reference", WRAP_METHOD(Console, cmdViewReference)); + registerCmd("vr", WRAP_METHOD(Console, cmdViewReference)); // alias + registerCmd("view_object", WRAP_METHOD(Console, cmdViewObject)); + registerCmd("vo", WRAP_METHOD(Console, cmdViewObject)); // alias + registerCmd("active_object", WRAP_METHOD(Console, cmdViewActiveObject)); + registerCmd("acc_object", WRAP_METHOD(Console, cmdViewAccumulatorObject)); _debugState.seeking = kDebugSeekNothing; _debugState.seekLevel = 0; @@ -307,137 +310,137 @@ void Console::postEnter() { } bool Console::cmdHelp(int argc, const char **argv) { - DebugPrintf("\n"); - DebugPrintf("Variables\n"); - DebugPrintf("---------\n"); - DebugPrintf("sleeptime_factor: Factor to multiply with wait times in kWait()\n"); - DebugPrintf("gc_interval: Number of kernel calls in between garbage collections\n"); - DebugPrintf("simulated_key: Add a key with the specified scan code to the event list\n"); - DebugPrintf("track_mouse_clicks: Toggles mouse click tracking to the console\n"); - DebugPrintf("weak_validations: Turns some validation errors into warnings\n"); - DebugPrintf("script_abort_flag: Set to 1 to abort script execution. Set to 2 to force a replay afterwards\n"); - DebugPrintf("\n"); - DebugPrintf("Debug flags\n"); - DebugPrintf("-----------\n"); - DebugPrintf("debugflag_list - Lists the available debug flags and their status\n"); - DebugPrintf("debugflag_enable - Enables a debug flag\n"); - DebugPrintf("debugflag_disable - Disables a debug flag\n"); - DebugPrintf("\n"); - DebugPrintf("Commands\n"); - DebugPrintf("--------\n"); - DebugPrintf("Kernel:\n"); - DebugPrintf(" opcodes - Lists the opcode names\n"); - DebugPrintf(" selectors - Lists the selector names\n"); - DebugPrintf(" selector - Attempts to find the requested selector by name\n"); - DebugPrintf(" functions - Lists the kernel functions\n"); - DebugPrintf(" class_table - Shows the available classes\n"); - DebugPrintf("\n"); - DebugPrintf("Parser:\n"); - DebugPrintf(" suffixes - Lists the vocabulary suffixes\n"); - DebugPrintf(" parse_grammar - Shows the parse grammar, in strict GNF\n"); - DebugPrintf(" parser_nodes - Shows the specified number of nodes from the parse node tree\n"); - DebugPrintf(" parser_words - Shows the words from the parse node tree\n"); - DebugPrintf(" sentence_fragments - Shows the sentence fragments (used to build Parse trees)\n"); - DebugPrintf(" parse - Parses a sequence of words and prints the resulting parse tree\n"); - DebugPrintf(" set_parse_nodes - Sets the contents of all parse nodes\n"); - DebugPrintf(" said - Match a string against a said spec\n"); - DebugPrintf("\n"); - DebugPrintf("Resources:\n"); - DebugPrintf(" diskdump - Dumps the specified resource to disk as a patch file\n"); - DebugPrintf(" hexdump - Dumps the specified resource to standard output\n"); - DebugPrintf(" resource_id - Identifies a resource number by splitting it up in resource type and resource number\n"); - DebugPrintf(" resource_info - Shows info about a resource\n"); - DebugPrintf(" resource_types - Shows the valid resource types\n"); - DebugPrintf(" list - Lists all the resources of a given type\n"); - DebugPrintf(" hexgrep - Searches some resources for a particular sequence of bytes, represented as hexadecimal numbers\n"); - DebugPrintf(" verify_scripts - Performs sanity checks on SCI1.1-SCI2.1 game scripts (e.g. if they're up to 64KB in total)\n"); - DebugPrintf("\n"); - DebugPrintf("Game:\n"); - DebugPrintf(" save_game - Saves the current game state to the hard disk\n"); - DebugPrintf(" restore_game - Restores a saved game from the hard disk\n"); - DebugPrintf(" list_saves - List all saved games including filenames\n"); - DebugPrintf(" restart_game - Restarts the game\n"); - DebugPrintf(" version - Shows the resource and interpreter versions\n"); - DebugPrintf(" room - Gets or sets the current room number\n"); - DebugPrintf(" quit - Quits the game\n"); - DebugPrintf("\n"); - DebugPrintf("Graphics:\n"); - DebugPrintf(" show_map - Switches to visual, priority, control or display screen\n"); - DebugPrintf(" set_palette - Sets a palette resource\n"); - DebugPrintf(" draw_pic - Draws a pic resource\n"); - DebugPrintf(" draw_cel - Draws a cel from a view resource\n"); - DebugPrintf(" pic_visualize - Enables visualization of the drawing process of EGA pictures\n"); - DebugPrintf(" undither - Enable/disable undithering\n"); - DebugPrintf(" play_video - Plays a SEQ, AVI, VMD, RBT or DUK video\n"); - DebugPrintf(" animate_list / al - Shows the current list of objects in kAnimate's draw list (SCI0 - SCI1.1)\n"); - DebugPrintf(" window_list / wl - Shows a list of all the windows (ports) in the draw list (SCI0 - SCI1.1)\n"); - DebugPrintf(" plane_list / pl - Shows a list of all the planes in the draw list (SCI2+)\n"); - DebugPrintf(" plane_items / pi - Shows a list of all items for a plane (SCI2+)\n"); - DebugPrintf(" saved_bits - List saved bits on the hunk\n"); - DebugPrintf(" show_saved_bits - Display saved bits\n"); - DebugPrintf("\n"); - DebugPrintf("Segments:\n"); - DebugPrintf(" segment_table / segtable - Lists all segments\n"); - DebugPrintf(" segment_info / seginfo - Provides information on the specified segment\n"); - DebugPrintf(" segment_kill / segkill - Deletes the specified segment\n"); - DebugPrintf("\n"); - DebugPrintf("Garbage collection:\n"); - DebugPrintf(" gc - Invokes the garbage collector\n"); - DebugPrintf(" gc_objects - Lists all reachable objects, normalized\n"); - DebugPrintf(" gc_reachable - Lists all addresses directly reachable from a given memory object\n"); - DebugPrintf(" gc_freeable - Lists all addresses freeable in a given segment\n"); - DebugPrintf(" gc_normalize - Prints the \"normal\" address of a given address\n"); - DebugPrintf("\n"); - DebugPrintf("Music/SFX:\n"); - DebugPrintf(" songlib - Shows the song library\n"); - DebugPrintf(" songinfo - Shows information about a specified song in the song library\n"); - DebugPrintf(" togglesound - Starts/stops a sound in the song library\n"); - DebugPrintf(" stopallsounds - Stops all sounds in the playlist\n"); - DebugPrintf(" startsound - Starts the specified sound resource, replacing the first song in the song library\n"); - DebugPrintf(" is_sample - Shows information on a given sound resource, if it's a PCM sample\n"); - DebugPrintf(" sfx01_header - Dumps the header of a SCI01 song\n"); - DebugPrintf(" sfx01_track - Dumps a track of a SCI01 song\n"); - DebugPrintf(" show_instruments - Shows the instruments of a specific song, or all songs\n"); - DebugPrintf(" map_instrument - Dynamically maps an MT-32 instrument to a GM instrument\n"); - DebugPrintf("\n"); - DebugPrintf("Script:\n"); - DebugPrintf(" addresses - Provides information on how to pass addresses\n"); - DebugPrintf(" registers - Shows the current register values\n"); - DebugPrintf(" dissect_script - Examines a script\n"); - DebugPrintf(" backtrace / bt - Dumps the send/self/super/call/calle/callb stack\n"); - DebugPrintf(" trace / t / s - Executes one operation (no parameters) or several operations (specified as a parameter) \n"); - DebugPrintf(" stepover / p - Executes one operation, skips over call/send\n"); - DebugPrintf(" step_ret / pret - Steps forward until ret is called on the current execution stack level.\n"); - DebugPrintf(" step_event / se - Steps forward until a SCI event is received.\n"); - DebugPrintf(" step_global / sg - Steps until the global variable with the specified index is modified.\n"); - DebugPrintf(" step_callk / snk - Steps forward until it hits the next callk operation, or a specific callk (specified as a parameter)\n"); - DebugPrintf(" disasm - Disassembles a method by name\n"); - DebugPrintf(" disasm_addr - Disassembles one or more commands\n"); - DebugPrintf(" send - Sends a message to an object\n"); - DebugPrintf(" go - Executes the script\n"); - DebugPrintf(" logkernel - Logs kernel calls\n"); - DebugPrintf("\n"); - DebugPrintf("Breakpoints:\n"); - DebugPrintf(" bp_list / bplist / bl - Lists the current breakpoints\n"); - DebugPrintf(" bp_del / bpdel / bc - Deletes a breakpoint with the specified index\n"); - DebugPrintf(" bp_method / bpx - Sets a breakpoint on the execution of a specified method/selector\n"); - DebugPrintf(" bp_read / bpr - Sets a breakpoint on reading of a specified selector\n"); - DebugPrintf(" bp_write / bpw - Sets a breakpoint on writing to a specified selector\n"); - DebugPrintf(" bp_kernel / bpk - Sets a breakpoint on execution of a kernel function\n"); - DebugPrintf(" bp_function / bpe - Sets a breakpoint on the execution of the specified exported function\n"); - DebugPrintf("\n"); - DebugPrintf("VM:\n"); - DebugPrintf(" script_steps - Shows the number of executed SCI operations\n"); - DebugPrintf(" vm_varlist / vmvarlist / vl - Shows the addresses of variables in the VM\n"); - DebugPrintf(" vm_vars / vmvars / vv - Displays or changes variables in the VM\n"); - DebugPrintf(" stack - Lists the specified number of stack elements\n"); - DebugPrintf(" value_type - Determines the type of a value\n"); - DebugPrintf(" view_listnode - Examines the list node at the given address\n"); - DebugPrintf(" view_reference / vr - Examines an arbitrary reference\n"); - DebugPrintf(" view_object / vo - Examines the object at the given address\n"); - DebugPrintf(" active_object - Shows information on the currently active object or class\n"); - DebugPrintf(" acc_object - Shows information on the object or class at the address indexed by the accumulator\n"); - DebugPrintf("\n"); + debugPrintf("\n"); + debugPrintf("Variables\n"); + debugPrintf("---------\n"); + debugPrintf("sleeptime_factor: Factor to multiply with wait times in kWait()\n"); + debugPrintf("gc_interval: Number of kernel calls in between garbage collections\n"); + debugPrintf("simulated_key: Add a key with the specified scan code to the event list\n"); + debugPrintf("track_mouse_clicks: Toggles mouse click tracking to the console\n"); + debugPrintf("weak_validations: Turns some validation errors into warnings\n"); + debugPrintf("script_abort_flag: Set to 1 to abort script execution. Set to 2 to force a replay afterwards\n"); + debugPrintf("\n"); + debugPrintf("Debug flags\n"); + debugPrintf("-----------\n"); + debugPrintf("debugflag_list - Lists the available debug flags and their status\n"); + debugPrintf("debugflag_enable - Enables a debug flag\n"); + debugPrintf("debugflag_disable - Disables a debug flag\n"); + debugPrintf("\n"); + debugPrintf("Commands\n"); + debugPrintf("--------\n"); + debugPrintf("Kernel:\n"); + debugPrintf(" opcodes - Lists the opcode names\n"); + debugPrintf(" selectors - Lists the selector names\n"); + debugPrintf(" selector - Attempts to find the requested selector by name\n"); + debugPrintf(" functions - Lists the kernel functions\n"); + debugPrintf(" class_table - Shows the available classes\n"); + debugPrintf("\n"); + debugPrintf("Parser:\n"); + debugPrintf(" suffixes - Lists the vocabulary suffixes\n"); + debugPrintf(" parse_grammar - Shows the parse grammar, in strict GNF\n"); + debugPrintf(" parser_nodes - Shows the specified number of nodes from the parse node tree\n"); + debugPrintf(" parser_words - Shows the words from the parse node tree\n"); + debugPrintf(" sentence_fragments - Shows the sentence fragments (used to build Parse trees)\n"); + debugPrintf(" parse - Parses a sequence of words and prints the resulting parse tree\n"); + debugPrintf(" set_parse_nodes - Sets the contents of all parse nodes\n"); + debugPrintf(" said - Match a string against a said spec\n"); + debugPrintf("\n"); + debugPrintf("Resources:\n"); + debugPrintf(" diskdump - Dumps the specified resource to disk as a patch file\n"); + debugPrintf(" hexdump - Dumps the specified resource to standard output\n"); + debugPrintf(" resource_id - Identifies a resource number by splitting it up in resource type and resource number\n"); + debugPrintf(" resource_info - Shows info about a resource\n"); + debugPrintf(" resource_types - Shows the valid resource types\n"); + debugPrintf(" list - Lists all the resources of a given type\n"); + debugPrintf(" hexgrep - Searches some resources for a particular sequence of bytes, represented as hexadecimal numbers\n"); + debugPrintf(" verify_scripts - Performs sanity checks on SCI1.1-SCI2.1 game scripts (e.g. if they're up to 64KB in total)\n"); + debugPrintf("\n"); + debugPrintf("Game:\n"); + debugPrintf(" save_game - Saves the current game state to the hard disk\n"); + debugPrintf(" restore_game - Restores a saved game from the hard disk\n"); + debugPrintf(" list_saves - List all saved games including filenames\n"); + debugPrintf(" restart_game - Restarts the game\n"); + debugPrintf(" version - Shows the resource and interpreter versions\n"); + debugPrintf(" room - Gets or sets the current room number\n"); + debugPrintf(" quit - Quits the game\n"); + debugPrintf("\n"); + debugPrintf("Graphics:\n"); + debugPrintf(" show_map - Switches to visual, priority, control or display screen\n"); + debugPrintf(" set_palette - Sets a palette resource\n"); + debugPrintf(" draw_pic - Draws a pic resource\n"); + debugPrintf(" draw_cel - Draws a cel from a view resource\n"); + debugPrintf(" pic_visualize - Enables visualization of the drawing process of EGA pictures\n"); + debugPrintf(" undither - Enable/disable undithering\n"); + debugPrintf(" play_video - Plays a SEQ, AVI, VMD, RBT or DUK video\n"); + debugPrintf(" animate_list / al - Shows the current list of objects in kAnimate's draw list (SCI0 - SCI1.1)\n"); + debugPrintf(" window_list / wl - Shows a list of all the windows (ports) in the draw list (SCI0 - SCI1.1)\n"); + debugPrintf(" plane_list / pl - Shows a list of all the planes in the draw list (SCI2+)\n"); + debugPrintf(" plane_items / pi - Shows a list of all items for a plane (SCI2+)\n"); + debugPrintf(" saved_bits - List saved bits on the hunk\n"); + debugPrintf(" show_saved_bits - Display saved bits\n"); + debugPrintf("\n"); + debugPrintf("Segments:\n"); + debugPrintf(" segment_table / segtable - Lists all segments\n"); + debugPrintf(" segment_info / seginfo - Provides information on the specified segment\n"); + debugPrintf(" segment_kill / segkill - Deletes the specified segment\n"); + debugPrintf("\n"); + debugPrintf("Garbage collection:\n"); + debugPrintf(" gc - Invokes the garbage collector\n"); + debugPrintf(" gc_objects - Lists all reachable objects, normalized\n"); + debugPrintf(" gc_reachable - Lists all addresses directly reachable from a given memory object\n"); + debugPrintf(" gc_freeable - Lists all addresses freeable in a given segment\n"); + debugPrintf(" gc_normalize - Prints the \"normal\" address of a given address\n"); + debugPrintf("\n"); + debugPrintf("Music/SFX:\n"); + debugPrintf(" songlib - Shows the song library\n"); + debugPrintf(" songinfo - Shows information about a specified song in the song library\n"); + debugPrintf(" togglesound - Starts/stops a sound in the song library\n"); + debugPrintf(" stopallsounds - Stops all sounds in the playlist\n"); + debugPrintf(" startsound - Starts the specified sound resource, replacing the first song in the song library\n"); + debugPrintf(" is_sample - Shows information on a given sound resource, if it's a PCM sample\n"); + debugPrintf(" sfx01_header - Dumps the header of a SCI01 song\n"); + debugPrintf(" sfx01_track - Dumps a track of a SCI01 song\n"); + debugPrintf(" show_instruments - Shows the instruments of a specific song, or all songs\n"); + debugPrintf(" map_instrument - Dynamically maps an MT-32 instrument to a GM instrument\n"); + debugPrintf("\n"); + debugPrintf("Script:\n"); + debugPrintf(" addresses - Provides information on how to pass addresses\n"); + debugPrintf(" registers - Shows the current register values\n"); + debugPrintf(" dissect_script - Examines a script\n"); + debugPrintf(" backtrace / bt - Dumps the send/self/super/call/calle/callb stack\n"); + debugPrintf(" trace / t / s - Executes one operation (no parameters) or several operations (specified as a parameter) \n"); + debugPrintf(" stepover / p - Executes one operation, skips over call/send\n"); + debugPrintf(" step_ret / pret - Steps forward until ret is called on the current execution stack level.\n"); + debugPrintf(" step_event / se - Steps forward until a SCI event is received.\n"); + debugPrintf(" step_global / sg - Steps until the global variable with the specified index is modified.\n"); + debugPrintf(" step_callk / snk - Steps forward until it hits the next callk operation, or a specific callk (specified as a parameter)\n"); + debugPrintf(" disasm - Disassembles a method by name\n"); + debugPrintf(" disasm_addr - Disassembles one or more commands\n"); + debugPrintf(" send - Sends a message to an object\n"); + debugPrintf(" go - Executes the script\n"); + debugPrintf(" logkernel - Logs kernel calls\n"); + debugPrintf("\n"); + debugPrintf("Breakpoints:\n"); + debugPrintf(" bp_list / bplist / bl - Lists the current breakpoints\n"); + debugPrintf(" bp_del / bpdel / bc - Deletes a breakpoint with the specified index\n"); + debugPrintf(" bp_method / bpx - Sets a breakpoint on the execution of a specified method/selector\n"); + debugPrintf(" bp_read / bpr - Sets a breakpoint on reading of a specified selector\n"); + debugPrintf(" bp_write / bpw - Sets a breakpoint on writing to a specified selector\n"); + debugPrintf(" bp_kernel / bpk - Sets a breakpoint on execution of a kernel function\n"); + debugPrintf(" bp_function / bpe - Sets a breakpoint on the execution of the specified exported function\n"); + debugPrintf("\n"); + debugPrintf("VM:\n"); + debugPrintf(" script_steps - Shows the number of executed SCI operations\n"); + debugPrintf(" vm_varlist / vmvarlist / vl - Shows the addresses of variables in the VM\n"); + debugPrintf(" vm_vars / vmvars / vv - Displays or changes variables in the VM\n"); + debugPrintf(" stack - Lists the specified number of stack elements\n"); + debugPrintf(" value_type - Determines the type of a value\n"); + debugPrintf(" view_listnode - Examines the list node at the given address\n"); + debugPrintf(" view_reference / vr - Examines an arbitrary reference\n"); + debugPrintf(" view_object / vo - Examines the object at the given address\n"); + debugPrintf(" active_object - Shows information on the currently active object or class\n"); + debugPrintf(" acc_object - Shows information on the object or class at the address indexed by the accumulator\n"); + debugPrintf("\n"); return true; } @@ -464,30 +467,30 @@ bool Console::cmdGetVersion(int argc, const char **argv) { versionFile.close(); } - DebugPrintf("Game ID: %s\n", _engine->getGameIdStr()); - DebugPrintf("Emulated interpreter version: %s\n", getSciVersionDesc(getSciVersion())); - DebugPrintf("\n"); - DebugPrintf("Detected features:\n"); - DebugPrintf("------------------\n"); - DebugPrintf("Sound type: %s\n", getSciVersionDesc(_engine->_features->detectDoSoundType())); - DebugPrintf("Graphics functions type: %s\n", getSciVersionDesc(_engine->_features->detectGfxFunctionsType())); - DebugPrintf("Lofs type: %s\n", getSciVersionDesc(_engine->_features->detectLofsType())); - DebugPrintf("Move count type: %s\n", (_engine->_features->handleMoveCount()) ? "increment" : "ignore"); - DebugPrintf("SetCursor type: %s\n", getSciVersionDesc(_engine->_features->detectSetCursorType())); + debugPrintf("Game ID: %s\n", _engine->getGameIdStr()); + debugPrintf("Emulated interpreter version: %s\n", getSciVersionDesc(getSciVersion())); + debugPrintf("\n"); + debugPrintf("Detected features:\n"); + debugPrintf("------------------\n"); + debugPrintf("Sound type: %s\n", getSciVersionDesc(_engine->_features->detectDoSoundType())); + debugPrintf("Graphics functions type: %s\n", getSciVersionDesc(_engine->_features->detectGfxFunctionsType())); + debugPrintf("Lofs type: %s\n", getSciVersionDesc(_engine->_features->detectLofsType())); + debugPrintf("Move count type: %s\n", (_engine->_features->handleMoveCount()) ? "increment" : "ignore"); + debugPrintf("SetCursor type: %s\n", getSciVersionDesc(_engine->_features->detectSetCursorType())); #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2) - DebugPrintf("kString type: %s\n", (_engine->_features->detectSci2StringFunctionType() == kSci2StringFunctionOld) ? "SCI2 (old)" : "SCI2.1 (new)"); + debugPrintf("kString type: %s\n", (_engine->_features->detectSci2StringFunctionType() == kSci2StringFunctionOld) ? "SCI2 (old)" : "SCI2.1 (new)"); if (getSciVersion() == SCI_VERSION_2_1) - DebugPrintf("SCI2.1 kernel table: %s\n", (_engine->_features->detectSci21KernelType() == SCI_VERSION_2) ? "modified SCI2 (old)" : "SCI2.1 (new)"); + debugPrintf("SCI2.1 kernel table: %s\n", (_engine->_features->detectSci21KernelType() == SCI_VERSION_2) ? "modified SCI2 (old)" : "SCI2.1 (new)"); #endif - DebugPrintf("View type: %s\n", viewTypeDesc[g_sci->getResMan()->getViewType()]); - DebugPrintf("Uses palette merging: %s\n", g_sci->_gfxPalette->isMerging() ? "yes" : "no"); - DebugPrintf("Resource volume version: %s\n", g_sci->getResMan()->getVolVersionDesc()); - DebugPrintf("Resource map version: %s\n", g_sci->getResMan()->getMapVersionDesc()); - DebugPrintf("Contains selector vocabulary (vocab.997): %s\n", hasVocab997 ? "yes" : "no"); - DebugPrintf("Has CantBeHere selector: %s\n", g_sci->getKernel()->_selectorCache.cantBeHere != -1 ? "yes" : "no"); - DebugPrintf("Game version (VERSION file): %s\n", gameVersion.c_str()); - DebugPrintf("\n"); + debugPrintf("View type: %s\n", viewTypeDesc[g_sci->getResMan()->getViewType()]); + debugPrintf("Uses palette merging: %s\n", g_sci->_gfxPalette->isMerging() ? "yes" : "no"); + debugPrintf("Resource volume version: %s\n", g_sci->getResMan()->getVolVersionDesc()); + debugPrintf("Resource map version: %s\n", g_sci->getResMan()->getMapVersionDesc()); + debugPrintf("Contains selector vocabulary (vocab.997): %s\n", hasVocab997 ? "yes" : "no"); + debugPrintf("Has CantBeHere selector: %s\n", g_sci->getKernel()->_selectorCache.cantBeHere != -1 ? "yes" : "no"); + debugPrintf("Game version (VERSION file): %s\n", gameVersion.c_str()); + debugPrintf("\n"); return true; } @@ -498,13 +501,13 @@ bool Console::cmdOpcodes(int argc, const char **argv) { // If the resource couldn't be loaded, leave if (!r) { - DebugPrintf("unable to load vocab.998"); + debugPrintf("unable to load vocab.998"); return true; } int count = READ_LE_UINT16(r->data); - DebugPrintf("Opcode names in numeric order [index: type name]:\n"); + debugPrintf("Opcode names in numeric order [index: type name]:\n"); for (int i = 0; i < count; i++) { int offset = READ_LE_UINT16(r->data + 2 + i * 2); @@ -512,49 +515,49 @@ bool Console::cmdOpcodes(int argc, const char **argv) { int type = READ_LE_UINT16(r->data + offset + 2); // QFG3 has empty opcodes Common::String name = len > 0 ? Common::String((const char *)r->data + offset + 4, len) : "Dummy"; - DebugPrintf("%03x: %03x %20s | ", i, type, name.c_str()); + debugPrintf("%03x: %03x %20s | ", i, type, name.c_str()); if ((i % 3) == 2) - DebugPrintf("\n"); + debugPrintf("\n"); } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } bool Console::cmdSelector(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Attempts to find the requested selector by name.\n"); - DebugPrintf("Usage: %s <selector name>\n", argv[0]); + debugPrintf("Attempts to find the requested selector by name.\n"); + debugPrintf("Usage: %s <selector name>\n", argv[0]); return true; } Common::String name = argv[1]; int seeker = _engine->getKernel()->findSelector(name.c_str()); if (seeker >= 0) { - DebugPrintf("Selector %s found at %03x (%d)\n", name.c_str(), seeker, seeker); + debugPrintf("Selector %s found at %03x (%d)\n", name.c_str(), seeker, seeker); return true; } - DebugPrintf("Selector %s wasn't found\n", name.c_str()); + debugPrintf("Selector %s wasn't found\n", name.c_str()); return true; } bool Console::cmdSelectors(int argc, const char **argv) { - DebugPrintf("Selector names in numeric order:\n"); + debugPrintf("Selector names in numeric order:\n"); Common::String selectorName; for (uint seeker = 0; seeker < _engine->getKernel()->getSelectorNamesSize(); seeker++) { selectorName = _engine->getKernel()->getSelectorName(seeker); if (selectorName != "BAD SELECTOR") - DebugPrintf("%03x: %20s | ", seeker, selectorName.c_str()); + debugPrintf("%03x: %20s | ", seeker, selectorName.c_str()); else continue; if ((seeker % 3) == 2) - DebugPrintf("\n"); + debugPrintf("\n"); } - DebugPrintf("\n"); + debugPrintf("\n"); #if 0 // For debug/development @@ -584,14 +587,14 @@ bool Console::cmdSelectors(int argc, const char **argv) { } bool Console::cmdKernelFunctions(int argc, const char **argv) { - DebugPrintf("Kernel function names in numeric order:\n"); + debugPrintf("Kernel function names in numeric order:\n"); for (uint seeker = 0; seeker < _engine->getKernel()->getKernelNamesSize(); seeker++) { - DebugPrintf("%03x: %20s | ", seeker, _engine->getKernel()->getKernelName(seeker).c_str()); + debugPrintf("%03x: %20s | ", seeker, _engine->getKernel()->getKernelName(seeker).c_str()); if ((seeker % 3) == 2) - DebugPrintf("\n"); + debugPrintf("\n"); } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } @@ -610,9 +613,9 @@ bool Console::cmdParserWords(int argc, const char **argv) { bool Console::cmdSetParseNodes(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Sets the contents of all parse nodes.\n"); - DebugPrintf("Usage: %s <parse node1> <parse node2> ... <parse noden>\n", argv[0]); - DebugPrintf("Tokens should be separated by blanks and enclosed in parentheses\n"); + debugPrintf("Sets the contents of all parse nodes.\n"); + debugPrintf("Usage: %s <parse node1> <parse node2> ... <parse noden>\n", argv[0]); + debugPrintf("Tokens should be separated by blanks and enclosed in parentheses\n"); return true; } @@ -643,23 +646,23 @@ bool Console::cmdSetParseNodes(int argc, const char **argv) { bool Console::cmdRegisters(int argc, const char **argv) { EngineState *s = _engine->_gamestate; - DebugPrintf("Current register values:\n"); - DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(s->r_acc), PRINT_REG(s->r_prev), s->r_rest); + debugPrintf("Current register values:\n"); + debugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(s->r_acc), PRINT_REG(s->r_prev), s->r_rest); if (!s->_executionStack.empty()) { - DebugPrintf("pc=%04x:%04x obj=%04x:%04x fp=ST:%04x sp=ST:%04x\n", + debugPrintf("pc=%04x:%04x obj=%04x:%04x fp=ST:%04x sp=ST:%04x\n", PRINT_REG(s->xs->addr.pc), PRINT_REG(s->xs->objp), (unsigned)(s->xs->fp - s->stack_base), (unsigned)(s->xs->sp - s->stack_base)); } else - DebugPrintf("<no execution stack: pc,obj,fp omitted>\n"); + debugPrintf("<no execution stack: pc,obj,fp omitted>\n"); return true; } bool Console::cmdDiskDump(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Dumps the specified resource to disk as a patch file\n"); - DebugPrintf("Usage: %s <resource type> <resource number>\n", argv[0]); + debugPrintf("Dumps the specified resource to disk as a patch file\n"); + debugPrintf("Usage: %s <resource type> <resource number>\n", argv[0]); cmdResourceTypes(argc, argv); return true; } @@ -668,7 +671,7 @@ bool Console::cmdDiskDump(int argc, const char **argv) { ResourceType res = parseResourceType(argv[1]); if (res == kResourceTypeInvalid) - DebugPrintf("Resource type '%s' is not valid\n", argv[1]); + debugPrintf("Resource type '%s' is not valid\n", argv[1]); else { Resource *resource = _engine->getResMan()->findResource(ResourceId(res, resNum), 0); if (resource) { @@ -680,9 +683,9 @@ bool Console::cmdDiskDump(int argc, const char **argv) { outFile->finalize(); outFile->close(); delete outFile; - DebugPrintf("Resource %s.%03d (located in %s) has been dumped to disk\n", argv[1], resNum, resource->getResourceLocation().c_str()); + debugPrintf("Resource %s.%03d (located in %s) has been dumped to disk\n", argv[1], resNum, resource->getResourceLocation().c_str()); } else { - DebugPrintf("Resource %s.%03d not found\n", argv[1], resNum); + debugPrintf("Resource %s.%03d not found\n", argv[1], resNum); } } @@ -691,8 +694,8 @@ bool Console::cmdDiskDump(int argc, const char **argv) { bool Console::cmdHexDump(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Dumps the specified resource to standard output\n"); - DebugPrintf("Usage: %s <resource type> <resource number>\n", argv[0]); + debugPrintf("Dumps the specified resource to standard output\n"); + debugPrintf("Usage: %s <resource type> <resource number>\n", argv[0]); cmdResourceTypes(argc, argv); return true; } @@ -701,14 +704,14 @@ bool Console::cmdHexDump(int argc, const char **argv) { ResourceType res = parseResourceType(argv[1]); if (res == kResourceTypeInvalid) - DebugPrintf("Resource type '%s' is not valid\n", argv[1]); + debugPrintf("Resource type '%s' is not valid\n", argv[1]); else { Resource *resource = _engine->getResMan()->findResource(ResourceId(res, resNum), 0); if (resource) { Common::hexdump(resource->data, resource->size, 16, 0); - DebugPrintf("Resource %s.%03d has been dumped to standard output\n", argv[1], resNum); + debugPrintf("Resource %s.%03d has been dumped to standard output\n", argv[1], resNum); } else { - DebugPrintf("Resource %s.%03d not found\n", argv[1], resNum); + debugPrintf("Resource %s.%03d not found\n", argv[1], resNum); } } @@ -717,21 +720,21 @@ bool Console::cmdHexDump(int argc, const char **argv) { bool Console::cmdResourceId(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Identifies a resource number by splitting it up in resource type and resource number\n"); - DebugPrintf("Usage: %s <resource number>\n", argv[0]); + debugPrintf("Identifies a resource number by splitting it up in resource type and resource number\n"); + debugPrintf("Usage: %s <resource number>\n", argv[0]); return true; } int id = atoi(argv[1]); - DebugPrintf("%s.%d (0x%x)\n", getResourceTypeName((ResourceType)(id >> 11)), id & 0x7ff, id & 0x7ff); + debugPrintf("%s.%d (0x%x)\n", getResourceTypeName((ResourceType)(id >> 11)), id & 0x7ff, id & 0x7ff); return true; } bool Console::cmdDissectScript(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Examines a script\n"); - DebugPrintf("Usage: %s <script number>\n", argv[0]); + debugPrintf("Examines a script\n"); + debugPrintf("Usage: %s <script number>\n", argv[0]); return true; } @@ -745,13 +748,13 @@ bool Console::cmdRoomNumber(int argc, const char **argv) { // The same functionality is provided by "vmvars g 13" (but this one is more straighforward) if (argc != 2) { - DebugPrintf("Current room number is %d\n", _engine->_gamestate->currentRoomNumber()); - DebugPrintf("Calling this command with the room number (in decimal or hexadecimal) changes the room\n"); + debugPrintf("Current room number is %d\n", _engine->_gamestate->currentRoomNumber()); + debugPrintf("Calling this command with the room number (in decimal or hexadecimal) changes the room\n"); } else { Common::String roomNumberStr = argv[1]; int roomNumber = strtol(roomNumberStr.c_str(), NULL, roomNumberStr.hasSuffix("h") ? 16 : 10); _engine->_gamestate->setRoomNumber(roomNumber); - DebugPrintf("Room number changed to %d (%x in hex)\n", roomNumber, roomNumber); + debugPrintf("Room number changed to %d (%x in hex)\n", roomNumber, roomNumber); } return true; @@ -759,8 +762,8 @@ bool Console::cmdRoomNumber(int argc, const char **argv) { bool Console::cmdResourceInfo(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Shows information about a resource\n"); - DebugPrintf("Usage: %s <resource type> <resource number>\n", argv[0]); + debugPrintf("Shows information about a resource\n"); + debugPrintf("Usage: %s <resource type> <resource number>\n", argv[0]); return true; } @@ -768,14 +771,14 @@ bool Console::cmdResourceInfo(int argc, const char **argv) { ResourceType res = parseResourceType(argv[1]); if (res == kResourceTypeInvalid) - DebugPrintf("Resource type '%s' is not valid\n", argv[1]); + debugPrintf("Resource type '%s' is not valid\n", argv[1]); else { Resource *resource = _engine->getResMan()->findResource(ResourceId(res, resNum), 0); if (resource) { - DebugPrintf("Resource size: %d\n", resource->size); - DebugPrintf("Resource location: %s\n", resource->getResourceLocation().c_str()); + debugPrintf("Resource size: %d\n", resource->size); + debugPrintf("Resource location: %s\n", resource->getResourceLocation().c_str()); } else { - DebugPrintf("Resource %s.%03d not found\n", argv[1], resNum); + debugPrintf("Resource %s.%03d not found\n", argv[1], resNum); } } @@ -783,10 +786,10 @@ bool Console::cmdResourceInfo(int argc, const char **argv) { } bool Console::cmdResourceTypes(int argc, const char **argv) { - DebugPrintf("The %d valid resource types are:\n", kResourceTypeInvalid); + debugPrintf("The %d valid resource types are:\n", kResourceTypeInvalid); for (int i = 0; i < kResourceTypeInvalid; i++) { - DebugPrintf("%s", getResourceTypeName((ResourceType) i)); - DebugPrintf((i < kResourceTypeInvalid - 1) ? ", " : "\n"); + debugPrintf("%s", getResourceTypeName((ResourceType) i)); + debugPrintf((i < kResourceTypeInvalid - 1) ? ", " : "\n"); } return true; @@ -794,10 +797,10 @@ bool Console::cmdResourceTypes(int argc, const char **argv) { bool Console::cmdHexgrep(int argc, const char **argv) { if (argc < 4) { - DebugPrintf("Searches some resources for a particular sequence of bytes, represented as decimal or hexadecimal numbers.\n"); - DebugPrintf("Usage: %s <resource type> <resource number> <search string>\n", argv[0]); - DebugPrintf("<resource number> can be a specific resource number, or \"all\" for all of the resources of the specified type\n"); - DebugPrintf("EXAMPLES:\n hexgrep script all 0xe8 0x03 0xc8 0x00\n hexgrep pic 0x42 0xfe\n"); + debugPrintf("Searches some resources for a particular sequence of bytes, represented as decimal or hexadecimal numbers.\n"); + debugPrintf("Usage: %s <resource type> <resource number> <search string>\n", argv[0]); + debugPrintf("<resource number> can be a specific resource number, or \"all\" for all of the resources of the specified type\n"); + debugPrintf("EXAMPLES:\n hexgrep script all 0xe8 0x03 0xc8 0x00\n hexgrep pic 0x42 0xfe\n"); cmdResourceTypes(argc, argv); return true; } @@ -807,7 +810,7 @@ bool Console::cmdHexgrep(int argc, const char **argv) { Resource *script = NULL; if (restype == kResourceTypeInvalid) { - DebugPrintf("Resource type '%s' is not valid\n", argv[1]); + debugPrintf("Resource type '%s' is not valid\n", argv[1]); return true; } @@ -845,10 +848,10 @@ bool Console::cmdHexgrep(int argc, const char **argv) { seeker = seekerold + 1; if (!output_script_name) { - DebugPrintf("\nIn %s.%03d:\n", getResourceTypeName((ResourceType)restype), resNumber); + debugPrintf("\nIn %s.%03d:\n", getResourceTypeName((ResourceType)restype), resNumber); output_script_name = 1; } - DebugPrintf(" 0x%04x\n", seekerold); + debugPrintf(" 0x%04x\n", seekerold); } } else comppos = 0; @@ -863,38 +866,38 @@ bool Console::cmdHexgrep(int argc, const char **argv) { bool Console::cmdVerifyScripts(int argc, const char **argv) { if (getSciVersion() < SCI_VERSION_1_1) { - DebugPrintf("This script check is only meant for SCI1.1-SCI3 games\n"); + debugPrintf("This script check is only meant for SCI1.1-SCI3 games\n"); return true; } Common::List<ResourceId> resources = _engine->getResMan()->listResources(kResourceTypeScript); Common::sort(resources.begin(), resources.end()); - DebugPrintf("%d SCI1.1-SCI3 scripts found, performing sanity checks...\n", resources.size()); + debugPrintf("%d SCI1.1-SCI3 scripts found, performing sanity checks...\n", resources.size()); Resource *script, *heap; Common::List<ResourceId>::iterator itr; for (itr = resources.begin(); itr != resources.end(); ++itr) { script = _engine->getResMan()->findResource(*itr, false); if (!script) - DebugPrintf("Error: script %d couldn't be loaded\n", itr->getNumber()); + debugPrintf("Error: script %d couldn't be loaded\n", itr->getNumber()); if (getSciVersion() <= SCI_VERSION_2_1) { heap = _engine->getResMan()->findResource(ResourceId(kResourceTypeHeap, itr->getNumber()), false); if (!heap) - DebugPrintf("Error: script %d doesn't have a corresponding heap\n", itr->getNumber()); + debugPrintf("Error: script %d doesn't have a corresponding heap\n", itr->getNumber()); if (script && heap && (script->size + heap->size > 65535)) - DebugPrintf("Error: script and heap %d together are larger than 64KB (%d bytes)\n", + debugPrintf("Error: script and heap %d together are larger than 64KB (%d bytes)\n", itr->getNumber(), script->size + heap->size); } else { // SCI3 if (script && script->size > 65535) - DebugPrintf("Error: script %d is larger than 64KB (%d bytes)\n", + debugPrintf("Error: script %d is larger than 64KB (%d bytes)\n", itr->getNumber(), script->size); } } - DebugPrintf("SCI1.1-SCI2.1 script check finished\n"); + debugPrintf("SCI1.1-SCI2.1 script check finished\n"); return true; } @@ -931,9 +934,9 @@ bool Console::cmdShowInstruments(int argc, const char **argv) { instrumentsSongs[i][j] = false; if (songNumber == -1) { - DebugPrintf("%d sounds found, checking their instrument mappings...\n", resources.size()); - DebugPrintf("Instruments:\n"); - DebugPrintf("============\n"); + debugPrintf("%d sounds found, checking their instrument mappings...\n", resources.size()); + debugPrintf("Instruments:\n"); + debugPrintf("============\n"); } Common::List<ResourceId>::iterator itr; @@ -956,7 +959,7 @@ bool Console::cmdShowInstruments(int argc, const char **argv) { bool endOfTrack = false; bool firstOneShown = false; - DebugPrintf("Song %d: ", itr->getNumber()); + debugPrintf("Song %d: ", itr->getNumber()); do { while (*channelData == 0xF8) @@ -984,9 +987,9 @@ bool Console::cmdShowInstruments(int argc, const char **argv) { if (!firstOneShown) firstOneShown = true; else - DebugPrintf(","); + debugPrintf(","); - DebugPrintf(" %d", instrument); + debugPrintf(" %d", instrument); instruments[instrument]++; instrumentsSongs[instrument][itr->getNumber()] = true; } else { @@ -1024,44 +1027,44 @@ bool Console::cmdShowInstruments(int argc, const char **argv) { } } while (!endOfTrack); - DebugPrintf("\n"); + debugPrintf("\n"); } delete parser; delete player; - DebugPrintf("\n"); + debugPrintf("\n"); if (songNumber == -1) { - DebugPrintf("Used instruments: "); + debugPrintf("Used instruments: "); for (int i = 0; i < 128; i++) { if (instruments[i] > 0) - DebugPrintf("%d, ", i); + debugPrintf("%d, ", i); } - DebugPrintf("\n\n"); + debugPrintf("\n\n"); } - DebugPrintf("Instruments not mapped in the MT32->GM map: "); + debugPrintf("Instruments not mapped in the MT32->GM map: "); for (int i = 0; i < 128; i++) { if (instruments[i] > 0 && getGmInstrument(Mt32MemoryTimbreMaps[i]) == MIDI_UNMAPPED) - DebugPrintf("%d, ", i); + debugPrintf("%d, ", i); } - DebugPrintf("\n\n"); + debugPrintf("\n\n"); if (songNumber == -1) { - DebugPrintf("Used instruments in songs:\n"); + debugPrintf("Used instruments in songs:\n"); for (int i = 0; i < 128; i++) { if (instruments[i] > 0) { - DebugPrintf("Instrument %d: ", i); + debugPrintf("Instrument %d: ", i); for (int j = 0; j < 1000; j++) { if (instrumentsSongs[i][j]) - DebugPrintf("%d, ", j); + debugPrintf("%d, ", j); } - DebugPrintf("\n"); + debugPrintf("\n"); } } - DebugPrintf("\n\n"); + debugPrintf("\n\n"); } return true; @@ -1069,13 +1072,13 @@ bool Console::cmdShowInstruments(int argc, const char **argv) { bool Console::cmdMapInstrument(int argc, const char **argv) { if (argc != 4) { - DebugPrintf("Maps an MT-32 custom instrument to a GM instrument on the fly\n\n"); - DebugPrintf("Usage %s <MT-32 instrument name> <GM instrument> <GM rhythm key>\n", argv[0]); - DebugPrintf("Each MT-32 instrument is always 10 characters and is mapped to either a GM instrument, or a GM rhythm key\n"); - DebugPrintf("A value of 255 (0xff) signifies an unmapped instrument\n"); - DebugPrintf("Please replace the spaces in the instrument name with underscores (\"_\"). They'll be converted to spaces afterwards\n\n"); - DebugPrintf("Example: %s test_0__XX 1 255\n", argv[0]); - DebugPrintf("The above example will map the MT-32 instrument \"test 0 XX\" to GM instrument 1\n\n"); + debugPrintf("Maps an MT-32 custom instrument to a GM instrument on the fly\n\n"); + debugPrintf("Usage %s <MT-32 instrument name> <GM instrument> <GM rhythm key>\n", argv[0]); + debugPrintf("Each MT-32 instrument is always 10 characters and is mapped to either a GM instrument, or a GM rhythm key\n"); + debugPrintf("A value of 255 (0xff) signifies an unmapped instrument\n"); + debugPrintf("Please replace the spaces in the instrument name with underscores (\"_\"). They'll be converted to spaces afterwards\n\n"); + debugPrintf("Example: %s test_0__XX 1 255\n", argv[0]); + debugPrintf("The above example will map the MT-32 instrument \"test 0 XX\" to GM instrument 1\n\n"); } else { if (Mt32dynamicMappings != NULL) { Mt32ToGmMap newMapping; @@ -1093,11 +1096,11 @@ bool Console::cmdMapInstrument(int argc, const char **argv) { } } - DebugPrintf("Current dynamic mappings:\n"); + debugPrintf("Current dynamic mappings:\n"); if (Mt32dynamicMappings != NULL) { const Mt32ToGmMapList::iterator end = Mt32dynamicMappings->end(); for (Mt32ToGmMapList::iterator it = Mt32dynamicMappings->begin(); it != end; ++it) { - DebugPrintf("\"%s\" -> %d / %d\n", (*it).name, (*it).gmInstr, (*it).gmRhythmKey); + debugPrintf("\"%s\" -> %d / %d\n", (*it).name, (*it).gmInstr, (*it).gmRhythmKey); } } @@ -1106,7 +1109,7 @@ bool Console::cmdMapInstrument(int argc, const char **argv) { bool Console::cmdList(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Lists all the resources of a given type\n"); + debugPrintf("Lists all the resources of a given type\n"); cmdResourceTypes(argc, argv); return true; } @@ -1114,13 +1117,13 @@ bool Console::cmdList(int argc, const char **argv) { ResourceType res = parseResourceType(argv[1]); if (res == kResourceTypeInvalid) - DebugPrintf("Unknown resource type: '%s'\n", argv[1]); + debugPrintf("Unknown resource type: '%s'\n", argv[1]); else { int number = -1; if ((res == kResourceTypeAudio36) || (res == kResourceTypeSync36)) { if (argc != 3) { - DebugPrintf("Please specify map number (-1: all maps)\n"); + debugPrintf("Please specify map number (-1: all maps)\n"); return true; } number = atoi(argv[2]); @@ -1133,18 +1136,18 @@ bool Console::cmdList(int argc, const char **argv) { Common::List<ResourceId>::iterator itr; for (itr = resources.begin(); itr != resources.end(); ++itr) { if (number == -1) { - DebugPrintf("%8i", itr->getNumber()); + debugPrintf("%8i", itr->getNumber()); if (++cnt % 10 == 0) - DebugPrintf("\n"); + debugPrintf("\n"); } else if (number == (int)itr->getNumber()) { const uint32 tuple = itr->getTuple(); - DebugPrintf("(%3i, %3i, %3i, %3i) ", (tuple >> 24) & 0xff, (tuple >> 16) & 0xff, + debugPrintf("(%3i, %3i, %3i, %3i) ", (tuple >> 24) & 0xff, (tuple >> 16) & 0xff, (tuple >> 8) & 0xff, tuple & 0xff); if (++cnt % 4 == 0) - DebugPrintf("\n"); + debugPrintf("\n"); } } - DebugPrintf("\n"); + debugPrintf("\n"); } return true; @@ -1152,8 +1155,8 @@ bool Console::cmdList(int argc, const char **argv) { bool Console::cmdSaveGame(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Saves the current game state to the hard disk\n"); - DebugPrintf("Usage: %s <filename>\n", argv[0]); + debugPrintf("Saves the current game state to the hard disk\n"); + debugPrintf("Usage: %s <filename>\n", argv[0]); return true; } @@ -1163,19 +1166,19 @@ bool Console::cmdSaveGame(int argc, const char **argv) { result++; if (result) - DebugPrintf("Note: Game state has %d open file handles.\n", result); + debugPrintf("Note: Game state has %d open file handles.\n", result); Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); Common::OutSaveFile *out = saveFileMan->openForSaving(argv[1]); const char *version = ""; if (!out) { - DebugPrintf("Error opening savegame \"%s\" for writing\n", argv[1]); + debugPrintf("Error opening savegame \"%s\" for writing\n", argv[1]); return true; } // TODO: enable custom descriptions? force filename into a specific format? if (!gamestate_save(_engine->_gamestate, out, "debugging", version)) { - DebugPrintf("Saving the game state to '%s' failed\n", argv[1]); + debugPrintf("Saving the game state to '%s' failed\n", argv[1]); } else { out->finalize(); if (out->err()) { @@ -1189,8 +1192,8 @@ bool Console::cmdSaveGame(int argc, const char **argv) { bool Console::cmdRestoreGame(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Restores a saved game from the hard disk\n"); - DebugPrintf("Usage: %s <filename>\n", argv[0]); + debugPrintf("Restores a saved game from the hard disk\n"); + debugPrintf("Usage: %s <filename>\n", argv[0]); return true; } @@ -1203,17 +1206,17 @@ bool Console::cmdRestoreGame(int argc, const char **argv) { } if (_engine->_gamestate->r_acc == make_reg(0, 1)) { - DebugPrintf("Restoring gamestate '%s' failed.\n", argv[1]); + debugPrintf("Restoring gamestate '%s' failed.\n", argv[1]); return true; } - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } bool Console::cmdRestartGame(int argc, const char **argv) { _engine->_gamestate->abortScriptProcessing = kAbortRestartGame; - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } // The scripts get IDs ranging from 100->199, because the scripts require us to assign unique ids THAT EVEN STAY BETWEEN @@ -1231,25 +1234,25 @@ bool Console::cmdListSaves(int argc, const char **argv) { for (uint i = 0; i < saves.size(); i++) { Common::String filename = g_sci->getSavegameName(saves[i].id); - DebugPrintf("%s: '%s'\n", filename.c_str(), saves[i].name); + debugPrintf("%s: '%s'\n", filename.c_str(), saves[i].name); } return true; } bool Console::cmdClassTable(int argc, const char **argv) { - DebugPrintf("Available classes (parse a parameter to filter the table by a specific class):\n"); + debugPrintf("Available classes (parse a parameter to filter the table by a specific class):\n"); for (uint i = 0; i < _engine->_gamestate->_segMan->classTableSize(); i++) { Class temp = _engine->_gamestate->_segMan->_classTable[i]; if (temp.reg.getSegment()) { const char *className = _engine->_gamestate->_segMan->getObjectName(temp.reg); if (argc == 1 || (argc == 2 && !strcmp(className, argv[1]))) { - DebugPrintf(" Class 0x%x (%s) at %04x:%04x (script %d)\n", i, + debugPrintf(" Class 0x%x (%s) at %04x:%04x (script %d)\n", i, className, PRINT_REG(temp.reg), temp.script); - } else DebugPrintf(" Class 0x%x (not loaded; can't get name) (script %d)\n", i, temp.script); + } else debugPrintf(" Class 0x%x (not loaded; can't get name) (script %d)\n", i, temp.script); } } @@ -1257,52 +1260,52 @@ bool Console::cmdClassTable(int argc, const char **argv) { } bool Console::cmdSentenceFragments(int argc, const char **argv) { - DebugPrintf("Sentence fragments (used to build Parse trees)\n"); + debugPrintf("Sentence fragments (used to build Parse trees)\n"); for (uint i = 0; i < _engine->getVocabulary()->getParserBranchesSize(); i++) { int j = 0; const parse_tree_branch_t &branch = _engine->getVocabulary()->getParseTreeBranch(i); - DebugPrintf("R%02d: [%x] ->", i, branch.id); + debugPrintf("R%02d: [%x] ->", i, branch.id); while ((j < 10) && branch.data[j]) { int dat = branch.data[j++]; switch (dat) { case VOCAB_TREE_NODE_COMPARE_TYPE: dat = branch.data[j++]; - DebugPrintf(" C(%x)", dat); + debugPrintf(" C(%x)", dat); break; case VOCAB_TREE_NODE_COMPARE_GROUP: dat = branch.data[j++]; - DebugPrintf(" WG(%x)", dat); + debugPrintf(" WG(%x)", dat); break; case VOCAB_TREE_NODE_FORCE_STORAGE: dat = branch.data[j++]; - DebugPrintf(" FORCE(%x)", dat); + debugPrintf(" FORCE(%x)", dat); break; default: if (dat > VOCAB_TREE_NODE_LAST_WORD_STORAGE) { int dat2 = branch.data[j++]; - DebugPrintf(" %x[%x]", dat, dat2); + debugPrintf(" %x[%x]", dat, dat2); } else - DebugPrintf(" ?%x?", dat); + debugPrintf(" ?%x?", dat); } } - DebugPrintf("\n"); + debugPrintf("\n"); } - DebugPrintf("%d rules.\n", _engine->getVocabulary()->getParserBranchesSize()); + debugPrintf("%d rules.\n", _engine->getVocabulary()->getParserBranchesSize()); return true; } bool Console::cmdParse(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Parses a sequence of words with a GNF rule set and prints the resulting parse tree\n"); - DebugPrintf("Usage: %s <word1> <word2> ... <wordn>\n", argv[0]); + debugPrintf("Parses a sequence of words with a GNF rule set and prints the resulting parse tree\n"); + debugPrintf("Usage: %s <word1> <word2> ... <wordn>\n", argv[0]); return true; } @@ -1316,7 +1319,7 @@ bool Console::cmdParse(int argc, const char **argv) { strcat(string, argv[i]); } - DebugPrintf("Parsing '%s'\n", string); + debugPrintf("Parsing '%s'\n", string); ResultWordListList words; bool res = _engine->getVocabulary()->tokenizeString(words, string, &error); @@ -1325,26 +1328,26 @@ bool Console::cmdParse(int argc, const char **argv) { _engine->getVocabulary()->synonymizeTokens(words); - DebugPrintf("Parsed to the following blocks:\n"); + debugPrintf("Parsed to the following blocks:\n"); for (ResultWordListList::const_iterator i = words.begin(); i != words.end(); ++i) { - DebugPrintf(" "); + debugPrintf(" "); for (ResultWordList::const_iterator j = i->begin(); j != i->end(); ++j) { - DebugPrintf("%sType[%04x] Group[%04x]", j == i->begin() ? "" : " / ", j->_class, j->_group); + debugPrintf("%sType[%04x] Group[%04x]", j == i->begin() ? "" : " / ", j->_class, j->_group); } - DebugPrintf("\n"); + debugPrintf("\n"); } if (_engine->getVocabulary()->parseGNF(words, true)) syntax_fail = 1; // Building a tree failed if (syntax_fail) - DebugPrintf("Building a tree failed.\n"); + debugPrintf("Building a tree failed.\n"); else _engine->getVocabulary()->dumpParseTree(); } else { - DebugPrintf("Unknown word: '%s'\n", error); + debugPrintf("Unknown word: '%s'\n", error); free(error); } @@ -1353,10 +1356,10 @@ bool Console::cmdParse(int argc, const char **argv) { bool Console::cmdSaid(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Matches a string against a said spec\n"); - DebugPrintf("Usage: %s <string> > & <said spec>\n", argv[0]); - DebugPrintf("<string> is a sequence of actual words.\n"); - DebugPrintf("<said spec> is a sequence of hex tokens.\n"); + debugPrintf("Matches a string against a said spec\n"); + debugPrintf("Usage: %s <string> > & <said spec>\n", argv[0]); + debugPrintf("<string> is a sequence of actual words.\n"); + debugPrintf("<said spec> is a sequence of hex tokens.\n"); return true; } @@ -1373,10 +1376,10 @@ bool Console::cmdSaid(int argc, const char **argv) { } if (p >= argc-1) { - DebugPrintf("Matches a string against a said spec\n"); - DebugPrintf("Usage: %s <string> > & <said spec>\n", argv[0]); - DebugPrintf("<string> is a sequence of actual words.\n"); - DebugPrintf("<said spec> is a sequence of hex tokens.\n"); + debugPrintf("Matches a string against a said spec\n"); + debugPrintf("Usage: %s <string> > & <said spec>\n", argv[0]); + debugPrintf("<string> is a sequence of actual words.\n"); + debugPrintf("<said spec> is a sequence of hex tokens.\n"); return true; } @@ -1440,14 +1443,14 @@ bool Console::cmdSaid(int argc, const char **argv) { _engine->getVocabulary()->synonymizeTokens(words); - DebugPrintf("Parsed to the following blocks:\n"); + debugPrintf("Parsed to the following blocks:\n"); for (ResultWordListList::const_iterator i = words.begin(); i != words.end(); ++i) { - DebugPrintf(" "); + debugPrintf(" "); for (ResultWordList::const_iterator j = i->begin(); j != i->end(); ++j) { - DebugPrintf("%sType[%04x] Group[%04x]", j == i->begin() ? "" : " / ", j->_class, j->_group); + debugPrintf("%sType[%04x] Group[%04x]", j == i->begin() ? "" : " / ", j->_class, j->_group); } - DebugPrintf("\n"); + debugPrintf("\n"); } @@ -1456,17 +1459,17 @@ bool Console::cmdSaid(int argc, const char **argv) { syntax_fail = 1; // Building a tree failed if (syntax_fail) - DebugPrintf("Building a tree failed.\n"); + debugPrintf("Building a tree failed.\n"); else { _engine->getVocabulary()->dumpParseTree(); _engine->getVocabulary()->parserIsValid = true; int ret = said((byte *)spec, true); - DebugPrintf("kSaid: %s\n", (ret == SAID_NO_MATCH ? "No match" : "Match")); + debugPrintf("kSaid: %s\n", (ret == SAID_NO_MATCH ? "No match" : "Match")); } } else { - DebugPrintf("Unknown word: '%s'\n", error); + debugPrintf("Unknown word: '%s'\n", error); free(error); } @@ -1476,9 +1479,9 @@ bool Console::cmdSaid(int argc, const char **argv) { bool Console::cmdParserNodes(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Shows the specified number of nodes from the parse node tree\n"); - DebugPrintf("Usage: %s <nr>\n", argv[0]); - DebugPrintf("where <nr> is the number of nodes to show from the parse node tree\n"); + debugPrintf("Shows the specified number of nodes from the parse node tree\n"); + debugPrintf("Usage: %s <nr>\n", argv[0]); + debugPrintf("where <nr> is the number of nodes to show from the parse node tree\n"); return true; } @@ -1491,9 +1494,9 @@ bool Console::cmdParserNodes(int argc, const char **argv) { bool Console::cmdSetPalette(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Sets a palette resource\n"); - DebugPrintf("Usage: %s <resourceId>\n", argv[0]); - DebugPrintf("where <resourceId> is the number of the palette resource to set\n"); + debugPrintf("Sets a palette resource\n"); + debugPrintf("Usage: %s <resourceId>\n", argv[0]); + debugPrintf("where <resourceId> is the number of the palette resource to set\n"); return true; } @@ -1505,9 +1508,9 @@ bool Console::cmdSetPalette(int argc, const char **argv) { bool Console::cmdDrawPic(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Draws a pic resource\n"); - DebugPrintf("Usage: %s <resourceId>\n", argv[0]); - DebugPrintf("where <resourceId> is the number of the pic resource to draw\n"); + debugPrintf("Draws a pic resource\n"); + debugPrintf("Usage: %s <resourceId>\n", argv[0]); + debugPrintf("where <resourceId> is the number of the pic resource to draw\n"); return true; } @@ -1532,9 +1535,9 @@ bool Console::cmdDrawPic(int argc, const char **argv) { bool Console::cmdDrawCel(int argc, const char **argv) { if (argc < 4) { - DebugPrintf("Draws a cel from a view resource\n"); - DebugPrintf("Usage: %s <resourceId> <loopNr> <celNr> \n", argv[0]); - DebugPrintf("where <resourceId> is the number of the view resource to draw\n"); + debugPrintf("Draws a cel from a view resource\n"); + debugPrintf("Usage: %s <resourceId> <loopNr> <celNr> \n", argv[0]); + debugPrintf("where <resourceId> is the number of the view resource to draw\n"); return true; } @@ -1555,24 +1558,24 @@ bool Console::cmdDrawCel(int argc, const char **argv) { bool Console::cmdUndither(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Enable/disable undithering.\n"); - DebugPrintf("Usage: %s <0/1>\n", argv[0]); + debugPrintf("Enable/disable undithering.\n"); + debugPrintf("Usage: %s <0/1>\n", argv[0]); return true; } bool flag = atoi(argv[1]) ? true : false; _engine->_gfxScreen->enableUndithering(flag); if (flag) - DebugPrintf("undithering ENABLED\n"); + debugPrintf("undithering ENABLED\n"); else - DebugPrintf("undithering DISABLED\n"); + debugPrintf("undithering DISABLED\n"); return true; } bool Console::cmdPicVisualize(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Enable/disable picture visualization (EGA only)\n"); - DebugPrintf("Usage: %s <0/1>\n", argv[0]); + debugPrintf("Enable/disable picture visualization (EGA only)\n"); + debugPrintf("Usage: %s <0/1>\n", argv[0]); return true; } @@ -1581,21 +1584,21 @@ bool Console::cmdPicVisualize(int argc, const char **argv) { if (_engine->_resMan->getViewType() == kViewEga) { _engine->_gfxPaint16->debugSetEGAdrawingVisualize(state); if (state) - DebugPrintf("picture visualization ENABLED\n"); + debugPrintf("picture visualization ENABLED\n"); else - DebugPrintf("picture visualization DISABLED\n"); + debugPrintf("picture visualization DISABLED\n"); } else { - DebugPrintf("picture visualization only available for EGA games\n"); + debugPrintf("picture visualization only available for EGA games\n"); } return true; } bool Console::cmdPlayVideo(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Plays a SEQ, AVI, VMD, RBT or DUK video.\n"); - DebugPrintf("Usage: %s <video file name> <delay>\n", argv[0]); - DebugPrintf("The video file name should include the extension\n"); - DebugPrintf("Delay is only used in SEQ videos and is measured in ticks (default: 10)\n"); + debugPrintf("Plays a SEQ, AVI, VMD, RBT or DUK video.\n"); + debugPrintf("Usage: %s <video file name> <delay>\n", argv[0]); + debugPrintf("The video file name should include the extension\n"); + debugPrintf("Delay is only used in SEQ videos and is measured in ticks (default: 10)\n"); return true; } @@ -1606,29 +1609,29 @@ bool Console::cmdPlayVideo(int argc, const char **argv) { filename.hasSuffix(".rbt") || filename.hasSuffix(".duk")) { _videoFile = filename; _videoFrameDelay = (argc == 2) ? 10 : atoi(argv[2]); - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } else { - DebugPrintf("Unknown video file type\n"); + debugPrintf("Unknown video file type\n"); return true; } } bool Console::cmdAnimateList(int argc, const char **argv) { if (_engine->_gfxAnimate) { - DebugPrintf("Animate list:\n"); + debugPrintf("Animate list:\n"); _engine->_gfxAnimate->printAnimateList(this); } else { - DebugPrintf("This SCI version does not have an animate list\n"); + debugPrintf("This SCI version does not have an animate list\n"); } return true; } bool Console::cmdWindowList(int argc, const char **argv) { if (_engine->_gfxPorts) { - DebugPrintf("Window list:\n"); + debugPrintf("Window list:\n"); _engine->_gfxPorts->printWindowList(this); } else { - DebugPrintf("This SCI version does not have a list of ports\n"); + debugPrintf("This SCI version does not have a list of ports\n"); } return true; } @@ -1636,41 +1639,41 @@ bool Console::cmdWindowList(int argc, const char **argv) { bool Console::cmdPlaneList(int argc, const char **argv) { #ifdef ENABLE_SCI32 if (_engine->_gfxFrameout) { - DebugPrintf("Plane list:\n"); + debugPrintf("Plane list:\n"); _engine->_gfxFrameout->printPlaneList(this); } else { - DebugPrintf("This SCI version does not have a list of planes\n"); + debugPrintf("This SCI version does not have a list of planes\n"); } #else - DebugPrintf("SCI32 isn't included in this compiled executable\n"); + debugPrintf("SCI32 isn't included in this compiled executable\n"); #endif return true; } bool Console::cmdPlaneItemList(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Shows the list of items for a plane\n"); - DebugPrintf("Usage: %s <plane address>\n", argv[0]); + debugPrintf("Shows the list of items for a plane\n"); + debugPrintf("Usage: %s <plane address>\n", argv[0]); return true; } reg_t planeObject = NULL_REG; if (parse_reg_t(_engine->_gamestate, argv[1], &planeObject, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } #ifdef ENABLE_SCI32 if (_engine->_gfxFrameout) { - DebugPrintf("Plane item list:\n"); + debugPrintf("Plane item list:\n"); _engine->_gfxFrameout->printPlaneItemList(this, planeObject); } else { - DebugPrintf("This SCI version does not have a list of plane items\n"); + debugPrintf("This SCI version does not have a list of plane items\n"); } #else - DebugPrintf("SCI32 isn't included in this compiled executable\n"); + debugPrintf("SCI32 isn't included in this compiled executable\n"); #endif return true; } @@ -1680,7 +1683,7 @@ bool Console::cmdSavedBits(int argc, const char **argv) { SegmentId id = segman->findSegmentByType(SEG_TYPE_HUNK); HunkTable* hunks = (HunkTable *)segman->getSegmentObj(id); if (!hunks) { - DebugPrintf("No hunk segment found.\n"); + debugPrintf("No hunk segment found.\n"); return true; } @@ -1693,7 +1696,7 @@ bool Console::cmdSavedBits(int argc, const char **argv) { byte* memoryPtr = (byte *)h.mem; if (memoryPtr) { - DebugPrintf("%04x:%04x:", PRINT_REG(entries[i])); + debugPrintf("%04x:%04x:", PRINT_REG(entries[i])); Common::Rect rect; byte mask; @@ -1702,17 +1705,17 @@ bool Console::cmdSavedBits(int argc, const char **argv) { memcpy((void *)&rect, memoryPtr, sizeof(rect)); memcpy((void *)&mask, memoryPtr + sizeof(rect), sizeof(mask)); - DebugPrintf(" %d,%d - %d,%d", rect.top, rect.left, + debugPrintf(" %d,%d - %d,%d", rect.top, rect.left, rect.bottom, rect.right); if (mask & GFX_SCREEN_MASK_VISUAL) - DebugPrintf(" visual"); + debugPrintf(" visual"); if (mask & GFX_SCREEN_MASK_PRIORITY) - DebugPrintf(" priority"); + debugPrintf(" priority"); if (mask & GFX_SCREEN_MASK_CONTROL) - DebugPrintf(" control"); + debugPrintf(" control"); if (mask & GFX_SCREEN_MASK_DISPLAY) - DebugPrintf(" display"); - DebugPrintf("\n"); + debugPrintf(" display"); + debugPrintf("\n"); } } } @@ -1723,22 +1726,22 @@ bool Console::cmdSavedBits(int argc, const char **argv) { bool Console::cmdShowSavedBits(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Display saved bits.\n"); - DebugPrintf("Usage: %s <address>\n", argv[0]); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Display saved bits.\n"); + debugPrintf("Usage: %s <address>\n", argv[0]); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } reg_t memoryHandle = NULL_REG; if (parse_reg_t(_engine->_gamestate, argv[1], &memoryHandle, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } if (memoryHandle.isNull()) { - DebugPrintf("Invalid address.\n"); + debugPrintf("Invalid address.\n"); return true; } @@ -1746,26 +1749,26 @@ bool Console::cmdShowSavedBits(int argc, const char **argv) { SegmentId id = segman->findSegmentByType(SEG_TYPE_HUNK); HunkTable* hunks = (HunkTable *)segman->getSegmentObj(id); if (!hunks) { - DebugPrintf("No hunk segment found.\n"); + debugPrintf("No hunk segment found.\n"); return true; } if (memoryHandle.getSegment() != id || !hunks->isValidOffset(memoryHandle.getOffset())) { - DebugPrintf("Invalid address.\n"); + debugPrintf("Invalid address.\n"); return true; } const Hunk& h = hunks->_table[memoryHandle.getOffset()]; if (strcmp(h.type, "SaveBits()") != 0) { - DebugPrintf("Invalid address.\n"); + debugPrintf("Invalid address.\n"); return true; } byte *memoryPtr = segman->getHunkPointer(memoryHandle); if (!memoryPtr) { - DebugPrintf("Invalid or freed bits.\n"); + debugPrintf("Invalid or freed bits.\n"); return true; } @@ -1783,17 +1786,17 @@ bool Console::cmdShowSavedBits(int argc, const char **argv) { Common::Point bl(rect.left, rect.bottom-1); Common::Point br(rect.right-1, rect.bottom-1); - DebugPrintf(" %d,%d - %d,%d", rect.top, rect.left, + debugPrintf(" %d,%d - %d,%d", rect.top, rect.left, rect.bottom, rect.right); if (mask & GFX_SCREEN_MASK_VISUAL) - DebugPrintf(" visual"); + debugPrintf(" visual"); if (mask & GFX_SCREEN_MASK_PRIORITY) - DebugPrintf(" priority"); + debugPrintf(" priority"); if (mask & GFX_SCREEN_MASK_CONTROL) - DebugPrintf(" control"); + debugPrintf(" control"); if (mask & GFX_SCREEN_MASK_DISPLAY) - DebugPrintf(" display"); - DebugPrintf("\n"); + debugPrintf(" display"); + debugPrintf("\n"); if (!_engine->_gfxPaint16 || !_engine->_gfxScreen) return true; @@ -1843,7 +1846,7 @@ bool Console::cmdShowSavedBits(int argc, const char **argv) { bool Console::cmdParseGrammar(int argc, const char **argv) { - DebugPrintf("Parse grammar, in strict GNF:\n"); + debugPrintf("Parse grammar, in strict GNF:\n"); _engine->getVocabulary()->buildGNF(true); @@ -1851,71 +1854,71 @@ bool Console::cmdParseGrammar(int argc, const char **argv) { } bool Console::cmdPrintSegmentTable(int argc, const char **argv) { - DebugPrintf("Segment table:\n"); + debugPrintf("Segment table:\n"); for (uint i = 0; i < _engine->_gamestate->_segMan->_heap.size(); i++) { SegmentObj *mobj = _engine->_gamestate->_segMan->_heap[i]; if (mobj && mobj->getType()) { - DebugPrintf(" [%04x] ", i); + debugPrintf(" [%04x] ", i); switch (mobj->getType()) { case SEG_TYPE_SCRIPT: - DebugPrintf("S script.%03d l:%d ", (*(Script *)mobj).getScriptNumber(), (*(Script *)mobj).getLockers()); + debugPrintf("S script.%03d l:%d ", (*(Script *)mobj).getScriptNumber(), (*(Script *)mobj).getLockers()); break; case SEG_TYPE_CLONES: - DebugPrintf("C clones (%d allocd)", (*(CloneTable *)mobj).entries_used); + debugPrintf("C clones (%d allocd)", (*(CloneTable *)mobj).entries_used); break; case SEG_TYPE_LOCALS: - DebugPrintf("V locals %03d", (*(LocalVariables *)mobj).script_id); + debugPrintf("V locals %03d", (*(LocalVariables *)mobj).script_id); break; case SEG_TYPE_STACK: - DebugPrintf("D data stack (%d)", (*(DataStack *)mobj)._capacity); + debugPrintf("D data stack (%d)", (*(DataStack *)mobj)._capacity); break; case SEG_TYPE_LISTS: - DebugPrintf("L lists (%d)", (*(ListTable *)mobj).entries_used); + debugPrintf("L lists (%d)", (*(ListTable *)mobj).entries_used); break; case SEG_TYPE_NODES: - DebugPrintf("N nodes (%d)", (*(NodeTable *)mobj).entries_used); + debugPrintf("N nodes (%d)", (*(NodeTable *)mobj).entries_used); break; case SEG_TYPE_HUNK: - DebugPrintf("H hunk (%d)", (*(HunkTable *)mobj).entries_used); + debugPrintf("H hunk (%d)", (*(HunkTable *)mobj).entries_used); break; case SEG_TYPE_DYNMEM: - DebugPrintf("M dynmem: %d bytes", (*(DynMem *)mobj)._size); + debugPrintf("M dynmem: %d bytes", (*(DynMem *)mobj)._size); break; #ifdef ENABLE_SCI32 case SEG_TYPE_ARRAY: - DebugPrintf("A SCI32 arrays (%d)", (*(ArrayTable *)mobj).entries_used); + debugPrintf("A SCI32 arrays (%d)", (*(ArrayTable *)mobj).entries_used); break; case SEG_TYPE_STRING: - DebugPrintf("T SCI32 strings (%d)", (*(StringTable *)mobj).entries_used); + debugPrintf("T SCI32 strings (%d)", (*(StringTable *)mobj).entries_used); break; #endif default: - DebugPrintf("I Invalid (type = %x)", mobj->getType()); + debugPrintf("I Invalid (type = %x)", mobj->getType()); break; } - DebugPrintf(" \n"); + debugPrintf(" \n"); } } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } bool Console::segmentInfo(int nr) { - DebugPrintf("[%04x] ", nr); + debugPrintf("[%04x] ", nr); if ((nr < 0) || ((uint)nr >= _engine->_gamestate->_segMan->_heap.size()) || !_engine->_gamestate->_segMan->_heap[nr]) return false; @@ -1926,30 +1929,30 @@ bool Console::segmentInfo(int nr) { case SEG_TYPE_SCRIPT: { Script *scr = (Script *)mobj; - DebugPrintf("script.%03d locked by %d, bufsize=%d (%x)\n", scr->getScriptNumber(), scr->getLockers(), (uint)scr->getBufSize(), (uint)scr->getBufSize()); + debugPrintf("script.%03d locked by %d, bufsize=%d (%x)\n", scr->getScriptNumber(), scr->getLockers(), (uint)scr->getBufSize(), (uint)scr->getBufSize()); if (scr->getExportTable()) - DebugPrintf(" Exports: %4d at %d\n", scr->getExportsNr(), (int)(((const byte *)scr->getExportTable()) - ((const byte *)scr->getBuf()))); + debugPrintf(" Exports: %4d at %d\n", scr->getExportsNr(), (int)(((const byte *)scr->getExportTable()) - ((const byte *)scr->getBuf()))); else - DebugPrintf(" Exports: none\n"); + debugPrintf(" Exports: none\n"); - DebugPrintf(" Synonyms: %4d\n", scr->getSynonymsNr()); + debugPrintf(" Synonyms: %4d\n", scr->getSynonymsNr()); if (scr->getLocalsCount() > 0) - DebugPrintf(" Locals : %4d in segment 0x%x\n", scr->getLocalsCount(), scr->getLocalsSegment()); + debugPrintf(" Locals : %4d in segment 0x%x\n", scr->getLocalsCount(), scr->getLocalsSegment()); else - DebugPrintf(" Locals : none\n"); + debugPrintf(" Locals : none\n"); ObjMap objects = scr->getObjectMap(); - DebugPrintf(" Objects: %4d\n", objects.size()); + debugPrintf(" Objects: %4d\n", objects.size()); ObjMap::iterator it; const ObjMap::iterator end = objects.end(); for (it = objects.begin(); it != end; ++it) { - DebugPrintf(" "); + debugPrintf(" "); // Object header const Object *obj = _engine->_gamestate->_segMan->getObject(it->_value.getPos()); if (obj) - DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(it->_value.getPos()), + debugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(it->_value.getPos()), _engine->_gamestate->_segMan->getObjectName(it->_value.getPos()), obj->getVarCount(), obj->getMethodCount()); } @@ -1958,31 +1961,31 @@ bool Console::segmentInfo(int nr) { case SEG_TYPE_LOCALS: { LocalVariables *locals = (LocalVariables *)mobj; - DebugPrintf("locals for script.%03d\n", locals->script_id); - DebugPrintf(" %d (0x%x) locals\n", locals->_locals.size(), locals->_locals.size()); + debugPrintf("locals for script.%03d\n", locals->script_id); + debugPrintf(" %d (0x%x) locals\n", locals->_locals.size(), locals->_locals.size()); } break; case SEG_TYPE_STACK: { DataStack *stack = (DataStack *)mobj; - DebugPrintf("stack\n"); - DebugPrintf(" %d (0x%x) entries\n", stack->_capacity, stack->_capacity); + debugPrintf("stack\n"); + debugPrintf(" %d (0x%x) entries\n", stack->_capacity, stack->_capacity); } break; case SEG_TYPE_CLONES: { CloneTable *ct = (CloneTable *)mobj; - DebugPrintf("clones\n"); + debugPrintf("clones\n"); for (uint i = 0; i < ct->_table.size(); i++) if (ct->isValidEntry(i)) { reg_t objpos = make_reg(nr, i); - DebugPrintf(" [%04x] %s; copy of ", i, _engine->_gamestate->_segMan->getObjectName(objpos)); + debugPrintf(" [%04x] %s; copy of ", i, _engine->_gamestate->_segMan->getObjectName(objpos)); // Object header const Object *obj = _engine->_gamestate->_segMan->getObject(ct->_table[i].getPos()); if (obj) - DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(ct->_table[i].getPos()), + debugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(ct->_table[i].getPos()), _engine->_gamestate->_segMan->getObjectName(ct->_table[i].getPos()), obj->getVarCount(), obj->getMethodCount()); } @@ -1992,34 +1995,34 @@ bool Console::segmentInfo(int nr) { case SEG_TYPE_LISTS: { ListTable *lt = (ListTable *)mobj; - DebugPrintf("lists\n"); + debugPrintf("lists\n"); for (uint i = 0; i < lt->_table.size(); i++) if (lt->isValidEntry(i)) { - DebugPrintf(" [%04x]: ", i); + debugPrintf(" [%04x]: ", i); printList(&(lt->_table[i])); } } break; case SEG_TYPE_NODES: { - DebugPrintf("nodes (total %d)\n", (*(NodeTable *)mobj).entries_used); + debugPrintf("nodes (total %d)\n", (*(NodeTable *)mobj).entries_used); break; } case SEG_TYPE_HUNK: { HunkTable *ht = (HunkTable *)mobj; - DebugPrintf("hunk (total %d)\n", ht->entries_used); + debugPrintf("hunk (total %d)\n", ht->entries_used); for (uint i = 0; i < ht->_table.size(); i++) if (ht->isValidEntry(i)) { - DebugPrintf(" [%04x] %d bytes at %p, type=%s\n", + debugPrintf(" [%04x] %d bytes at %p, type=%s\n", i, ht->_table[i].size, ht->_table[i].mem, ht->_table[i].type); } } break; case SEG_TYPE_DYNMEM: { - DebugPrintf("dynmem (%s): %d bytes\n", + debugPrintf("dynmem (%s): %d bytes\n", (*(DynMem *)mobj)._description.c_str(), (*(DynMem *)mobj)._size); Common::hexdump((*(DynMem *)mobj)._buf, (*(DynMem *)mobj)._size, 16, 0); @@ -2028,28 +2031,28 @@ bool Console::segmentInfo(int nr) { #ifdef ENABLE_SCI32 case SEG_TYPE_STRING: - DebugPrintf("SCI32 strings\n"); + debugPrintf("SCI32 strings\n"); break; case SEG_TYPE_ARRAY: - DebugPrintf("SCI32 arrays\n"); + debugPrintf("SCI32 arrays\n"); break; #endif default : - DebugPrintf("Invalid type %d\n", mobj->getType()); + debugPrintf("Invalid type %d\n", mobj->getType()); break; } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } bool Console::cmdSegmentInfo(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Provides information on the specified segment(s)\n"); - DebugPrintf("Usage: %s <segment number>\n", argv[0]); - DebugPrintf("<segment number> can be a number, which shows the information of the segment with\n"); - DebugPrintf("the specified number, or \"all\" to show information on all active segments\n"); + debugPrintf("Provides information on the specified segment(s)\n"); + debugPrintf("Usage: %s <segment number>\n", argv[0]); + debugPrintf("<segment number> can be a number, which shows the information of the segment with\n"); + debugPrintf("the specified number, or \"all\" to show information on all active segments\n"); return true; } @@ -2061,7 +2064,7 @@ bool Console::cmdSegmentInfo(int argc, const char **argv) { if (!parseInteger(argv[1], segmentNr)) return true; if (!segmentInfo(segmentNr)) - DebugPrintf("Segment %04xh does not exist\n", segmentNr); + debugPrintf("Segment %04xh does not exist\n", segmentNr); } return true; @@ -2070,8 +2073,8 @@ bool Console::cmdSegmentInfo(int argc, const char **argv) { bool Console::cmdKillSegment(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Deletes the specified segment\n"); - DebugPrintf("Usage: %s <segment number>\n", argv[0]); + debugPrintf("Deletes the specified segment\n"); + debugPrintf("Usage: %s <segment number>\n", argv[0]); return true; } int segmentNumber; @@ -2084,13 +2087,13 @@ bool Console::cmdKillSegment(int argc, const char **argv) { bool Console::cmdShowMap(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Switches to one of the following screen maps\n"); - DebugPrintf("Usage: %s <screen map>\n", argv[0]); - DebugPrintf("Screen maps:\n"); - DebugPrintf("- 0: visual map\n"); - DebugPrintf("- 1: priority map\n"); - DebugPrintf("- 2: control map\n"); - DebugPrintf("- 3: display screen\n"); + debugPrintf("Switches to one of the following screen maps\n"); + debugPrintf("Usage: %s <screen map>\n", argv[0]); + debugPrintf("Screen maps:\n"); + debugPrintf("- 0: visual map\n"); + debugPrintf("- 1: priority map\n"); + debugPrintf("- 2: control map\n"); + debugPrintf("- 3: display screen\n"); return true; } @@ -2105,14 +2108,14 @@ bool Console::cmdShowMap(int argc, const char **argv) { break; default: - DebugPrintf("Map %d is not available.\n", map); + debugPrintf("Map %d is not available.\n", map); return true; } - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } bool Console::cmdSongLib(int argc, const char **argv) { - DebugPrintf("Song library:\n"); + debugPrintf("Song library:\n"); g_sci->_soundCmd->printPlayList(this); return true; @@ -2120,16 +2123,16 @@ bool Console::cmdSongLib(int argc, const char **argv) { bool Console::cmdSongInfo(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Shows information about a given song in the playlist\n"); - DebugPrintf("Usage: %s <song object>\n", argv[0]); + debugPrintf("Shows information about a given song in the playlist\n"); + debugPrintf("Usage: %s <song object>\n", argv[0]); return true; } reg_t addr; if (parse_reg_t(_engine->_gamestate, argv[1], &addr, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } @@ -2140,38 +2143,38 @@ bool Console::cmdSongInfo(int argc, const char **argv) { bool Console::cmdStartSound(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Adds the requested sound resource to the playlist, and starts playing it\n"); - DebugPrintf("Usage: %s <sound resource id>\n", argv[0]); + debugPrintf("Adds the requested sound resource to the playlist, and starts playing it\n"); + debugPrintf("Usage: %s <sound resource id>\n", argv[0]); return true; } int16 number = atoi(argv[1]); if (!_engine->getResMan()->testResource(ResourceId(kResourceTypeSound, number))) { - DebugPrintf("Unable to load this sound resource, most probably it has an equivalent audio resource (SCI1.1)\n"); + debugPrintf("Unable to load this sound resource, most probably it has an equivalent audio resource (SCI1.1)\n"); return true; } g_sci->_soundCmd->startNewSound(number); - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } bool Console::cmdToggleSound(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Plays or stops the specified sound in the playlist\n"); - DebugPrintf("Usage: %s <address> <state>\n", argv[0]); - DebugPrintf("Where:\n"); - DebugPrintf("- <address> is the address of the sound to play or stop.\n"); - DebugPrintf("- <state> is the new state (play or stop).\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Plays or stops the specified sound in the playlist\n"); + debugPrintf("Usage: %s <address> <state>\n", argv[0]); + debugPrintf("Where:\n"); + debugPrintf("- <address> is the address of the sound to play or stop.\n"); + debugPrintf("- <state> is the new state (play or stop).\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } reg_t id; if (parse_reg_t(_engine->_gamestate, argv[1], &id, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } @@ -2183,7 +2186,7 @@ bool Console::cmdToggleSound(int argc, const char **argv) { else if (newState == "stop") g_sci->_soundCmd->processStopSound(id, false); else - DebugPrintf("New state can either be 'play' or 'stop'"); + debugPrintf("New state can either be 'play' or 'stop'"); return true; } @@ -2191,40 +2194,40 @@ bool Console::cmdToggleSound(int argc, const char **argv) { bool Console::cmdStopAllSounds(int argc, const char **argv) { g_sci->_soundCmd->stopAllSounds(); - DebugPrintf("All sounds have been stopped\n"); + debugPrintf("All sounds have been stopped\n"); return true; } bool Console::cmdIsSample(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Tests whether a given sound resource is a PCM sample, \n"); - DebugPrintf("and displays information on it if it is.\n"); - DebugPrintf("Usage: %s <sample id>\n", argv[0]); + debugPrintf("Tests whether a given sound resource is a PCM sample, \n"); + debugPrintf("and displays information on it if it is.\n"); + debugPrintf("Usage: %s <sample id>\n", argv[0]); return true; } int16 number = atoi(argv[1]); if (!_engine->getResMan()->testResource(ResourceId(kResourceTypeSound, number))) { - DebugPrintf("Unable to load this sound resource, most probably it has an equivalent audio resource (SCI1.1)\n"); + debugPrintf("Unable to load this sound resource, most probably it has an equivalent audio resource (SCI1.1)\n"); return true; } SoundResource *soundRes = new SoundResource(number, _engine->getResMan(), _engine->_features->detectDoSoundType()); if (!soundRes) { - DebugPrintf("Not a sound resource!\n"); + debugPrintf("Not a sound resource!\n"); return true; } SoundResource::Track *track = soundRes->getDigitalTrack(); if (!track || track->digitalChannelNr == -1) { - DebugPrintf("Valid song, but not a sample.\n"); + debugPrintf("Valid song, but not a sample.\n"); delete soundRes; return true; } - DebugPrintf("Sample size: %d, sample rate: %d, channels: %d, digital channel number: %d\n", + debugPrintf("Sample size: %d, sample rate: %d, channels: %d, digital channel number: %d\n", track->digitalSampleSize, track->digitalSampleRate, track->channelCount, track->digitalChannelNr); delete soundRes; @@ -2232,7 +2235,7 @@ bool Console::cmdIsSample(int argc, const char **argv) { } bool Console::cmdGCInvoke(int argc, const char **argv) { - DebugPrintf("Performing garbage collection...\n"); + debugPrintf("Performing garbage collection...\n"); run_gc(_engine->_gamestate); return true; } @@ -2240,9 +2243,9 @@ bool Console::cmdGCInvoke(int argc, const char **argv) { bool Console::cmdGCObjects(int argc, const char **argv) { AddrSet *use_map = findAllActiveReferences(_engine->_gamestate); - DebugPrintf("Reachable object references (normalised):\n"); + debugPrintf("Reachable object references (normalised):\n"); for (AddrSet::iterator i = use_map->begin(); i != use_map->end(); ++i) { - DebugPrintf(" - %04x:%04x\n", PRINT_REG(i->_key)); + debugPrintf(" - %04x:%04x\n", PRINT_REG(i->_key)); } delete use_map; @@ -2252,93 +2255,93 @@ bool Console::cmdGCObjects(int argc, const char **argv) { bool Console::cmdGCShowReachable(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Prints all addresses directly reachable from the memory object specified as parameter.\n"); - DebugPrintf("Usage: %s <address>\n", argv[0]); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Prints all addresses directly reachable from the memory object specified as parameter.\n"); + debugPrintf("Usage: %s <address>\n", argv[0]); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } reg_t addr; if (parse_reg_t(_engine->_gamestate, argv[1], &addr, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } SegmentObj *mobj = _engine->_gamestate->_segMan->getSegmentObj(addr.getSegment()); if (!mobj) { - DebugPrintf("Unknown segment : %x\n", addr.getSegment()); + debugPrintf("Unknown segment : %x\n", addr.getSegment()); return 1; } - DebugPrintf("Reachable from %04x:%04x:\n", PRINT_REG(addr)); + debugPrintf("Reachable from %04x:%04x:\n", PRINT_REG(addr)); const Common::Array<reg_t> tmp = mobj->listAllOutgoingReferences(addr); for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it) if (it->getSegment()) - g_sci->getSciDebugger()->DebugPrintf(" %04x:%04x\n", PRINT_REG(*it)); + g_sci->getSciDebugger()->debugPrintf(" %04x:%04x\n", PRINT_REG(*it)); return true; } bool Console::cmdGCShowFreeable(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Prints all addresses freeable in the segment associated with the\n"); - DebugPrintf("given address (offset is ignored).\n"); - DebugPrintf("Usage: %s <address>\n", argv[0]); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Prints all addresses freeable in the segment associated with the\n"); + debugPrintf("given address (offset is ignored).\n"); + debugPrintf("Usage: %s <address>\n", argv[0]); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } reg_t addr; if (parse_reg_t(_engine->_gamestate, argv[1], &addr, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } SegmentObj *mobj = _engine->_gamestate->_segMan->getSegmentObj(addr.getSegment()); if (!mobj) { - DebugPrintf("Unknown segment : %x\n", addr.getSegment()); + debugPrintf("Unknown segment : %x\n", addr.getSegment()); return true; } - DebugPrintf("Freeable in segment %04x:\n", addr.getSegment()); + debugPrintf("Freeable in segment %04x:\n", addr.getSegment()); const Common::Array<reg_t> tmp = mobj->listAllDeallocatable(addr.getSegment()); for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it) if (it->getSegment()) - g_sci->getSciDebugger()->DebugPrintf(" %04x:%04x\n", PRINT_REG(*it)); + g_sci->getSciDebugger()->debugPrintf(" %04x:%04x\n", PRINT_REG(*it)); return true; } bool Console::cmdGCNormalize(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Prints the \"normal\" address of a given address,\n"); - DebugPrintf("i.e. the address we would free in order to free\n"); - DebugPrintf("the object associated with the original address.\n"); - DebugPrintf("Usage: %s <address>\n", argv[0]); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Prints the \"normal\" address of a given address,\n"); + debugPrintf("i.e. the address we would free in order to free\n"); + debugPrintf("the object associated with the original address.\n"); + debugPrintf("Usage: %s <address>\n", argv[0]); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } reg_t addr; if (parse_reg_t(_engine->_gamestate, argv[1], &addr, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } SegmentObj *mobj = _engine->_gamestate->_segMan->getSegmentObj(addr.getSegment()); if (!mobj) { - DebugPrintf("Unknown segment : %x\n", addr.getSegment()); + debugPrintf("Unknown segment : %x\n", addr.getSegment()); return true; } addr = mobj->findCanonicAddress(_engine->_gamestate->_segMan, addr); - DebugPrintf(" %04x:%04x\n", PRINT_REG(addr)); + debugPrintf(" %04x:%04x\n", PRINT_REG(addr)); return true; } @@ -2347,12 +2350,12 @@ bool Console::cmdVMVarlist(int argc, const char **argv) { EngineState *s = _engine->_gamestate; const char *varnames[] = {"global", "local", "temp", "param"}; - DebugPrintf("Addresses of variables in the VM:\n"); + debugPrintf("Addresses of variables in the VM:\n"); for (int i = 0; i < 4; i++) { - DebugPrintf("%s vars at %04x:%04x ", varnames[i], PRINT_REG(make_reg(s->variablesSegment[i], s->variables[i] - s->variablesBase[i]))); - DebugPrintf(" total %d", s->variablesMax[i]); - DebugPrintf("\n"); + debugPrintf("%s vars at %04x:%04x ", varnames[i], PRINT_REG(make_reg(s->variablesSegment[i], s->variables[i] - s->variablesBase[i]))); + debugPrintf(" total %d", s->variablesMax[i]); + debugPrintf("\n"); } return true; @@ -2360,12 +2363,12 @@ bool Console::cmdVMVarlist(int argc, const char **argv) { bool Console::cmdVMVars(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Displays or changes variables in the VM\n"); - DebugPrintf("Usage: %s <type> <varnum> [<value>]\n", argv[0]); - DebugPrintf("First parameter is either g(lobal), l(ocal), t(emp), p(aram) or a(cc).\n"); - DebugPrintf("Second parameter is the var number (not specified on acc)\n"); - DebugPrintf("Third parameter (if specified) is the value to set the variable to, in address form\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Displays or changes variables in the VM\n"); + debugPrintf("Usage: %s <type> <varnum> [<value>]\n", argv[0]); + debugPrintf("First parameter is either g(lobal), l(ocal), t(emp), p(aram) or a(cc).\n"); + debugPrintf("Second parameter is the var number (not specified on acc)\n"); + debugPrintf("Third parameter (if specified) is the value to set the variable to, in address form\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } @@ -2379,7 +2382,7 @@ bool Console::cmdVMVars(int argc, const char **argv) { const char *setValue = NULL; if (!varType_pre) { - DebugPrintf("Invalid variable type '%c'\n", *argv[1]); + debugPrintf("Invalid variable type '%c'\n", *argv[1]); return true; } @@ -2392,11 +2395,11 @@ bool Console::cmdVMVars(int argc, const char **argv) { case 3: { // for global, local, temp and param, we need an index if (argc < 3) { - DebugPrintf("Variable number must be specified for requested type\n"); + debugPrintf("Variable number must be specified for requested type\n"); return true; } if (argc > 4) { - DebugPrintf("Too many arguments\n"); + debugPrintf("Too many arguments\n"); return true; } @@ -2404,12 +2407,12 @@ bool Console::cmdVMVars(int argc, const char **argv) { return true; if (varIndex < 0) { - DebugPrintf("Variable number may not be negative\n"); + debugPrintf("Variable number may not be negative\n"); return true; } if (s->variablesMax[varType] <= varIndex) { - DebugPrintf("Maximum variable number for this type is %d (0x%x)\n", s->variablesMax[varType], s->variablesMax[varType]); + debugPrintf("Maximum variable number for this type is %d (0x%x)\n", s->variablesMax[varType], s->variablesMax[varType]); return true; } curValue = &s->variables[varType][varIndex]; @@ -2421,7 +2424,7 @@ bool Console::cmdVMVars(int argc, const char **argv) { case 4: // acc if (argc > 3) { - DebugPrintf("Too many arguments\n"); + debugPrintf("Too many arguments\n"); return true; } curValue = &s->r_acc; @@ -2435,16 +2438,16 @@ bool Console::cmdVMVars(int argc, const char **argv) { if (!setValue) { if (varType == 4) - DebugPrintf("%s == %04x:%04x", varNames[varType], PRINT_REG(*curValue)); + debugPrintf("%s == %04x:%04x", varNames[varType], PRINT_REG(*curValue)); else - DebugPrintf("%s var %d == %04x:%04x", varNames[varType], varIndex, PRINT_REG(*curValue)); + debugPrintf("%s var %d == %04x:%04x", varNames[varType], varIndex, PRINT_REG(*curValue)); printBasicVarInfo(*curValue); - DebugPrintf("\n"); + debugPrintf("\n"); } else { if (parse_reg_t(s, setValue, curValue, true)) { - DebugPrintf("Invalid value/address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); - DebugPrintf("Or pass a decimal or hexadecimal value directly (e.g. 12, 1Ah)\n"); + debugPrintf("Invalid value/address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Or pass a decimal or hexadecimal value directly (e.g. 12, 1Ah)\n"); return true; } } @@ -2453,13 +2456,13 @@ bool Console::cmdVMVars(int argc, const char **argv) { bool Console::cmdStack(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Lists the specified number of stack elements.\n"); - DebugPrintf("Usage: %s <elements>\n", argv[0]); + debugPrintf("Lists the specified number of stack elements.\n"); + debugPrintf("Usage: %s <elements>\n", argv[0]); return true; } if (_engine->_gamestate->_executionStack.empty()) { - DebugPrintf("No exec stack!"); + debugPrintf("No exec stack!"); return true; } @@ -2468,9 +2471,9 @@ bool Console::cmdStack(int argc, const char **argv) { for (int i = nr; i > 0; i--) { if ((xs.sp - xs.fp - i) == 0) - DebugPrintf("-- temp variables --\n"); + debugPrintf("-- temp variables --\n"); if (xs.sp - i >= _engine->_gamestate->stack_base) - DebugPrintf("ST:%04x = %04x:%04x\n", (unsigned)(xs.sp - i - _engine->_gamestate->stack_base), PRINT_REG(xs.sp[-i])); + debugPrintf("ST:%04x = %04x:%04x\n", (unsigned)(xs.sp - i - _engine->_gamestate->stack_base), PRINT_REG(xs.sp[-i])); } return true; @@ -2478,19 +2481,19 @@ bool Console::cmdStack(int argc, const char **argv) { bool Console::cmdValueType(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Determines the type of a value.\n"); - DebugPrintf("The type can be one of the following:\n"); - DebugPrintf("Invalid, list, object, reference or arithmetic\n"); - DebugPrintf("Usage: %s <address>\n", argv[0]); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Determines the type of a value.\n"); + debugPrintf("The type can be one of the following:\n"); + debugPrintf("Invalid, list, object, reference or arithmetic\n"); + debugPrintf("Usage: %s <address>\n", argv[0]); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } reg_t val; if (parse_reg_t(_engine->_gamestate, argv[1], &val, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } @@ -2498,22 +2501,22 @@ bool Console::cmdValueType(int argc, const char **argv) { switch (t) { case SIG_TYPE_LIST: - DebugPrintf("List"); + debugPrintf("List"); break; case SIG_TYPE_OBJECT: - DebugPrintf("Object"); + debugPrintf("Object"); break; case SIG_TYPE_REFERENCE: - DebugPrintf("Reference"); + debugPrintf("Reference"); break; case SIG_TYPE_INTEGER: - DebugPrintf("Integer"); + debugPrintf("Integer"); break; case SIG_TYPE_INTEGER | SIG_TYPE_NULL: - DebugPrintf("Null"); + debugPrintf("Null"); break; default: - DebugPrintf("Erroneous unknown type 0x%02x (%d decimal)\n", t, t); + debugPrintf("Erroneous unknown type 0x%02x (%d decimal)\n", t, t); } return true; @@ -2521,17 +2524,17 @@ bool Console::cmdValueType(int argc, const char **argv) { bool Console::cmdViewListNode(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Examines the list node at the given address.\n"); - DebugPrintf("Usage: %s <address>\n", argv[0]); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Examines the list node at the given address.\n"); + debugPrintf("Usage: %s <address>\n", argv[0]); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } reg_t addr; if (parse_reg_t(_engine->_gamestate, argv[1], &addr, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } @@ -2541,11 +2544,11 @@ bool Console::cmdViewListNode(int argc, const char **argv) { bool Console::cmdViewReference(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Examines an arbitrary reference.\n"); - DebugPrintf("Usage: %s <start address> [<end address>]\n", argv[0]); - DebugPrintf("Where <start address> is the starting address to examine\n"); - DebugPrintf("<end address>, if provided, is the address where examining ends at\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Examines an arbitrary reference.\n"); + debugPrintf("Usage: %s <start address> [<end address>]\n", argv[0]); + debugPrintf("Where <start address> is the starting address to examine\n"); + debugPrintf("<end address>, if provided, is the address where examining ends at\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } @@ -2553,15 +2556,15 @@ bool Console::cmdViewReference(int argc, const char **argv) { reg_t reg_end = NULL_REG; if (parse_reg_t(_engine->_gamestate, argv[1], ®, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } if (argc > 2) { if (parse_reg_t(_engine->_gamestate, argv[2], ®_end, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } } @@ -2570,15 +2573,15 @@ bool Console::cmdViewReference(int argc, const char **argv) { int filter; int found = 0; - DebugPrintf("%04x:%04x is of type 0x%x: ", PRINT_REG(reg), type_mask); + debugPrintf("%04x:%04x is of type 0x%x: ", PRINT_REG(reg), type_mask); if (reg.getSegment() == 0 && reg.getOffset() == 0) { - DebugPrintf("Null.\n"); + debugPrintf("Null.\n"); return true; } if (reg_end.getSegment() != reg.getSegment() && reg_end != NULL_REG) { - DebugPrintf("Ending segment different from starting segment. Assuming no bound on dump.\n"); + debugPrintf("Ending segment different from starting segment. Assuming no bound on dump.\n"); reg_end = NULL_REG; } @@ -2586,7 +2589,7 @@ bool Console::cmdViewReference(int argc, const char **argv) { int type = type_mask & filter; if (found && type) { - DebugPrintf("--- Alternatively, it could be a "); + debugPrintf("--- Alternatively, it could be a "); } @@ -2596,33 +2599,33 @@ bool Console::cmdViewReference(int argc, const char **argv) { case SIG_TYPE_LIST: { List *list = _engine->_gamestate->_segMan->lookupList(reg); - DebugPrintf("list\n"); + debugPrintf("list\n"); if (list) printList(list); else - DebugPrintf("Invalid list.\n"); + debugPrintf("Invalid list.\n"); } break; case SIG_TYPE_NODE: - DebugPrintf("list node\n"); + debugPrintf("list node\n"); printNode(reg); break; case SIG_TYPE_OBJECT: - DebugPrintf("object\n"); + debugPrintf("object\n"); printObject(reg); break; case SIG_TYPE_REFERENCE: { switch (_engine->_gamestate->_segMan->getSegmentType(reg.getSegment())) { #ifdef ENABLE_SCI32 case SEG_TYPE_STRING: { - DebugPrintf("SCI32 string\n"); + debugPrintf("SCI32 string\n"); const SciString *str = _engine->_gamestate->_segMan->lookupString(reg); Common::hexdump((const byte *) str->getRawData(), str->getSize(), 16, 0); break; } case SEG_TYPE_ARRAY: { - DebugPrintf("SCI32 array:\n"); + debugPrintf("SCI32 array:\n"); const SciArray<reg_t> *array = _engine->_gamestate->_segMan->lookupArray(reg); hexDumpReg(array->getRawData(), array->getSize(), 4, 0, true); break; @@ -2632,10 +2635,10 @@ bool Console::cmdViewReference(int argc, const char **argv) { const SegmentRef block = _engine->_gamestate->_segMan->dereference(reg); uint16 size = block.maxSize; - DebugPrintf("raw data\n"); + debugPrintf("raw data\n"); if (reg_end.getSegment() != 0 && (size < reg_end.getOffset() - reg.getOffset())) { - DebugPrintf("Block end out of bounds (size %d). Resetting.\n", size); + debugPrintf("Block end out of bounds (size %d). Resetting.\n", size); reg_end = NULL_REG; } @@ -2643,7 +2646,7 @@ bool Console::cmdViewReference(int argc, const char **argv) { size = reg_end.getOffset() - reg.getOffset(); if (reg_end.getSegment() != 0) - DebugPrintf("Block size less than or equal to %d\n", size); + debugPrintf("Block size less than or equal to %d\n", size); if (block.isRaw) Common::hexdump(block.raw, size, 16, 0); @@ -2654,14 +2657,14 @@ bool Console::cmdViewReference(int argc, const char **argv) { break; } case SIG_TYPE_INTEGER: - DebugPrintf("arithmetic value\n %d (%04x)\n", (int16) reg.getOffset(), reg.getOffset()); + debugPrintf("arithmetic value\n %d (%04x)\n", (int16) reg.getOffset(), reg.getOffset()); break; default: - DebugPrintf("unknown type %d.\n", type); + debugPrintf("unknown type %d.\n", type); } if (type) { - DebugPrintf("\n"); + debugPrintf("\n"); found = 1; } } @@ -2671,47 +2674,47 @@ bool Console::cmdViewReference(int argc, const char **argv) { bool Console::cmdViewObject(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Examines the object at the given address.\n"); - DebugPrintf("Usage: %s <address>\n", argv[0]); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Examines the object at the given address.\n"); + debugPrintf("Usage: %s <address>\n", argv[0]); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } reg_t addr; if (parse_reg_t(_engine->_gamestate, argv[1], &addr, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } - DebugPrintf("Information on the object at the given address:\n"); + debugPrintf("Information on the object at the given address:\n"); printObject(addr); return true; } bool Console::cmdViewActiveObject(int argc, const char **argv) { - DebugPrintf("Information on the currently active object or class:\n"); + debugPrintf("Information on the currently active object or class:\n"); printObject(_engine->_gamestate->xs->objp); return true; } bool Console::cmdViewAccumulatorObject(int argc, const char **argv) { - DebugPrintf("Information on the currently active object or class at the address indexed by the accumulator:\n"); + debugPrintf("Information on the currently active object or class at the address indexed by the accumulator:\n"); printObject(_engine->_gamestate->r_acc); return true; } bool Console::cmdScriptSteps(int argc, const char **argv) { - DebugPrintf("Number of executed SCI operations: %d\n", _engine->_gamestate->scriptStepCounter); + debugPrintf("Number of executed SCI operations: %d\n", _engine->_gamestate->scriptStepCounter); return true; } bool Console::cmdBacktrace(int argc, const char **argv) { - DebugPrintf("Call stack (current base: 0x%x):\n", _engine->_gamestate->executionStackBase); + debugPrintf("Call stack (current base: 0x%x):\n", _engine->_gamestate->executionStackBase); Common::List<ExecStack>::const_iterator iter; uint i = 0; @@ -2724,22 +2727,22 @@ bool Console::cmdBacktrace(int argc, const char **argv) { switch (call.type) { case EXEC_STACK_TYPE_CALL: // Normal function if (call.type == EXEC_STACK_TYPE_CALL) - DebugPrintf(" %x: script %d - ", i, (*(Script *)_engine->_gamestate->_segMan->_heap[call.addr.pc.getSegment()]).getScriptNumber()); + debugPrintf(" %x: script %d - ", i, (*(Script *)_engine->_gamestate->_segMan->_heap[call.addr.pc.getSegment()]).getScriptNumber()); if (call.debugSelector != -1) { - DebugPrintf("%s::%s(", objname, _engine->getKernel()->getSelectorName(call.debugSelector).c_str()); + debugPrintf("%s::%s(", objname, _engine->getKernel()->getSelectorName(call.debugSelector).c_str()); } else if (call.debugExportId != -1) { - DebugPrintf("export %d (", call.debugExportId); + debugPrintf("export %d (", call.debugExportId); } else if (call.debugLocalCallOffset != -1) { - DebugPrintf("call %x (", call.debugLocalCallOffset); + debugPrintf("call %x (", call.debugLocalCallOffset); } break; case EXEC_STACK_TYPE_KERNEL: // Kernel function - DebugPrintf(" %x:[%x] k%s(", i, call.debugOrigin, _engine->getKernel()->getKernelName(call.debugSelector).c_str()); + debugPrintf(" %x:[%x] k%s(", i, call.debugOrigin, _engine->getKernel()->getKernelName(call.debugSelector).c_str()); break; case EXEC_STACK_TYPE_VARSELECTOR: - DebugPrintf(" %x:[%x] vs%s %s::%s (", i, call.debugOrigin, (call.argc) ? "write" : "read", + debugPrintf(" %x:[%x] vs%s %s::%s (", i, call.debugOrigin, (call.argc) ? "write" : "read", objname, _engine->getKernel()->getSelectorName(call.debugSelector).c_str()); break; } @@ -2750,32 +2753,32 @@ bool Console::cmdBacktrace(int argc, const char **argv) { totalparamc = 16; for (paramc = 1; paramc <= totalparamc; paramc++) { - DebugPrintf("%04x:%04x", PRINT_REG(call.variables_argp[paramc])); + debugPrintf("%04x:%04x", PRINT_REG(call.variables_argp[paramc])); if (paramc < call.argc) - DebugPrintf(", "); + debugPrintf(", "); } if (call.argc > 16) - DebugPrintf("..."); + debugPrintf("..."); - DebugPrintf(")\n "); + debugPrintf(")\n "); if (call.debugOrigin != -1) - DebugPrintf("by %x ", call.debugOrigin); - DebugPrintf("obj@%04x:%04x", PRINT_REG(call.objp)); + debugPrintf("by %x ", call.debugOrigin); + debugPrintf("obj@%04x:%04x", PRINT_REG(call.objp)); if (call.type == EXEC_STACK_TYPE_CALL) { - DebugPrintf(" pc=%04x:%04x", PRINT_REG(call.addr.pc)); + debugPrintf(" pc=%04x:%04x", PRINT_REG(call.addr.pc)); if (call.sp == CALL_SP_CARRY) - DebugPrintf(" sp,fp:carry"); + debugPrintf(" sp,fp:carry"); else { - DebugPrintf(" sp=ST:%04x", (unsigned)(call.sp - _engine->_gamestate->stack_base)); - DebugPrintf(" fp=ST:%04x", (unsigned)(call.fp - _engine->_gamestate->stack_base)); + debugPrintf(" sp=ST:%04x", (unsigned)(call.sp - _engine->_gamestate->stack_base)); + debugPrintf(" fp=ST:%04x", (unsigned)(call.fp - _engine->_gamestate->stack_base)); } } else - DebugPrintf(" pc:none"); + debugPrintf(" pc:none"); - DebugPrintf(" argp:ST:%04x", (unsigned)(call.variables_argp - _engine->_gamestate->stack_base)); - DebugPrintf("\n"); + debugPrintf(" argp:ST:%04x", (unsigned)(call.variables_argp - _engine->_gamestate->stack_base)); + debugPrintf("\n"); } return true; @@ -2786,7 +2789,7 @@ bool Console::cmdTrace(int argc, const char **argv) { _debugState.runningStep = atoi(argv[1]) - 1; _debugState.debugging = true; - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } bool Console::cmdStepOver(int argc, const char **argv) { @@ -2794,14 +2797,14 @@ bool Console::cmdStepOver(int argc, const char **argv) { _debugState.seekLevel = _engine->_gamestate->_executionStack.size(); _debugState.debugging = true; - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } bool Console::cmdStepEvent(int argc, const char **argv) { _debugState.stopOnEvent = true; _debugState.debugging = true; - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } bool Console::cmdStepRet(int argc, const char **argv) { @@ -2809,13 +2812,13 @@ bool Console::cmdStepRet(int argc, const char **argv) { _debugState.seekLevel = _engine->_gamestate->_executionStack.size() - 1; _debugState.debugging = true; - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } bool Console::cmdStepGlobal(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Steps until the global variable with the specified index is modified.\n"); - DebugPrintf("Usage: %s <global variable index>\n", argv[0]); + debugPrintf("Steps until the global variable with the specified index is modified.\n"); + debugPrintf("Usage: %s <global variable index>\n", argv[0]); return true; } @@ -2823,7 +2826,7 @@ bool Console::cmdStepGlobal(int argc, const char **argv) { _debugState.seekSpecial = atoi(argv[1]); _debugState.debugging = true; - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } bool Console::cmdStepCallk(int argc, const char **argv) { @@ -2844,7 +2847,7 @@ bool Console::cmdStepCallk(int argc, const char **argv) { } if (callk_index == -1) { - DebugPrintf("Unknown kernel function '%s'\n", argv[1]); + debugPrintf("Unknown kernel function '%s'\n", argv[1]); return true; } } @@ -2856,16 +2859,16 @@ bool Console::cmdStepCallk(int argc, const char **argv) { } _debugState.debugging = true; - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } bool Console::cmdDisassemble(int argc, const char **argv) { if (argc < 3) { - DebugPrintf("Disassembles a method by name.\n"); - DebugPrintf("Usage: %s <object> <method> <options>\n", argv[0]); - DebugPrintf("Valid options are:\n"); - DebugPrintf(" bwt : Print byte/word tag\n"); - DebugPrintf(" bc : Print bytecode\n"); + debugPrintf("Disassembles a method by name.\n"); + debugPrintf("Usage: %s <object> <method> <options>\n", argv[0]); + debugPrintf("Valid options are:\n"); + debugPrintf(" bwt : Print byte/word tag\n"); + debugPrintf(" bc : Print bytecode\n"); return true; } @@ -2874,8 +2877,8 @@ bool Console::cmdDisassemble(int argc, const char **argv) { bool printBWTag = false; if (parse_reg_t(_engine->_gamestate, argv[1], &objAddr, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } @@ -2884,17 +2887,17 @@ bool Console::cmdDisassemble(int argc, const char **argv) { reg_t addr = NULL_REG; if (!obj) { - DebugPrintf("Not an object.\n"); + debugPrintf("Not an object.\n"); return true; } if (selectorId < 0) { - DebugPrintf("Not a valid selector name.\n"); + debugPrintf("Not a valid selector name.\n"); return true; } if (lookupSelector(_engine->_gamestate->_segMan, objAddr, selectorId, NULL, &addr) != kSelectorMethod) { - DebugPrintf("Not a method.\n"); + debugPrintf("Not a method.\n"); return true; } @@ -2924,12 +2927,12 @@ bool Console::cmdDisassemble(int argc, const char **argv) { bool Console::cmdDisassembleAddress(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Disassembles one or more commands.\n"); - DebugPrintf("Usage: %s [startaddr] <options>\n", argv[0]); - DebugPrintf("Valid options are:\n"); - DebugPrintf(" bwt : Print byte/word tag\n"); - DebugPrintf(" c<x> : Disassemble <x> bytes\n"); - DebugPrintf(" bc : Print bytecode\n"); + debugPrintf("Disassembles one or more commands.\n"); + debugPrintf("Usage: %s [startaddr] <options>\n", argv[0]); + debugPrintf("Valid options are:\n"); + debugPrintf(" bwt : Print byte/word tag\n"); + debugPrintf(" c<x> : Disassemble <x> bytes\n"); + debugPrintf(" bc : Print bytecode\n"); return true; } @@ -2940,8 +2943,8 @@ bool Console::cmdDisassembleAddress(int argc, const char **argv) { uint16 size; if (parse_reg_t(_engine->_gamestate, argv[1], &vpc, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } @@ -2956,7 +2959,7 @@ bool Console::cmdDisassembleAddress(int argc, const char **argv) { else if (toupper(argv[i][0]) == 'C') opCount = atoi(argv[i] + 1); else { - DebugPrintf("Invalid option '%s'\n", argv[i]); + debugPrintf("Invalid option '%s'\n", argv[i]); return true; } } @@ -2974,7 +2977,7 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) { Common::sort(resources.begin(), resources.end()); if (showFoundScripts) - DebugPrintf("%d scripts found, dissassembling...\n", resources.size()); + debugPrintf("%d scripts found, dissassembling...\n", resources.size()); int scriptSegment; Script *script; @@ -3023,7 +3026,7 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) { uint16 argc2 = opparams[1]; if (kFuncNum == kernelFuncNum) { - DebugPrintf("Called from script %d, object %s, method %s(%d) with %d bytes for arguments\n", + debugPrintf("Called from script %d, object %s, method %s(%d) with %d bytes for arguments\n", itr->getNumber(), objName, _engine->getKernel()->getSelectorName(obj->getFuncSelector(i)).c_str(), i, argc2); } @@ -3055,19 +3058,19 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) { bool Console::cmdFindKernelFunctionCall(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Finds the scripts and methods that call a specific kernel function.\n"); - DebugPrintf("Usage: %s <kernel function>\n", argv[0]); - DebugPrintf("Example: %s Display\n", argv[0]); - DebugPrintf("Special usage:\n"); - DebugPrintf("%s Dummy - find all calls to actual dummy functions " + debugPrintf("Finds the scripts and methods that call a specific kernel function.\n"); + debugPrintf("Usage: %s <kernel function>\n", argv[0]); + debugPrintf("Example: %s Display\n", argv[0]); + debugPrintf("Special usage:\n"); + debugPrintf("%s Dummy - find all calls to actual dummy functions " "(mapped to kDummy, and dummy in the kernel table). " "There shouldn't be calls to these (apart from a known " "one in Shivers)\n", argv[0]); - DebugPrintf("%s Unused - find all calls to unused functions (mapped to " + debugPrintf("%s Unused - find all calls to unused functions (mapped to " "kDummy - i.e. mapped in SSCI but dummy in ScummVM, thus " "they'll error out when called). Only debug scripts should " "be calling these\n", argv[0]); - DebugPrintf("%s Unmapped - find all calls to currently unmapped or " + debugPrintf("%s Unmapped - find all calls to currently unmapped or " "unimplemented functions (mapped to kStub/kStubNull)\n", argv[0]); return true; } @@ -3080,7 +3083,7 @@ bool Console::cmdFindKernelFunctionCall(int argc, const char **argv) { int kernelFuncNum = kernel->findKernelFuncPos(argv[1]); if (kernelFuncNum < 0) { - DebugPrintf("Invalid kernel function requested\n"); + debugPrintf("Invalid kernel function requested\n"); return true; } @@ -3090,7 +3093,7 @@ bool Console::cmdFindKernelFunctionCall(int argc, const char **argv) { // in the kernel table) for (uint i = 0; i < kernel->_kernelFuncs.size(); i++) { if (kernel->_kernelFuncs[i].function == &kDummy && kernel->getKernelName(i) == "Dummy") { - DebugPrintf("Searching for kernel function %d (%s)...\n", i, kernel->getKernelName(i).c_str()); + debugPrintf("Searching for kernel function %d (%s)...\n", i, kernel->getKernelName(i).c_str()); printKernelCallsFound(i, false); } } @@ -3100,7 +3103,7 @@ bool Console::cmdFindKernelFunctionCall(int argc, const char **argv) { // called) for (uint i = 0; i < kernel->_kernelFuncs.size(); i++) { if (kernel->_kernelFuncs[i].function == &kDummy && kernel->getKernelName(i) != "Dummy") { - DebugPrintf("Searching for kernel function %d (%s)...\n", i, kernel->getKernelName(i).c_str()); + debugPrintf("Searching for kernel function %d (%s)...\n", i, kernel->getKernelName(i).c_str()); printKernelCallsFound(i, false); } } @@ -3109,7 +3112,7 @@ bool Console::cmdFindKernelFunctionCall(int argc, const char **argv) { for (uint i = 0; i < kernel->_kernelFuncs.size(); i++) { if (kernel->_kernelFuncs[i].function == &kStub || kernel->_kernelFuncs[i].function == &kStubNull) { - DebugPrintf("Searching for kernel function %d (%s)...\n", i, kernel->getKernelName(i).c_str()); + debugPrintf("Searching for kernel function %d (%s)...\n", i, kernel->getKernelName(i).c_str()); printKernelCallsFound(i, false); } } @@ -3120,17 +3123,17 @@ bool Console::cmdFindKernelFunctionCall(int argc, const char **argv) { bool Console::cmdSend(int argc, const char **argv) { if (argc < 3) { - DebugPrintf("Sends a message to an object.\n"); - DebugPrintf("Usage: %s <object> <selector name> <param1> <param2> ... <paramn>\n", argv[0]); - DebugPrintf("Example: %s ?fooScript cue\n", argv[0]); + debugPrintf("Sends a message to an object.\n"); + debugPrintf("Usage: %s <object> <selector name> <param1> <param2> ... <paramn>\n", argv[0]); + debugPrintf("Example: %s ?fooScript cue\n", argv[0]); return true; } reg_t object; if (parse_reg_t(_engine->_gamestate, argv[1], &object, false)) { - DebugPrintf("Invalid address \"%s\" passed.\n", argv[1]); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address \"%s\" passed.\n", argv[1]); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } @@ -3138,20 +3141,20 @@ bool Console::cmdSend(int argc, const char **argv) { int selectorId = _engine->getKernel()->findSelector(selectorName); if (selectorId < 0) { - DebugPrintf("Unknown selector: \"%s\"\n", selectorName); + debugPrintf("Unknown selector: \"%s\"\n", selectorName); return true; } const Object *o = _engine->_gamestate->_segMan->getObject(object); if (o == NULL) { - DebugPrintf("Address \"%04x:%04x\" is not an object\n", PRINT_REG(object)); + debugPrintf("Address \"%04x:%04x\" is not an object\n", PRINT_REG(object)); return true; } SelectorType selector_type = lookupSelector(_engine->_gamestate->_segMan, object, selectorId, NULL, NULL); if (selector_type == kSelectorNone) { - DebugPrintf("Object does not support selector: \"%s\"\n", selectorName); + debugPrintf("Object does not support selector: \"%s\"\n", selectorName); return true; } @@ -3165,8 +3168,8 @@ bool Console::cmdSend(int argc, const char **argv) { stackframe[1] = make_reg(0, send_argc); for (int i = 0; i < send_argc; i++) { if (parse_reg_t(_engine->_gamestate, argv[3+i], &stackframe[2+i], false)) { - DebugPrintf("Invalid address \"%s\" passed.\n", argv[3+i]); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address \"%s\" passed.\n", argv[3+i]); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } } @@ -3184,7 +3187,7 @@ bool Console::cmdSend(int argc, const char **argv) { if (old_xstack != xstack) { _engine->_gamestate->_executionStackPosChanged = true; - DebugPrintf("Message scheduled for execution\n"); + debugPrintf("Message scheduled for execution\n"); // We call run_engine explictly so we can restore the value of r_acc // after execution. @@ -3194,7 +3197,7 @@ bool Console::cmdSend(int argc, const char **argv) { if (restore_acc) { // varselector read or message executed - DebugPrintf("Message completed. Value returned: %04x:%04x\n", PRINT_REG(_engine->_gamestate->r_acc)); + debugPrintf("Message completed. Value returned: %04x:%04x\n", PRINT_REG(_engine->_gamestate->r_acc)); _engine->_gamestate->r_acc = old_acc; } @@ -3205,14 +3208,14 @@ bool Console::cmdGo(int argc, const char **argv) { // CHECKME: is this necessary? _debugState.seeking = kDebugSeekNothing; - return Cmd_Exit(argc, argv); + return cmdExit(argc, argv); } bool Console::cmdLogKernel(int argc, const char **argv) { if (argc < 3) { - DebugPrintf("Logs calls to specified kernel function.\n"); - DebugPrintf("Usage: %s <kernel function/*> <on/off>\n", argv[0]); - DebugPrintf("Example: %s StrCpy on\n", argv[0]); + debugPrintf("Logs calls to specified kernel function.\n"); + debugPrintf("Usage: %s <kernel function/*> <on/off>\n", argv[0]); + debugPrintf("Example: %s StrCpy on\n", argv[0]); return true; } @@ -3222,14 +3225,14 @@ bool Console::cmdLogKernel(int argc, const char **argv) { else if (strcmp(argv[2], "off") == 0) logging = false; else { - DebugPrintf("2nd parameter must be either on or off\n"); + debugPrintf("2nd parameter must be either on or off\n"); return true; } if (g_sci->getKernel()->debugSetFunction(argv[1], logging, -1)) - DebugPrintf("Logging %s for k%s\n", logging ? "enabled" : "disabled", argv[1]); + debugPrintf("Logging %s for k%s\n", logging ? "enabled" : "disabled", argv[1]); else - DebugPrintf("Unknown kernel function %s\n", argv[1]); + debugPrintf("Unknown kernel function %s\n", argv[1]); return true; } @@ -3237,25 +3240,25 @@ bool Console::cmdBreakpointList(int argc, const char **argv) { int i = 0; int bpdata; - DebugPrintf("Breakpoint list:\n"); + debugPrintf("Breakpoint list:\n"); Common::List<Breakpoint>::const_iterator bp = _debugState._breakpoints.begin(); Common::List<Breakpoint>::const_iterator end = _debugState._breakpoints.end(); for (; bp != end; ++bp) { - DebugPrintf(" #%i: ", i); + debugPrintf(" #%i: ", i); switch (bp->type) { case BREAK_SELECTOREXEC: - DebugPrintf("Execute %s\n", bp->name.c_str()); + debugPrintf("Execute %s\n", bp->name.c_str()); break; case BREAK_SELECTORREAD: - DebugPrintf("Read %s\n", bp->name.c_str()); + debugPrintf("Read %s\n", bp->name.c_str()); break; case BREAK_SELECTORWRITE: - DebugPrintf("Write %s\n", bp->name.c_str()); + debugPrintf("Write %s\n", bp->name.c_str()); break; case BREAK_EXPORT: bpdata = bp->address; - DebugPrintf("Execute script %d, export %d\n", bpdata >> 16, bpdata & 0xFFFF); + debugPrintf("Execute script %d, export %d\n", bpdata >> 16, bpdata & 0xFFFF); break; } @@ -3263,16 +3266,16 @@ bool Console::cmdBreakpointList(int argc, const char **argv) { } if (!i) - DebugPrintf(" No breakpoints defined.\n"); + debugPrintf(" No breakpoints defined.\n"); return true; } bool Console::cmdBreakpointDelete(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Deletes a breakpoint with the specified index.\n"); - DebugPrintf("Usage: %s <breakpoint index>\n", argv[0]); - DebugPrintf("<index> * will remove all breakpoints\n"); + debugPrintf("Deletes a breakpoint with the specified index.\n"); + debugPrintf("Usage: %s <breakpoint index>\n", argv[0]); + debugPrintf("<index> * will remove all breakpoints\n"); return true; } @@ -3292,7 +3295,7 @@ bool Console::cmdBreakpointDelete(int argc, const char **argv) { } if (bp == end) { - DebugPrintf("Invalid breakpoint index %i\n", idx); + debugPrintf("Invalid breakpoint index %i\n", idx); return true; } @@ -3312,11 +3315,11 @@ bool Console::cmdBreakpointDelete(int argc, const char **argv) { bool Console::cmdBreakpointMethod(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Sets a breakpoint on execution of a specified method/selector.\n"); - DebugPrintf("Usage: %s <name>\n", argv[0]); - DebugPrintf("Example: %s ego::doit\n", argv[0]); - DebugPrintf("May also be used to set a breakpoint that applies whenever an object\n"); - DebugPrintf("of a specific type is touched: %s foo::\n", argv[0]); + debugPrintf("Sets a breakpoint on execution of a specified method/selector.\n"); + debugPrintf("Usage: %s <name>\n", argv[0]); + debugPrintf("Example: %s ego::doit\n", argv[0]); + debugPrintf("May also be used to set a breakpoint that applies whenever an object\n"); + debugPrintf("of a specific type is touched: %s foo::\n", argv[0]); return true; } @@ -3334,9 +3337,9 @@ bool Console::cmdBreakpointMethod(int argc, const char **argv) { bool Console::cmdBreakpointRead(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Sets a breakpoint on reading of a specified selector.\n"); - DebugPrintf("Usage: %s <name>\n", argv[0]); - DebugPrintf("Example: %s ego::view\n", argv[0]); + debugPrintf("Sets a breakpoint on reading of a specified selector.\n"); + debugPrintf("Usage: %s <name>\n", argv[0]); + debugPrintf("Example: %s ego::view\n", argv[0]); return true; } @@ -3351,9 +3354,9 @@ bool Console::cmdBreakpointRead(int argc, const char **argv) { bool Console::cmdBreakpointWrite(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Sets a breakpoint on writing of a specified selector.\n"); - DebugPrintf("Usage: %s <name>\n", argv[0]); - DebugPrintf("Example: %s ego::view\n", argv[0]); + debugPrintf("Sets a breakpoint on writing of a specified selector.\n"); + debugPrintf("Usage: %s <name>\n", argv[0]); + debugPrintf("Example: %s ego::view\n", argv[0]); return true; } @@ -3368,9 +3371,9 @@ bool Console::cmdBreakpointWrite(int argc, const char **argv) { bool Console::cmdBreakpointKernel(int argc, const char **argv) { if (argc < 3) { - DebugPrintf("Sets a breakpoint on execution of a kernel function.\n"); - DebugPrintf("Usage: %s <name> <on/off>\n", argv[0]); - DebugPrintf("Example: %s DrawPic on\n", argv[0]); + debugPrintf("Sets a breakpoint on execution of a kernel function.\n"); + debugPrintf("Usage: %s <name> <on/off>\n", argv[0]); + debugPrintf("Example: %s DrawPic on\n", argv[0]); return true; } @@ -3380,22 +3383,22 @@ bool Console::cmdBreakpointKernel(int argc, const char **argv) { else if (strcmp(argv[2], "off") == 0) breakpoint = false; else { - DebugPrintf("2nd parameter must be either on or off\n"); + debugPrintf("2nd parameter must be either on or off\n"); return true; } if (g_sci->getKernel()->debugSetFunction(argv[1], -1, breakpoint)) - DebugPrintf("Breakpoint %s for k%s\n", (breakpoint ? "enabled" : "disabled"), argv[1]); + debugPrintf("Breakpoint %s for k%s\n", (breakpoint ? "enabled" : "disabled"), argv[1]); else - DebugPrintf("Unknown kernel function %s\n", argv[1]); + debugPrintf("Unknown kernel function %s\n", argv[1]); return true; } bool Console::cmdBreakpointFunction(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Sets a breakpoint on the execution of the specified exported function.\n"); - DebugPrintf("Usage: %s <script number> <export number\n", argv[0]); + debugPrintf("Sets a breakpoint on the execution of the specified exported function.\n"); + debugPrintf("Usage: %s <script number> <export number\n", argv[0]); return true; } @@ -3415,21 +3418,21 @@ bool Console::cmdBreakpointFunction(int argc, const char **argv) { bool Console::cmdSfx01Header(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Dumps the header of a SCI01 song\n"); - DebugPrintf("Usage: %s <track>\n", argv[0]); + debugPrintf("Dumps the header of a SCI01 song\n"); + debugPrintf("Usage: %s <track>\n", argv[0]); return true; } Resource *song = _engine->getResMan()->findResource(ResourceId(kResourceTypeSound, atoi(argv[1])), 0); if (!song) { - DebugPrintf("Doesn't exist\n"); + debugPrintf("Doesn't exist\n"); return true; } uint32 offset = 0; - DebugPrintf("SCI01 song track mappings:\n"); + debugPrintf("SCI01 song track mappings:\n"); if (*song->data == 0xf0) // SCI1 priority spec offset = 8; @@ -3439,7 +3442,7 @@ bool Console::cmdSfx01Header(int argc, const char **argv) { while (song->data[offset] != 0xff) { byte device_id = song->data[offset]; - DebugPrintf("* Device %02x:\n", device_id); + debugPrintf("* Device %02x:\n", device_id); offset++; if (offset + 1 >= song->size) @@ -3461,12 +3464,12 @@ bool Console::cmdSfx01Header(int argc, const char **argv) { track_offset += 2; end = READ_LE_UINT16(song->data + offset + 2); - DebugPrintf(" - %04x -- %04x", track_offset, track_offset + end); + debugPrintf(" - %04x -- %04x", track_offset, track_offset + end); if (track_offset == 0xfe) - DebugPrintf(" (PCM data)\n"); + debugPrintf(" (PCM data)\n"); else - DebugPrintf(" (channel %d, special %d, %d playing notes, %d foo)\n", + debugPrintf(" (channel %d, special %d, %d playing notes, %d foo)\n", header1 & 0xf, header1 >> 4, header2 & 0xf, header2 >> 4); offset += 4; } @@ -3580,8 +3583,8 @@ static void midi_hexdump(byte *data, int size, int notational_offset) { bool Console::cmdSfx01Track(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Dumps a track of a SCI01 song\n"); - DebugPrintf("Usage: %s <track> <offset>\n", argv[0]); + debugPrintf("Dumps a track of a SCI01 song\n"); + debugPrintf("Usage: %s <track> <offset>\n", argv[0]); return true; } @@ -3590,7 +3593,7 @@ bool Console::cmdSfx01Track(int argc, const char **argv) { int offset = atoi(argv[2]); if (!song) { - DebugPrintf("Doesn't exist\n"); + debugPrintf("Doesn't exist\n"); return true; } @@ -3614,29 +3617,29 @@ bool Console::cmdQuit(int argc, const char **argv) { _debugState.runningStep = 0; } else { - DebugPrintf("%s [game] - exit gracefully\n", argv[0]); - DebugPrintf("%s now - exit ungracefully\n", argv[0]); + debugPrintf("%s [game] - exit gracefully\n", argv[0]); + debugPrintf("%s now - exit ungracefully\n", argv[0]); return true; } - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } bool Console::cmdAddresses(int argc, const char **argv) { - DebugPrintf("Address parameters may be passed in one of three forms:\n"); - DebugPrintf(" - ssss:oooo -- where 'ssss' denotes a segment and 'oooo' an offset.\n"); - DebugPrintf(" Example: \"a:c5\" would address something in segment 0xa at offset 0xc5.\n"); - DebugPrintf(" - &scr:oooo -- where 'scr' is a script number and oooo an offset within that script; will\n"); - DebugPrintf(" fail if the script is not currently loaded\n"); - DebugPrintf(" - $REG -- where 'REG' is one of 'PC', 'ACC', 'PREV' or 'OBJ': References the address\n"); - DebugPrintf(" indicated by the register of this name.\n"); - DebugPrintf(" - $REG+n (or -n) -- Like $REG, but modifies the offset part by a specific amount (which\n"); - DebugPrintf(" is specified in hexadecimal).\n"); - DebugPrintf(" - ?obj -- Looks up an object with the specified name, uses its address. This will abort if\n"); - DebugPrintf(" the object name is ambiguous; in that case, a list of addresses and indices is provided.\n"); - DebugPrintf(" ?obj.idx may be used to disambiguate 'obj' by the index 'idx'.\n"); - DebugPrintf(" Underscores are used as substitute characters for spaces in object names.\n"); - DebugPrintf(" For example, an object named \"Glass Jar\" can be accessed as \"Glass_Jar\".\n"); + debugPrintf("Address parameters may be passed in one of three forms:\n"); + debugPrintf(" - ssss:oooo -- where 'ssss' denotes a segment and 'oooo' an offset.\n"); + debugPrintf(" Example: \"a:c5\" would address something in segment 0xa at offset 0xc5.\n"); + debugPrintf(" - &scr:oooo -- where 'scr' is a script number and oooo an offset within that script; will\n"); + debugPrintf(" fail if the script is not currently loaded\n"); + debugPrintf(" - $REG -- where 'REG' is one of 'PC', 'ACC', 'PREV' or 'OBJ': References the address\n"); + debugPrintf(" indicated by the register of this name.\n"); + debugPrintf(" - $REG+n (or -n) -- Like $REG, but modifies the offset part by a specific amount (which\n"); + debugPrintf(" is specified in hexadecimal).\n"); + debugPrintf(" - ?obj -- Looks up an object with the specified name, uses its address. This will abort if\n"); + debugPrintf(" the object name is ambiguous; in that case, a list of addresses and indices is provided.\n"); + debugPrintf(" ?obj.idx may be used to disambiguate 'obj' by the index 'idx'.\n"); + debugPrintf(" Underscores are used as substitute characters for spaces in object names.\n"); + debugPrintf(" For example, an object named \"Glass Jar\" can be accessed as \"Glass_Jar\".\n"); return true; } @@ -3887,14 +3890,14 @@ bool Console::parseInteger(const char *argument, int &result) { // hexadecimal number result = strtol(argument, &endPtr, 16); if ((*endPtr != 0) && (*endPtr != 'h')) { - DebugPrintf("Invalid hexadecimal number '%s'\n", argument); + debugPrintf("Invalid hexadecimal number '%s'\n", argument); return false; } } else { // decimal number result = strtol(argument, &endPtr, 10); if (*endPtr != 0) { - DebugPrintf("Invalid decimal number '%s'\n", argument); + debugPrintf("Invalid decimal number '%s'\n", argument); return false; } } @@ -3912,57 +3915,57 @@ void Console::printBasicVarInfo(reg_t variable) { case SIG_TYPE_INTEGER: { uint16 content = variable.toUint16(); if (content >= 10) - DebugPrintf(" (%dd)", content); + debugPrintf(" (%dd)", content); break; } case SIG_TYPE_OBJECT: - DebugPrintf(" (object '%s')", segMan->getObjectName(variable)); + debugPrintf(" (object '%s')", segMan->getObjectName(variable)); break; case SIG_TYPE_REFERENCE: - DebugPrintf(" (reference)"); + debugPrintf(" (reference)"); break; case SIG_TYPE_NODE: - DebugPrintf(" (node)"); + debugPrintf(" (node)"); break; case SIG_TYPE_LIST: - DebugPrintf(" (list)"); + debugPrintf(" (list)"); break; case SIG_TYPE_UNINITIALIZED: - DebugPrintf(" (uninitialized)"); + debugPrintf(" (uninitialized)"); break; case SIG_TYPE_ERROR: - DebugPrintf(" (error)"); + debugPrintf(" (error)"); break; default: - DebugPrintf(" (??\?)"); + debugPrintf(" (??\?)"); } if (regType & SIG_IS_INVALID) - DebugPrintf(" IS INVALID!"); + debugPrintf(" IS INVALID!"); } void Console::printList(List *list) { reg_t pos = list->first; reg_t my_prev = NULL_REG; - DebugPrintf("\t<\n"); + debugPrintf("\t<\n"); while (!pos.isNull()) { Node *node; NodeTable *nt = (NodeTable *)_engine->_gamestate->_segMan->getSegment(pos.getSegment(), SEG_TYPE_NODES); if (!nt || !nt->isValidEntry(pos.getOffset())) { - DebugPrintf(" WARNING: %04x:%04x: Doesn't contain list node!\n", + debugPrintf(" WARNING: %04x:%04x: Doesn't contain list node!\n", PRINT_REG(pos)); return; } node = &(nt->_table[pos.getOffset()]); - DebugPrintf("\t%04x:%04x : %04x:%04x -> %04x:%04x\n", PRINT_REG(pos), PRINT_REG(node->key), PRINT_REG(node->value)); + debugPrintf("\t%04x:%04x : %04x:%04x -> %04x:%04x\n", PRINT_REG(pos), PRINT_REG(node->key), PRINT_REG(node->value)); if (my_prev != node->pred) - DebugPrintf(" WARNING: current node gives %04x:%04x as predecessor!\n", + debugPrintf(" WARNING: current node gives %04x:%04x as predecessor!\n", PRINT_REG(node->pred)); my_prev = pos; @@ -3970,9 +3973,9 @@ void Console::printList(List *list) { } if (my_prev != list->last) - DebugPrintf(" WARNING: Last node was expected to be %04x:%04x, was %04x:%04x!\n", + debugPrintf(" WARNING: Last node was expected to be %04x:%04x, was %04x:%04x!\n", PRINT_REG(list->last), PRINT_REG(my_prev)); - DebugPrintf("\t>\n"); + debugPrintf("\t>\n"); } int Console::printNode(reg_t addr) { @@ -3983,32 +3986,32 @@ int Console::printNode(reg_t addr) { List *list; if (!lt->isValidEntry(addr.getOffset())) { - DebugPrintf("Address does not contain a list\n"); + debugPrintf("Address does not contain a list\n"); return 1; } list = &(lt->_table[addr.getOffset()]); - DebugPrintf("%04x:%04x : first x last = (%04x:%04x, %04x:%04x)\n", PRINT_REG(addr), PRINT_REG(list->first), PRINT_REG(list->last)); + debugPrintf("%04x:%04x : first x last = (%04x:%04x, %04x:%04x)\n", PRINT_REG(addr), PRINT_REG(list->first), PRINT_REG(list->last)); } else { NodeTable *nt; Node *node; mobj = _engine->_gamestate->_segMan->getSegment(addr.getSegment(), SEG_TYPE_NODES); if (!mobj) { - DebugPrintf("Segment #%04x is not a list or node segment\n", addr.getSegment()); + debugPrintf("Segment #%04x is not a list or node segment\n", addr.getSegment()); return 1; } nt = (NodeTable *)mobj; if (!nt->isValidEntry(addr.getOffset())) { - DebugPrintf("Address does not contain a node\n"); + debugPrintf("Address does not contain a node\n"); return 1; } node = &(nt->_table[addr.getOffset()]); - DebugPrintf("%04x:%04x : prev x next = (%04x:%04x, %04x:%04x); maps %04x:%04x -> %04x:%04x\n", + debugPrintf("%04x:%04x : prev x next = (%04x:%04x, %04x:%04x); maps %04x:%04x -> %04x:%04x\n", PRINT_REG(addr), PRINT_REG(node->pred), PRINT_REG(node->succ), PRINT_REG(node->key), PRINT_REG(node->value)); } @@ -4022,44 +4025,44 @@ int Console::printObject(reg_t pos) { uint i; if (!obj) { - DebugPrintf("[%04x:%04x]: Not an object.", PRINT_REG(pos)); + debugPrintf("[%04x:%04x]: Not an object.", PRINT_REG(pos)); return 1; } // Object header - DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(pos), s->_segMan->getObjectName(pos), + debugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(pos), s->_segMan->getObjectName(pos), obj->getVarCount(), obj->getMethodCount()); if (!obj->isClass() && getSciVersion() != SCI_VERSION_3) var_container = s->_segMan->getObject(obj->getSuperClassSelector()); - DebugPrintf(" -- member variables:\n"); + debugPrintf(" -- member variables:\n"); for (i = 0; (uint)i < obj->getVarCount(); i++) { - DebugPrintf(" "); + debugPrintf(" "); if (var_container && i < var_container->getVarCount()) { uint16 varSelector = var_container->getVarSelector(i); - DebugPrintf("[%03x] %s = ", varSelector, _engine->getKernel()->getSelectorName(varSelector).c_str()); + debugPrintf("[%03x] %s = ", varSelector, _engine->getKernel()->getSelectorName(varSelector).c_str()); } else - DebugPrintf("p#%x = ", i); + debugPrintf("p#%x = ", i); reg_t val = obj->getVariable(i); - DebugPrintf("%04x:%04x", PRINT_REG(val)); + debugPrintf("%04x:%04x", PRINT_REG(val)); if (!val.getSegment()) - DebugPrintf(" (%d)", val.getOffset()); + debugPrintf(" (%d)", val.getOffset()); const Object *ref = s->_segMan->getObject(val); if (ref) - DebugPrintf(" (%s)", s->_segMan->getObjectName(val)); + debugPrintf(" (%s)", s->_segMan->getObjectName(val)); - DebugPrintf("\n"); + debugPrintf("\n"); } - DebugPrintf(" -- methods:\n"); + debugPrintf(" -- methods:\n"); for (i = 0; i < obj->getMethodCount(); i++) { reg_t fptr = obj->getFunction(i); - DebugPrintf(" [%03x] %s = %04x:%04x\n", obj->getFuncSelector(i), _engine->getKernel()->getSelectorName(obj->getFuncSelector(i)).c_str(), PRINT_REG(fptr)); + debugPrintf(" [%03x] %s = %04x:%04x\n", obj->getFuncSelector(i), _engine->getKernel()->getSelectorName(obj->getFuncSelector(i)).c_str(), PRINT_REG(fptr)); } if (s->_segMan->_heap[pos.getSegment()]->getType() == SEG_TYPE_SCRIPT) - DebugPrintf("\nOwner script: %d\n", s->_segMan->getScript(pos.getSegment())->getScriptNumber()); + debugPrintf("\nOwner script: %d\n", s->_segMan->getScript(pos.getSegment())->getScriptNumber()); return 0; } diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index 8c5f9be425..368b82cb93 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -4054,7 +4054,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { FANMADE("SCI Capture the Flag", "4cd679a51d93b8b27c6b38d81be24b8b", 432, "98ae1f6ed7b4c21f88addbf643dd1d2f", 147878), FANMADE("SCI Companion Template", "ad54d4f504086cd597aa2348d0aa3b09", 354, "6798b7b601ce8154c1d1bc0f0edcdd18", 113061), FANMADE("SCI Logging Demo", "615c30c1445ea9349847e8868312a674", 558, "2df6858526177612ef9473e7af5b31c6", 171012), -#ifdef 0 +#if 0 // Disabled as this requires network access to the Google Translate API, which is not available as OSystem has no network API. FANMADE("SCI Narration Demo", "731f4f2b726a13c153380af08da16591", 360, "38c80558fb942e8568f011d4a1a4af59", 109789), #endif diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index 59f741a254..cb81da2279 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -126,7 +126,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { // track left buttton clicks, if requested if (curEvent.type == SCI_EVENT_MOUSE_PRESS && curEvent.data == 1 && g_debug_track_mouse_clicks) { - g_sci->getSciDebugger()->DebugPrintf("Mouse clicked at %d, %d\n", + g_sci->getSciDebugger()->debugPrintf("Mouse clicked at %d, %d\n", mousePos.x, mousePos.y); } @@ -163,20 +163,20 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { // A SCI event occurred, and we have been asked to stop, so open the debug console Console *con = g_sci->getSciDebugger(); - con->DebugPrintf("SCI event occurred: "); + con->debugPrintf("SCI event occurred: "); switch (curEvent.type) { case SCI_EVENT_QUIT: - con->DebugPrintf("quit event\n"); + con->debugPrintf("quit event\n"); break; case SCI_EVENT_KEYBOARD: - con->DebugPrintf("keyboard event\n"); + con->debugPrintf("keyboard event\n"); break; case SCI_EVENT_MOUSE_RELEASE: case SCI_EVENT_MOUSE_PRESS: - con->DebugPrintf("mouse click event\n"); + con->debugPrintf("mouse click event\n"); break; default: - con->DebugPrintf("unknown or no event (event type %d)\n", curEvent.type); + con->debugPrintf("unknown or no event (event type %d)\n", curEvent.type); } con->attach(); diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index b4d245197b..8bbbd713a6 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -1218,7 +1218,7 @@ static const uint16 kq6CDPatchAudioTextSupportGirlInTheTower[] = { // Adds another button state for the text/audio button. We currently use the "speech" view for "dual" mode. // View 947, loop 9, cel 0+1 -> "text" // View 947, loop 8, cel 0+1 -> "speech" -// View 947, loop 12, cel 0+1 -> "dual" (TODO: inject our own 2 views for the new "dual" mode) +// View 947, loop 12, cel 0+1 -> "dual" (this view is injected by us into the game) // Applies to at least: PC-CD // Patched method: iconTextSwitch::show, iconTextSwitch::doit static const uint16 kq6CDSignatureAudioTextMenuSupport[] = { @@ -1595,6 +1595,86 @@ static const uint16 laurabow2CDPatchFixProblematicIconBar[] = { PATCH_END }; +// Opening/Closing the east door in the pterodactyl room doesn't +// check, if it's locked and will open/close the door internally +// even when it is. +// +// It will get wired shut later in the game by Laura Bow and will be +// "locked" because of this. We patch in a check for the locked +// state. We also add code, that will set the "locked" state +// in case our eastDoor-wired-global is set. This makes the locked +// state effectively persistent. +// +// Applies to at least: English PC-CD, English PC-Floppy +// Responsible method (CD): eastDoor::doVerb +// Responsible method (Floppy): eastDoor::<noname300> +// Fixes bug: #6458 (partly, see additional patch below) +static const uint16 laurabow2CDSignatureFixWiredEastDoor[] = { + 0x30, SIG_UINT16(0x0022), // bnt [skip hand action] + 0x67, SIG_ADDTOOFFSET(+1), // pTos CD: doorState, Floppy: state + 0x35, 0x00, // ldi 00 + 0x1a, // eq? + 0x31, 0x08, // bnt [close door code] + 0x78, // push1 + SIG_MAGICDWORD, + 0x39, 0x63, // pushi 63h + 0x45, 0x04, 0x02, // callb export000_4, 02 (sets door-bitflag) + 0x33, 0x06, // jmp [super-code] + 0x78, // push1 + 0x39, 0x63, // pushi 63h + 0x45, 0x03, 0x02, // callb export000_3, 02 (resets door-bitflag) + 0x38, SIG_ADDTOOFFSET(+2), // pushi CD: 011dh, Floppy: 012ch + 0x78, // push1 + 0x8f, 0x01, // lsp param[01] + 0x59, 0x02, // rest 02 + 0x57, SIG_ADDTOOFFSET(+1), 0x06, // super CD: LbDoor, Floppy: Door, 06 + 0x33, 0x0b, // jmp [ret] + SIG_END +}; + +static const uint16 laurabow2CDPatchFixWiredEastDoor[] = { + 0x31, 0x23, // bnt [skip hand action] (saves 1 byte) + 0x81, 97, // lag 97d (get our eastDoor-wired-global) + 0x31, 0x04, // bnt [skip setting locked property] + 0x35, 0x01, // ldi 01 + 0x65, 0x6a, // aTop locked (set eastDoor::locked to 1) + 0x63, 0x6a, // pToa locked (get eastDoor::locked) + 0x2f, 0x17, // bt [skip hand action] + 0x63, PATCH_GETORIGINALBYTE(+4), // pToa CD: doorState, Floppy: state + 0x78, // push1 + 0x39, 0x63, // pushi 63h + 0x2f, 0x05, // bt [close door code] + 0x45, 0x04, 0x02, // callb export000_4, 02 (sets door-bitflag) + 0x33, 0x0b, // jmp [super-code] + 0x45, 0x03, 0x02, // callb export000_3, 02 (resets door-bitflag) + 0x33, 0x06, // jmp [super-code] + PATCH_END +}; + +// We patch in code, so that our eastDoor-wired-global will get set to 1. +// This way the wired-state won't get lost when exiting room 430. +// +// Applies to at least: English PC-CD, English PC-Floppy +// Responsible method (CD): sWireItShut::changeState +// Responsible method (Floppy): sWireItShut::<noname144> +// Fixes bug: #6458 (partly, see additional patch above) +static const uint16 laurabow2SignatureRememberWiredEastDoor[] = { + SIG_MAGICDWORD, + 0x33, 0x27, // jmp [ret] + 0x3c, // dup + 0x35, 0x06, // ldi 06 + 0x1a, // eq? + 0x31, 0x21, // bnt [skip step] + SIG_END +}; + +static const uint16 laurabow2PatchRememberWiredEastDoor[] = { + PATCH_ADDTOOFFSET(+2), // skip jmp [ret] + 0x34, PATCH_UINT16(0x0001), // ldi 0001 + 0xa1, PATCH_UINT16(97), // sag 97d (set our eastDoor-wired-global) + PATCH_END +}; + // Laura Bow 2 CD resets the audio mode to speech on init/restart // We already sync the settings from ScummVM (see SciEngine::syncIngameAudioOptions()) // and this script code would make it impossible to see the intro using "dual" mode w/o using debugger command @@ -1617,7 +1697,7 @@ static const uint16 laurabow2CDPatchAudioTextSupportModeReset[] = { // That way it's possible to use a new "dual" mode view in the game menu // View 995, loop 13, cel 0 -> "text" // View 995, loop 13, cel 1 -> "speech" -// View 995, loop 13, cel 2 -> "dual" (TODO: inject our own view for the new "dual" mode) +// View 995, loop 13, cel 2 -> "dual" (this view is injected by us into the game) // Patched method: gcWin::open static const uint16 laurabow2CDSignatureAudioTextMenuSupport1[] = { SIG_MAGICDWORD, @@ -1636,7 +1716,6 @@ static const uint16 laurabow2CDPatchAudioTextMenuSupport1[] = { }; // Adds another button state for the text/audio button. We currently use the "speech" view for "dual" mode. -// TODO: inject our own 2 views for the new "dual" mode // Patched method: iconMode::doit static const uint16 laurabow2CDSignatureAudioTextMenuSupport2[] = { SIG_MAGICDWORD, @@ -1684,6 +1763,8 @@ static const uint16 laurabow2CDPatchAudioTextMenuSupport2[] = { static const SciScriptPatcherEntry laurabow2Signatures[] = { { true, 560, "CD: painting closing immediately", 1, laurabow2CDSignaturePaintingClosing, laurabow2CDPatchPaintingClosing }, { true, 0, "CD: fix problematic icon bar", 1, laurabow2CDSignatureFixProblematicIconBar, laurabow2CDPatchFixProblematicIconBar }, + { true, 430, "CD/Floppy: make wired east door persistent", 1, laurabow2SignatureRememberWiredEastDoor, laurabow2PatchRememberWiredEastDoor }, + { true, 430, "CD/Floppy: fix wired east door", 1, laurabow2CDSignatureFixWiredEastDoor, laurabow2CDPatchFixWiredEastDoor }, // King's Quest 6 and Laura Bow 2 share basic patches for audio + text support { false, 924, "CD: audio + text support 1", 1, kq6laurabow2CDSignatureAudioTextSupport1, kq6laurabow2CDPatchAudioTextSupport1 }, { false, 924, "CD: audio + text support 2", 1, kq6laurabow2CDSignatureAudioTextSupport2, kq6laurabow2CDPatchAudioTextSupport2 }, @@ -2373,11 +2454,91 @@ static const uint16 sq1vgaPatchEgoShowsCard[] = { PATCH_END }; +// The spider droid on planet Korona has a fixed movement speed, +// which is way faster than the default movement speed of ego. +// This means that the player would have to turn up movement speed, +// otherwise it will be impossible to escape it. +// We fix this issue by making the droid move a bit slower than ego +// does (relative to movement speed setting). +// +// Applies to at least: English PC floppy +// Responsible method: spider::doit +static const uint16 sq1vgaSignatureSpiderDroidTiming[] = { + SIG_MAGICDWORD, + 0x63, 0x4e, // pToa script + 0x30, SIG_UINT16(0x0005), // bnt [further method code] + 0x35, 0x00, // ldi 00 + 0x32, SIG_UINT16(0x0062), // jmp [super-call] + 0x38, SIG_UINT16(0x0088), // pushi 0088h (script) + 0x76, // push0 + 0x81, 0x02, // lag global[2] (current room) + 0x4a, 0x04, // send 04 (get [current room].script) + 0x30, SIG_UINT16(0x0005), // bnt [further method code] + 0x35, 0x00, // ldi 00 + 0x32, SIG_UINT16(0x0052), // jmp [super-call] + 0x89, 0xa6, // lsg global[a6] + 0x35, 0x01, // ldi 01 + 0x1a, // eq? + 0x30, SIG_UINT16(0x0012), // bnt [2nd code], in case global A6 <> 1 + 0x81, 0xb5, // lag global[b5] + 0x30, SIG_UINT16(0x000d), // bnt [2nd code], in case global B5 == 0 + 0x38, SIG_UINT16(0x008c), // pushi 008c + 0x78, // push1 + 0x72, SIG_UINT16(0x1cb6), // lofsa 1CB6 (moveToPath) + 0x36, // push + 0x54, 0x06, // self 06 + 0x32, SIG_UINT16(0x0038), // jmp [super-call] + 0x81, 0xb5, // lag global[B5] + 0x18, // not + 0x30, SIG_UINT16(0x0032), // bnt [super-call], in case global B5 <> 0 + SIG_END +}; // 58 bytes) + +static const uint16 sq1vgaPatchSpiderDroidTiming[] = { + 0x63, 0x4e, // pToa script + 0x2f, 0x68, // bt [super-call] + 0x38, PATCH_UINT16(0x0088), // pushi 0088 (script) + 0x76, // push0 + 0x81, 0x02, // lag global[2] (current room) + 0x4a, 0x04, // send 04 + 0x2f, 0x5e, // bt [super-call] + // --> 12 bytes saved + // new code + 0x38, PATCH_UINT16(0x0176), // pushi 0176 (egoMoveSpeed) + 0x76, // push0 + 0x81, 0x01, // lag global[1] + 0x4a, 0x04, // send 04 - sq1::egoMoveSpeed + 0x36, // push + 0x36, // push + 0x35, 0x03, // ldi 03 + 0x0c, // shr + 0x02, // add --> egoMoveSpeed + (egoMoveSpeed >> 3) + 0x39, 0x01, // push 01 (waste 1 byte) + 0x02, // add --> egoMoveSpeed++ + 0x65, 0x4c, // aTop cycleSpeed + 0x65, 0x5e, // aTop moveSpeed + // new code end + 0x89, 0xb5, // lsg global[B5] + 0x31, 0x13, // bnt [2nd code chunk] + 0x89, 0xa6, // lsg global[A6] + 0x35, 0x01, // ldi 01 + 0x1a, // eq? + 0x31, 0x3e, // bnt [super-call] + 0x38, PATCH_UINT16(0x008c), // pushi 008c + 0x78, // push1 + 0x72, PATCH_UINT16(0x1cb6), // lofsa moveToPath + 0x36, // push + 0x54, 0x06, // self 06 - spider::setScript(movePath) + 0x33, 0x32, // jmp [super-call] + // --> 9 bytes saved + PATCH_END +}; // script, description, signature patch static const SciScriptPatcherEntry sq1vgaSignatures[] = { { true, 45, "Ulence Flats: timepod graphic glitch", 1, sq1vgaSignatureUlenceFlatsTimepodGfxGlitch, sq1vgaPatchUlenceFlatsTimepodGfxGlitch }, { true, 58, "Sarien armory droid zapping ego first time", 1, sq1vgaSignatureEgoShowsCard, sq1vgaPatchEgoShowsCard }, + { true, 704, "spider droid timing issue", 1, sq1vgaSignatureSpiderDroidTiming, sq1vgaPatchSpiderDroidTiming }, SCI_SIGNATUREENTRY_TERMINATOR }; diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 44910058ef..f0157a6569 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -604,7 +604,7 @@ bool SciEngine::checkSelectorBreakpoint(BreakpointType breakpointType, reg_t sen Common::List<Breakpoint>::const_iterator bpIter; for (bpIter = _debugState._breakpoints.begin(); bpIter != _debugState._breakpoints.end(); ++bpIter) { if ((*bpIter).type == breakpointType && (*bpIter).name == methodName) { - _console->DebugPrintf("Break on %s (in [%04x:%04x])\n", methodName.c_str(), PRINT_REG(send_obj)); + _console->debugPrintf("Break on %s (in [%04x:%04x])\n", methodName.c_str(), PRINT_REG(send_obj)); _debugState.debugging = true; _debugState.breakpointWasHit = true; return true; @@ -620,7 +620,7 @@ bool SciEngine::checkExportBreakpoint(uint16 script, uint16 pubfunct) { Common::List<Breakpoint>::const_iterator bp; for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) { if (bp->type == BREAK_EXPORT && bp->address == bpaddress) { - _console->DebugPrintf("Break on script %d, export %d\n", script, pubfunct); + _console->debugPrintf("Break on script %d, export %d\n", script, pubfunct); _debugState.debugging = true; _debugState.breakpointWasHit = true; return true; @@ -666,12 +666,12 @@ void debugSelectorCall(reg_t send_obj, Selector selector, int argc, StackPtr arg reg_t selectorValue = *varp.getPointer(segMan); if (!argc && (activeBreakpointTypes & BREAK_SELECTORREAD)) { if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORREAD, send_obj, selector)) - con->DebugPrintf("Read from selector (%s:%s): %04x:%04x\n", + con->debugPrintf("Read from selector (%s:%s): %04x:%04x\n", objectName, selectorName, PRINT_REG(selectorValue)); } else if (argc && (activeBreakpointTypes & BREAK_SELECTORWRITE)) { if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORWRITE, send_obj, selector)) - con->DebugPrintf("Write to selector (%s:%s): change %04x:%04x to %04x:%04x\n", + con->debugPrintf("Write to selector (%s:%s): change %04x:%04x to %04x:%04x\n", objectName, selectorName, PRINT_REG(selectorValue), PRINT_REG(argp[1])); } @@ -690,13 +690,13 @@ void debugSelectorCall(reg_t send_obj, Selector selector, int argc, StackPtr arg if (true) { if (true) { #endif - con->DebugPrintf("%s::%s(", objectName, selectorName); + con->debugPrintf("%s::%s(", objectName, selectorName); for (int i = 0; i < argc; i++) { - con->DebugPrintf("%04x:%04x", PRINT_REG(argp[i+1])); + con->debugPrintf("%04x:%04x", PRINT_REG(argp[i+1])); if (i + 1 < argc) - con->DebugPrintf(", "); + con->debugPrintf(", "); } - con->DebugPrintf(") at %04x:%04x\n", PRINT_REG(funcp)); + con->debugPrintf(") at %04x:%04x\n", PRINT_REG(funcp)); } } break; diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index 73cd7240d3..7957ed6a55 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -726,7 +726,7 @@ void GfxAnimate::printAnimateList(Console *con) { Script *scr = _s->_segMan->getScriptIfLoaded(it->object.getSegment()); int16 scriptNo = scr ? scr->getScriptNumber() : -1; - con->DebugPrintf("%04x:%04x (%s), script %d, view %d (%d, %d), pal %d, " + con->debugPrintf("%04x:%04x (%s), script %d, view %d (%d, %d), pal %d, " "at %d, %d, scale %d, %d / %d (z: %d, prio: %d, shown: %d, signal: %d)\n", PRINT_REG(it->object), _s->_segMan->getObjectName(it->object), scriptNo, it->viewId, it->loopNo, it->celNo, it->paletteNo, diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index ffed7b596e..a322eb8e61 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -852,21 +852,21 @@ void GfxFrameout::printPlaneList(Console *con) { Common::Rect r = p.upscaledPlaneRect; Common::Rect cr = p.upscaledPlaneClipRect; - con->DebugPrintf("%04x:%04x (%s): prio %d, lastprio %d, offsetX %d, offsetY %d, pic %d, mirror %d, back %d\n", + con->debugPrintf("%04x:%04x (%s): prio %d, lastprio %d, offsetX %d, offsetY %d, pic %d, mirror %d, back %d\n", PRINT_REG(p.object), curPlaneName.c_str(), (int16)p.priority, (int16)p.lastPriority, p.planeOffsetX, p.planeOffsetY, p.pictureId, p.planePictureMirrored, p.planeBack); - con->DebugPrintf(" rect: (%d, %d, %d, %d), clip rect: (%d, %d, %d, %d)\n", + con->debugPrintf(" rect: (%d, %d, %d, %d), clip rect: (%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom, cr.left, cr.top, cr.right, cr.bottom); if (p.pictureId != 0xffff && p.pictureId != 0xfffe) { - con->DebugPrintf("Pictures:\n"); + con->debugPrintf("Pictures:\n"); for (PlanePictureList::iterator pictureIt = _planePictures.begin(); pictureIt != _planePictures.end(); pictureIt++) { if (pictureIt->object == p.object) { - con->DebugPrintf(" Picture %d: x %d, y %d\n", pictureIt->pictureId, pictureIt->startX, pictureIt->startY); + con->debugPrintf(" Picture %d: x %d, y %d\n", pictureIt->pictureId, pictureIt->startX, pictureIt->startY); } } } @@ -883,7 +883,7 @@ void GfxFrameout::printPlaneItemList(Console *con, reg_t planeObject) { Common::Rect icr = e->celRect; GuiResourceId picId = e->picture ? e->picture->getResourceId() : 0; - con->DebugPrintf("%d: %04x:%04x (%s), view %d, loop %d, cel %d, x %d, y %d, z %d, " + con->debugPrintf("%d: %04x:%04x (%s), view %d, loop %d, cel %d, x %d, y %d, z %d, " "signal %d, scale signal %d, scaleX %d, scaleY %d, rect (%d, %d, %d, %d), " "pic %d, picX %d, picY %d, visible %d\n", e->givenOrderNr, PRINT_REG(e->object), curItemName.c_str(), diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp index bd0b5f4081..56c63a7b12 100644 --- a/engines/sci/graphics/ports.cpp +++ b/engines/sci/graphics/ports.cpp @@ -748,7 +748,7 @@ void GfxPorts::printWindowList(Console *con) { for (PortList::const_iterator it = _windowList.begin(); it != _windowList.end(); ++it) { if ((*it)->isWindow()) { Window *wnd = ((Window *)*it); - con->DebugPrintf("%d: '%s' at %d, %d, (%d, %d, %d, %d), drawn: %d, style: %d\n", + con->debugPrintf("%d: '%s' at %d, %d, (%d, %d, %d, %d), drawn: %d, style: %d\n", wnd->id, wnd->title.c_str(), wnd->left, wnd->top, wnd->rect.left, wnd->rect.top, wnd->rect.right, wnd->rect.bottom, wnd->bDrawn, wnd->wndStyle); diff --git a/engines/sci/parser/grammar.cpp b/engines/sci/parser/grammar.cpp index ee0125b7c9..05764ba0a8 100644 --- a/engines/sci/parser/grammar.cpp +++ b/engines/sci/parser/grammar.cpp @@ -397,7 +397,7 @@ ParseRuleList *Vocabulary::buildGNF(bool verbose) { ntrules_nr = _vocab_rule_list_length(ntlist); if (verbose) - con->DebugPrintf("Starting with %d rules\n", ntrules_nr); + con->debugPrintf("Starting with %d rules\n", ntrules_nr); new_tlist = tlist; tlist = NULL; @@ -425,17 +425,17 @@ ParseRuleList *Vocabulary::buildGNF(bool verbose) { termrules = _vocab_rule_list_length(new_new_tlist); if (verbose) - con->DebugPrintf("After iteration #%d: %d new term rules\n", ++iterations, termrules); + con->debugPrintf("After iteration #%d: %d new term rules\n", ++iterations, termrules); } while (termrules && (iterations < 30)); freeRuleList(ntlist); if (verbose) { - con->DebugPrintf("\nGNF rules:\n"); + con->debugPrintf("\nGNF rules:\n"); tlist->print(); - con->DebugPrintf("%d allocd rules\n", _allocd_rules); - con->DebugPrintf("Freeing rule list...\n"); + con->debugPrintf("%d allocd rules\n", _allocd_rules); + con->debugPrintf("Freeing rule list...\n"); freeRuleList(tlist); return NULL; } @@ -548,7 +548,7 @@ int Vocabulary::parseGNF(const ResultWordListList &words, bool verbose) { ParseRuleList *seeker, *subseeker; if (verbose) - con->DebugPrintf("Adding word %d...\n", word); + con->debugPrintf("Adding word %d...\n", word); seeker = work; while (seeker) { @@ -562,7 +562,7 @@ int Vocabulary::parseGNF(const ResultWordListList &words, bool verbose) { if (reduced_rules == NULL) { freeRuleList(work); if (verbose) - con->DebugPrintf("No results.\n"); + con->debugPrintf("No results.\n"); return 1; } @@ -592,10 +592,10 @@ int Vocabulary::parseGNF(const ResultWordListList &words, bool verbose) { work = new_work; if (verbose) - con->DebugPrintf("Now at %d candidates\n", _vocab_rule_list_length(work)); + con->debugPrintf("Now at %d candidates\n", _vocab_rule_list_length(work)); if (work == NULL) { if (verbose) - con->DebugPrintf("No results.\n"); + con->debugPrintf("No results.\n"); return 1; } } @@ -603,9 +603,9 @@ int Vocabulary::parseGNF(const ResultWordListList &words, bool verbose) { results = work; if (verbose) { - con->DebugPrintf("All results (excluding the surrounding '(141 %03x' and ')'):\n", _parserBranches[0].id); + con->debugPrintf("All results (excluding the surrounding '(141 %03x' and ')'):\n", _parserBranches[0].id); results->print(); - con->DebugPrintf("\n"); + con->debugPrintf("\n"); } // now use the first result diff --git a/engines/sci/parser/vocabulary.cpp b/engines/sci/parser/vocabulary.cpp index 7c560dfaef..b4a223dcff 100644 --- a/engines/sci/parser/vocabulary.cpp +++ b/engines/sci/parser/vocabulary.cpp @@ -577,7 +577,7 @@ void Vocabulary::printSuffixes() const { strncpy(alt_buf, suf->alt_suffix, suf->alt_suffix_length); alt_buf[suf->alt_suffix_length] = 0; - con->DebugPrintf("%4d: (%03x) -%12s => -%12s (%03x)\n", i, suf->class_mask, word_buf, alt_buf, suf->result_class); + con->debugPrintf("%4d: (%03x) -%12s => -%12s (%03x)\n", i, suf->class_mask, word_buf, alt_buf, suf->result_class); ++i; } } @@ -588,14 +588,14 @@ void Vocabulary::printParserWords() const { int n = 0; for (WordMap::iterator i = _parserWords.begin(); i != _parserWords.end(); ++i) { for (ResultWordList::iterator j = i->_value.begin(); j != i->_value.end(); ++j) { - con->DebugPrintf("%4d: %03x [%03x] %20s |", n, j->_class, j->_group, i->_key.c_str()); + con->debugPrintf("%4d: %03x [%03x] %20s |", n, j->_class, j->_group, i->_key.c_str()); if (n % 3 == 0) - con->DebugPrintf("\n"); + con->debugPrintf("\n"); n++; } } - con->DebugPrintf("\n"); + con->debugPrintf("\n"); } void _vocab_recursive_ptree_dump(ParseTreeNode *tree, int blanks) { @@ -665,15 +665,15 @@ void Vocabulary::printParserNodes(int num) { Console *con = g_sci->getSciDebugger(); for (int i = 0; i < num; i++) { - con->DebugPrintf(" Node %03x: ", i); + con->debugPrintf(" Node %03x: ", i); if (_parserNodes[i].type == kParseTreeLeafNode) - con->DebugPrintf("Leaf: %04x\n", _parserNodes[i].value); + con->debugPrintf("Leaf: %04x\n", _parserNodes[i].value); else { // FIXME: Do we really want to print the *addresses* // of the left & right child? // Note that one or both may be zero pointers, so we can't just // print their values. - con->DebugPrintf("Branch: ->%p, ->%p\n", + con->debugPrintf("Branch: ->%p, ->%p\n", (const void *)_parserNodes[i].left, (const void *)_parserNodes[i].right); } @@ -694,11 +694,11 @@ int Vocabulary::parseNodes(int *i, int *pos, int type, int nr, int argc, const c return *pos; } if (type == kParseEndOfInput) { - con->DebugPrintf("Unbalanced parentheses\n"); + con->debugPrintf("Unbalanced parentheses\n"); return -1; } if (type == kParseClosingParenthesis) { - con->DebugPrintf("Syntax error at token %d\n", *i); + con->debugPrintf("Syntax error at token %d\n", *i); return -1; } @@ -735,7 +735,7 @@ int Vocabulary::parseNodes(int *i, int *pos, int type, int nr, int argc, const c const char *token = argv[(*i)++]; if (strcmp(token, ")")) - con->DebugPrintf("Expected ')' at token %d\n", *i); + con->debugPrintf("Expected ')' at token %d\n", *i); return oldPos; } diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 97675a140e..362cca699d 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -142,6 +142,8 @@ void SciMusic::init() { _driverLastChannel = _pMidiDrv->getLastChannel(); if (getSciVersion() <= SCI_VERSION_0_LATE) _globalReverb = _pMidiDrv->getReverb(); // Init global reverb for SCI0 + + _currentlyPlayingSample = NULL; } void SciMusic::miditimerCallback(void *p) { @@ -432,6 +434,17 @@ void SciMusic::soundPlay(MusicEntry *pSnd) { if (pSnd->pStreamAud) { if (!_pMixer->isSoundHandleActive(pSnd->hCurrentAud)) { + if ((_currentlyPlayingSample) && (_pMixer->isSoundHandleActive(_currentlyPlayingSample->hCurrentAud))) { + // Another sample is already playing, we have to stop that one + // SSCI is only able to play 1 sample at a time + // In Space Quest 5 room 250 the player is able to open the air-hatch and kill himself. + // In that situation the scripts are playing 2 samples at the same time and the first sample + // is not supposed to play. + // TODO: SSCI actually calls kDoAudio(play) internally, which stops other samples from being played + // but such a change isn't trivial, because we also handle Sound resources in here, that contain samples + _pMixer->stopHandle(_currentlyPlayingSample->hCurrentAud); + warning("kDoSound: sample already playing, old resource %d, new resource %d", _currentlyPlayingSample->resourceId, pSnd->resourceId); + } // Sierra SCI ignores volume set when playing samples via kDoSound // At least freddy pharkas/CD has a script bug that sets volume to 0 // when playing the "score" sample @@ -449,6 +462,8 @@ void SciMusic::soundPlay(MusicEntry *pSnd) { pSnd->pStreamAud, -1, _pMixer->kMaxChannelVolume, 0, DisposeAfterUse::NO); } + // Remember the sample, that is now playing + _currentlyPlayingSample = pSnd; } } else { if (pSnd->pMidiParser) { @@ -495,8 +510,11 @@ void SciMusic::soundStop(MusicEntry *pSnd) { pSnd->status = kSoundStopped; if (_soundVersion <= SCI_VERSION_0_LATE) pSnd->isQueued = false; - if (pSnd->pStreamAud) + if (pSnd->pStreamAud) { + if (_currentlyPlayingSample == pSnd) + _currentlyPlayingSample = NULL; _pMixer->stopHandle(pSnd->hCurrentAud); + } if (pSnd->pMidiParser) { Common::StackLock lock(_mutex); @@ -556,6 +574,10 @@ void SciMusic::soundKill(MusicEntry *pSnd) { _mutex.unlock(); if (pSnd->pStreamAud) { + if (_currentlyPlayingSample == pSnd) { + // Forget about this sound, in case it was currently playing + _currentlyPlayingSample = NULL; + } _pMixer->stopHandle(pSnd->hCurrentAud); delete pSnd->pStreamAud; pSnd->pStreamAud = NULL; @@ -666,7 +688,7 @@ void SciMusic::printPlayList(Console *con) { for (uint32 i = 0; i < _playList.size(); i++) { MusicEntry *song = _playList[i]; - con->DebugPrintf("%d: %04x:%04x (%s), resource id: %d, status: %s, %s type\n", + con->debugPrintf("%d: %04x:%04x (%s), resource id: %d, status: %s, %s type\n", i, PRINT_REG(song->soundObj), g_sci->getEngineState()->_segMan->getObjectName(song->soundObj), song->resourceId, musicStatus[song->status], @@ -683,26 +705,26 @@ void SciMusic::printSongInfo(reg_t obj, Console *con) { for (MusicList::iterator i = _playList.begin(); i != end; ++i) { MusicEntry *song = *i; if (song->soundObj == obj) { - con->DebugPrintf("Resource id: %d, status: %s\n", song->resourceId, musicStatus[song->status]); - con->DebugPrintf("dataInc: %d, hold: %d, loop: %d\n", song->dataInc, song->hold, song->loop); - con->DebugPrintf("signal: %d, priority: %d\n", song->signal, song->priority); - con->DebugPrintf("ticker: %d, volume: %d\n", song->ticker, song->volume); + con->debugPrintf("Resource id: %d, status: %s\n", song->resourceId, musicStatus[song->status]); + con->debugPrintf("dataInc: %d, hold: %d, loop: %d\n", song->dataInc, song->hold, song->loop); + con->debugPrintf("signal: %d, priority: %d\n", song->signal, song->priority); + con->debugPrintf("ticker: %d, volume: %d\n", song->ticker, song->volume); if (song->pMidiParser) { - con->DebugPrintf("Type: MIDI\n"); + con->debugPrintf("Type: MIDI\n"); if (song->soundRes) { SoundResource::Track *track = song->soundRes->getTrackByType(_pMidiDrv->getPlayId()); - con->DebugPrintf("Channels: %d\n", track->channelCount); + con->debugPrintf("Channels: %d\n", track->channelCount); } } else if (song->pStreamAud || song->pLoopStream) { - con->DebugPrintf("Type: digital audio (%s), sound active: %s\n", + con->debugPrintf("Type: digital audio (%s), sound active: %s\n", song->pStreamAud ? "non looping" : "looping", _pMixer->isSoundHandleActive(song->hCurrentAud) ? "yes" : "no"); if (song->soundRes) { - con->DebugPrintf("Sound resource information:\n"); + con->debugPrintf("Sound resource information:\n"); SoundResource::Track *track = song->soundRes->getTrackByType(_pMidiDrv->getPlayId()); if (track && track->digitalChannelNr != -1) { - con->DebugPrintf("Sample size: %d, sample rate: %d, channels: %d, digital channel number: %d\n", + con->debugPrintf("Sample size: %d, sample rate: %d, channels: %d, digital channel number: %d\n", track->digitalSampleSize, track->digitalSampleRate, track->channelCount, track->digitalChannelNr); } } @@ -712,7 +734,7 @@ void SciMusic::printSongInfo(reg_t obj, Console *con) { } } - con->DebugPrintf("Song object not found in playlist"); + con->debugPrintf("Song object not found in playlist"); } MusicEntry::MusicEntry() { @@ -1169,8 +1191,14 @@ ChannelRemapping *SciMusic::determineChannelMap() { int neededVoices = channel._voices; // do we have enough free voices? - // We only care for essential channels - if (map->_freeVoices < neededVoices && prio > 0) { + if (map->_freeVoices < neededVoices) { + // We only care for essential channels + if (prio > 0) { +#ifdef DEBUG_REMAP + debug(" not enough voices; need %d, have %d. Skipping this channel.", neededVoices, map->_freeVoices); +#endif + continue; + } do { int j = map->lowestPrio(); if (j == -1) { diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h index bfc542d2a5..6149bb799e 100644 --- a/engines/sci/sound/music.h +++ b/engines/sci/sound/music.h @@ -264,6 +264,8 @@ private: int _driverFirstChannel; int _driverLastChannel; + + MusicEntry *_currentlyPlayingSample; }; } // End of namespace Sci diff --git a/engines/scumm/debugger.cpp b/engines/scumm/debugger.cpp index a792d63149..2b718b2cfe 100644 --- a/engines/scumm/debugger.cpp +++ b/engines/scumm/debugger.cpp @@ -58,52 +58,63 @@ ScummDebugger::ScummDebugger(ScummEngine *s) _vm = s; // Register variables - DVar_Register("scumm_speed", &_vm->_fastMode, DVAR_BYTE, 0); - DVar_Register("scumm_room", &_vm->_currentRoom, DVAR_BYTE, 0); - DVar_Register("scumm_roomresource", &_vm->_roomResource, DVAR_INT, 0); - DVar_Register("scumm_vars", &_vm->_scummVars, DVAR_INTARRAY, _vm->_numVariables); + registerVar("scumm_speed", &_vm->_fastMode); + registerVar("scumm_room", &_vm->_currentRoom); + registerVar("scumm_roomresource", &_vm->_roomResource); + registerVar("scumm_vars", &_vm->_scummVars, _vm->_numVariables); // Register commands - DCmd_Register("continue", WRAP_METHOD(ScummDebugger, Cmd_Exit)); - DCmd_Register("restart", WRAP_METHOD(ScummDebugger, Cmd_Restart)); - - DCmd_Register("actor", WRAP_METHOD(ScummDebugger, Cmd_Actor)); - DCmd_Register("actors", WRAP_METHOD(ScummDebugger, Cmd_PrintActor)); - DCmd_Register("box", WRAP_METHOD(ScummDebugger, Cmd_PrintBox)); - DCmd_Register("matrix", WRAP_METHOD(ScummDebugger, Cmd_PrintBoxMatrix)); - DCmd_Register("camera", WRAP_METHOD(ScummDebugger, Cmd_Camera)); - DCmd_Register("room", WRAP_METHOD(ScummDebugger, Cmd_Room)); - DCmd_Register("objects", WRAP_METHOD(ScummDebugger, Cmd_PrintObjects)); - DCmd_Register("object", WRAP_METHOD(ScummDebugger, Cmd_Object)); - DCmd_Register("script", WRAP_METHOD(ScummDebugger, Cmd_Script)); - DCmd_Register("scr", WRAP_METHOD(ScummDebugger, Cmd_Script)); - DCmd_Register("scripts", WRAP_METHOD(ScummDebugger, Cmd_PrintScript)); - DCmd_Register("importres", WRAP_METHOD(ScummDebugger, Cmd_ImportRes)); + registerCmd("continue", WRAP_METHOD(ScummDebugger, cmdExit)); + registerCmd("restart", WRAP_METHOD(ScummDebugger, Cmd_Restart)); + + registerCmd("actor", WRAP_METHOD(ScummDebugger, Cmd_Actor)); + registerCmd("actors", WRAP_METHOD(ScummDebugger, Cmd_PrintActor)); + registerCmd("box", WRAP_METHOD(ScummDebugger, Cmd_PrintBox)); + registerCmd("matrix", WRAP_METHOD(ScummDebugger, Cmd_PrintBoxMatrix)); + registerCmd("camera", WRAP_METHOD(ScummDebugger, Cmd_Camera)); + registerCmd("room", WRAP_METHOD(ScummDebugger, Cmd_Room)); + registerCmd("objects", WRAP_METHOD(ScummDebugger, Cmd_PrintObjects)); + registerCmd("object", WRAP_METHOD(ScummDebugger, Cmd_Object)); + registerCmd("script", WRAP_METHOD(ScummDebugger, Cmd_Script)); + registerCmd("scr", WRAP_METHOD(ScummDebugger, Cmd_Script)); + registerCmd("scripts", WRAP_METHOD(ScummDebugger, Cmd_PrintScript)); + registerCmd("importres", WRAP_METHOD(ScummDebugger, Cmd_ImportRes)); if (_vm->_game.id == GID_LOOM) - DCmd_Register("drafts", WRAP_METHOD(ScummDebugger, Cmd_PrintDraft)); + registerCmd("drafts", WRAP_METHOD(ScummDebugger, Cmd_PrintDraft)); if (_vm->_game.id == GID_MONKEY && _vm->_game.platform == Common::kPlatformSegaCD) - DCmd_Register("passcode", WRAP_METHOD(ScummDebugger, Cmd_Passcode)); + registerCmd("passcode", WRAP_METHOD(ScummDebugger, Cmd_Passcode)); - DCmd_Register("loadgame", WRAP_METHOD(ScummDebugger, Cmd_LoadGame)); - DCmd_Register("savegame", WRAP_METHOD(ScummDebugger, Cmd_SaveGame)); + registerCmd("loadgame", WRAP_METHOD(ScummDebugger, Cmd_LoadGame)); + registerCmd("savegame", WRAP_METHOD(ScummDebugger, Cmd_SaveGame)); - DCmd_Register("level", WRAP_METHOD(ScummDebugger, Cmd_DebugLevel)); - DCmd_Register("debug", WRAP_METHOD(ScummDebugger, Cmd_Debug)); + registerCmd("debug", WRAP_METHOD(ScummDebugger, Cmd_Debug)); - DCmd_Register("show", WRAP_METHOD(ScummDebugger, Cmd_Show)); - DCmd_Register("hide", WRAP_METHOD(ScummDebugger, Cmd_Hide)); + registerCmd("show", WRAP_METHOD(ScummDebugger, Cmd_Show)); + registerCmd("hide", WRAP_METHOD(ScummDebugger, Cmd_Hide)); - DCmd_Register("imuse", WRAP_METHOD(ScummDebugger, Cmd_IMuse)); + registerCmd("imuse", WRAP_METHOD(ScummDebugger, Cmd_IMuse)); - DCmd_Register("resetcursors", WRAP_METHOD(ScummDebugger, Cmd_ResetCursors)); + registerCmd("resetcursors", WRAP_METHOD(ScummDebugger, Cmd_ResetCursors)); } ScummDebugger::~ScummDebugger() { // we need this destructor, even if it is empty, for __SYMBIAN32__ } +void ScummDebugger::preEnter() { +} + +void ScummDebugger::postEnter() { + // Runtime debug level change is dealt with by the base class "debuglevel" command + // but need to ensure that the _debugMode parameter is updated in sync. + _vm->_debugMode = (gDebugLevel >= 0); + // Boot params often need debugging switched on to work + if (_vm->_bootParam) + _vm->_debugMode = true; +} + /////////////////////////////////////////////////// // Now the fun stuff: @@ -117,51 +128,51 @@ bool ScummDebugger::Cmd_Restart(int argc, const char **argv) { bool ScummDebugger::Cmd_IMuse(int argc, const char **argv) { if (!_vm->_imuse && !_vm->_musicEngine) { - DebugPrintf("No iMuse engine is active.\n"); + debugPrintf("No iMuse engine is active.\n"); return true; } if (argc > 1) { if (!strcmp(argv[1], "panic")) { _vm->_musicEngine->stopAllSounds(); - DebugPrintf("AAAIIIEEEEEE!\n"); - DebugPrintf("Shutting down all music tracks\n"); + debugPrintf("AAAIIIEEEEEE!\n"); + debugPrintf("Shutting down all music tracks\n"); return true; } else if (!strcmp(argv[1], "play")) { if (argc > 2 && (!strcmp(argv[2], "random") || atoi(argv[2]) != 0)) { int sound = atoi(argv[2]); if (!strcmp(argv[2], "random")) { - DebugPrintf("Selecting from %d songs...\n", _vm->_numSounds); + debugPrintf("Selecting from %d songs...\n", _vm->_numSounds); sound = _vm->_rnd.getRandomNumber(_vm->_numSounds); } _vm->ensureResourceLoaded(rtSound, sound); _vm->_musicEngine->startSound(sound); - DebugPrintf("Attempted to start music %d.\n", sound); + debugPrintf("Attempted to start music %d.\n", sound); } else { - DebugPrintf("Specify a music resource # from 1-255.\n"); + debugPrintf("Specify a music resource # from 1-255.\n"); } return true; } else if (!strcmp(argv[1], "stop")) { if (argc > 2 && (!strcmp(argv[2], "all") || atoi(argv[2]) != 0)) { if (!strcmp(argv[2], "all")) { _vm->_musicEngine->stopAllSounds(); - DebugPrintf("Shutting down all music tracks.\n"); + debugPrintf("Shutting down all music tracks.\n"); } else { _vm->_musicEngine->stopSound(atoi(argv[2])); - DebugPrintf("Attempted to stop music %d.\n", atoi(argv[2])); + debugPrintf("Attempted to stop music %d.\n", atoi(argv[2])); } } else { - DebugPrintf("Specify a music resource # or \"all\".\n"); + debugPrintf("Specify a music resource # or \"all\".\n"); } return true; } } - DebugPrintf("Available iMuse commands:\n"); - DebugPrintf(" panic - Stop all music tracks\n"); - DebugPrintf(" play # - Play a music resource\n"); - DebugPrintf(" stop # - Stop a music resource\n"); + debugPrintf("Available iMuse commands:\n"); + debugPrintf(" panic - Stop all music tracks\n"); + debugPrintf(" play # - Play a music resource\n"); + debugPrintf(" stop # - Stop a music resource\n"); return true; } @@ -174,7 +185,7 @@ bool ScummDebugger::Cmd_Room(int argc, const char **argv) { _vm->_fullRedraw = true; return false; } else { - DebugPrintf("Current room: %d [%d] - use 'room <roomnum>' to switch\n", _vm->_currentRoom, _vm->_roomResource); + debugPrintf("Current room: %d [%d] - use 'room <roomnum>' to switch\n", _vm->_currentRoom, _vm->_roomResource); return true; } } @@ -189,7 +200,7 @@ bool ScummDebugger::Cmd_LoadGame(int argc, const char **argv) { return false; } - DebugPrintf("Syntax: loadgame <slotnum>\n"); + debugPrintf("Syntax: loadgame <slotnum>\n"); return true; } @@ -199,7 +210,7 @@ bool ScummDebugger::Cmd_SaveGame(int argc, const char **argv) { _vm->requestSave(slot, argv[2]); } else - DebugPrintf("Syntax: savegame <slotnum> <name>\n"); + debugPrintf("Syntax: savegame <slotnum> <name>\n"); return true; } @@ -207,18 +218,18 @@ bool ScummDebugger::Cmd_SaveGame(int argc, const char **argv) { bool ScummDebugger::Cmd_Show(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Syntax: show <parameter>\n"); + debugPrintf("Syntax: show <parameter>\n"); return true; } if (!strcmp(argv[1], "hex")) { _vm->_hexdumpScripts = true; - DebugPrintf("Script hex dumping on\n"); + debugPrintf("Script hex dumping on\n"); } else if (!strncmp(argv[1], "sta", 3)) { _vm->_showStack = 1; - DebugPrintf("Stack tracing on\n"); + debugPrintf("Stack tracing on\n"); } else { - DebugPrintf("Unknown show parameter '%s'\nParameters are 'hex' for hex dumping and 'sta' for stack tracing\n", argv[1]); + debugPrintf("Unknown show parameter '%s'\nParameters are 'hex' for hex dumping and 'sta' for stack tracing\n", argv[1]); } return true; } @@ -226,18 +237,18 @@ bool ScummDebugger::Cmd_Show(int argc, const char **argv) { bool ScummDebugger::Cmd_Hide(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Syntax: hide <parameter>\n"); + debugPrintf("Syntax: hide <parameter>\n"); return true; } if (!strcmp(argv[1], "hex")) { _vm->_hexdumpScripts = false; - DebugPrintf("Script hex dumping off\n"); + debugPrintf("Script hex dumping off\n"); } else if (!strncmp(argv[1], "sta", 3)) { _vm->_showStack = 0; - DebugPrintf("Stack tracing off\n"); + debugPrintf("Stack tracing off\n"); } else { - DebugPrintf("Unknown hide parameter '%s'\nParameters are 'hex' to turn off hex dumping and 'sta' to turn off stack tracing\n", argv[1]); + debugPrintf("Unknown hide parameter '%s'\nParameters are 'hex' to turn off hex dumping and 'sta' to turn off stack tracing\n", argv[1]); } return true; } @@ -246,7 +257,7 @@ bool ScummDebugger::Cmd_Script(int argc, const char** argv) { int scriptnum; if (argc < 2) { - DebugPrintf("Syntax: script <scriptnum> <command>\n"); + debugPrintf("Syntax: script <scriptnum> <command>\n"); return true; } @@ -254,7 +265,7 @@ bool ScummDebugger::Cmd_Script(int argc, const char** argv) { // FIXME: what is the max range on these? // if (scriptnum >= _vm->_numScripts) { - // DebugPrintf("Script number %d is out of range (range: 1 - %d)\n", scriptnum, _vm->_numScripts); + // debugPrintf("Script number %d is out of range (range: 1 - %d)\n", scriptnum, _vm->_numScripts); // return true; //} @@ -264,7 +275,7 @@ bool ScummDebugger::Cmd_Script(int argc, const char** argv) { _vm->runScript(scriptnum, 0, 0, 0); return false; } else { - DebugPrintf("Unknown script command '%s'\nUse <kill/stop | run/start> as command\n", argv[2]); + debugPrintf("Unknown script command '%s'\nUse <kill/stop | run/start> as command\n", argv[2]); } return true; @@ -276,7 +287,7 @@ bool ScummDebugger::Cmd_ImportRes(int argc, const char** argv) { int resnum; if (argc != 4) { - DebugPrintf("Syntax: importres <restype> <filename> <resnum>\n"); + debugPrintf("Syntax: importres <restype> <filename> <resnum>\n"); return true; } @@ -286,7 +297,7 @@ bool ScummDebugger::Cmd_ImportRes(int argc, const char** argv) { if (!strncmp(argv[1], "scr", 3)) { file.open(argv[2]); if (file.isOpen() == false) { - DebugPrintf("Could not open file %s\n", argv[2]); + debugPrintf("Could not open file %s\n", argv[2]); return true; } if (_vm->_game.features & GF_SMALL_HEADER) { @@ -307,25 +318,25 @@ bool ScummDebugger::Cmd_ImportRes(int argc, const char** argv) { file.read(_vm->_res->createResource(rtScript, resnum, size), size); } else - DebugPrintf("Unknown importres type '%s'\n", argv[1]); + debugPrintf("Unknown importres type '%s'\n", argv[1]); return true; } bool ScummDebugger::Cmd_PrintScript(int argc, const char **argv) { int i; ScriptSlot *ss = _vm->vm.slot; - DebugPrintf("+-----------------------------------+\n"); - DebugPrintf("|# | num|offst|sta|typ|fr|rec|fc|cut|\n"); - DebugPrintf("+--+----+-----+---+---+--+---+--+---+\n"); + debugPrintf("+-----------------------------------+\n"); + debugPrintf("|# | num|offst|sta|typ|fr|rec|fc|cut|\n"); + debugPrintf("+--+----+-----+---+---+--+---+--+---+\n"); for (i = 0; i < NUM_SCRIPT_SLOT; i++, ss++) { if (ss->number) { - DebugPrintf("|%2d|%4d|%05x|%3d|%3d|%2d|%3d|%2d|%3d|\n", + debugPrintf("|%2d|%4d|%05x|%3d|%3d|%2d|%3d|%2d|%3d|\n", i, ss->number, ss->offs, ss->status, ss->where, ss->freezeResistant, ss->recursive, ss->freezeCount, ss->cutsceneOverride); } } - DebugPrintf("+-----------------------------------+\n"); + debugPrintf("+-----------------------------------+\n"); return true; } @@ -336,13 +347,13 @@ bool ScummDebugger::Cmd_Actor(int argc, const char **argv) { int value = 0, value2 = 0; if (argc < 3) { - DebugPrintf("Syntax: actor <actornum> <command> <parameter>\n"); + debugPrintf("Syntax: actor <actornum> <command> <parameter>\n"); return true; } actnum = atoi(argv[1]); if (actnum >= _vm->_numActors) { - DebugPrintf("Actor %d is out of range (range: 1 - %d)\n", actnum, _vm->_numActors); + debugPrintf("Actor %d is out of range (range: 1 - %d)\n", actnum, _vm->_numActors); return true; } @@ -354,43 +365,43 @@ bool ScummDebugger::Cmd_Actor(int argc, const char **argv) { if (!strcmp(argv[2], "animvar")) { a->setAnimVar(value, value2); - DebugPrintf("Actor[%d].animVar[%d] = %d\n", actnum, value, a->getAnimVar(value)); + debugPrintf("Actor[%d].animVar[%d] = %d\n", actnum, value, a->getAnimVar(value)); } else if (!strcmp(argv[2], "anim")) { a->animateActor(value); - DebugPrintf("Actor[%d].animateActor(%d)\n", actnum, value); + debugPrintf("Actor[%d].animateActor(%d)\n", actnum, value); } else if (!strcmp(argv[2], "ignoreboxes")) { a->_ignoreBoxes = (value > 0); - DebugPrintf("Actor[%d].ignoreBoxes = %d\n", actnum, a->_ignoreBoxes); + debugPrintf("Actor[%d].ignoreBoxes = %d\n", actnum, a->_ignoreBoxes); } else if (!strcmp(argv[2], "x")) { a->putActor(value, a->getRealPos().y); - DebugPrintf("Actor[%d].x = %d\n", actnum, a->getRealPos().x); + debugPrintf("Actor[%d].x = %d\n", actnum, a->getRealPos().x); _vm->_fullRedraw = true; } else if (!strcmp(argv[2], "y")) { a->putActor(a->getRealPos().x, value); - DebugPrintf("Actor[%d].y = %d\n", actnum, a->getRealPos().y); + debugPrintf("Actor[%d].y = %d\n", actnum, a->getRealPos().y); _vm->_fullRedraw = true; } else if (!strcmp(argv[2], "_elevation")) { a->setElevation(value); - DebugPrintf("Actor[%d]._elevation = %d\n", actnum, a->getElevation()); + debugPrintf("Actor[%d]._elevation = %d\n", actnum, a->getElevation()); _vm->_fullRedraw = true; } else if (!strcmp(argv[2], "costume")) { if (value >= (int)_vm->_res->_types[rtCostume].size()) - DebugPrintf("Costume not changed as %d exceeds max of %d\n", value, _vm->_res->_types[rtCostume].size()); + debugPrintf("Costume not changed as %d exceeds max of %d\n", value, _vm->_res->_types[rtCostume].size()); else { a->setActorCostume(value); _vm->_fullRedraw = true; - DebugPrintf("Actor[%d].costume = %d\n", actnum, a->_costume); + debugPrintf("Actor[%d].costume = %d\n", actnum, a->_costume); } } else if (!strcmp(argv[2], "name")) { - DebugPrintf("Name of actor %d: %s\n", actnum, + debugPrintf("Name of actor %d: %s\n", actnum, _vm->getObjOrActorName(_vm->actorToObj(actnum))); } else if (!strcmp(argv[2], "condmask")) { if (argc > 3) { a->_heCondMask = value; } - DebugPrintf("Actor[%d]._heCondMask = 0x%X\n", actnum, a->_heCondMask); + debugPrintf("Actor[%d]._heCondMask = 0x%X\n", actnum, a->_heCondMask); } else { - DebugPrintf("Unknown actor command '%s'\nUse <ignoreboxes |costume> as command\n", argv[2]); + debugPrintf("Unknown actor command '%s'\nUse <ignoreboxes |costume> as command\n", argv[2]); } return true; @@ -400,40 +411,40 @@ bool ScummDebugger::Cmd_PrintActor(int argc, const char **argv) { int i; Actor *a; - DebugPrintf("+---------------------------------------------------------------+\n"); - DebugPrintf("|# | x | y | w | h |elev|cos|box|mov| zp|frm|scl|dir| cls |\n"); - DebugPrintf("+--+----+----+---+---+----+---+---+---+---+---+---+---+---------+\n"); + debugPrintf("+---------------------------------------------------------------+\n"); + debugPrintf("|# | x | y | w | h |elev|cos|box|mov| zp|frm|scl|dir| cls |\n"); + debugPrintf("+--+----+----+---+---+----+---+---+---+---+---+---+---+---------+\n"); for (i = 1; i < _vm->_numActors; i++) { a = _vm->_actors[i]; if (a->_visible) - DebugPrintf("|%2d|%4d|%4d|%3d|%3d|%4d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|$%08x|\n", + debugPrintf("|%2d|%4d|%4d|%3d|%3d|%4d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|$%08x|\n", a->_number, a->getRealPos().x, a->getRealPos().y, a->_width, a->_bottom - a->_top, a->getElevation(), a->_costume, a->_walkbox, a->_moving, a->_forceClip, a->_frame, a->_scalex, a->getFacing(), _vm->_classData[a->_number]); } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } bool ScummDebugger::Cmd_PrintObjects(int argc, const char **argv) { int i; ObjectData *o; - DebugPrintf("Objects in current room\n"); - DebugPrintf("+---------------------------------+------------+\n"); - DebugPrintf("|num | x | y |width|height|state|fl| cls |\n"); - DebugPrintf("+----+----+----+-----+------+-----+--+---------+\n"); + debugPrintf("Objects in current room\n"); + debugPrintf("+---------------------------------+------------+\n"); + debugPrintf("|num | x | y |width|height|state|fl| cls |\n"); + debugPrintf("+----+----+----+-----+------+-----+--+---------+\n"); for (i = 1; i < _vm->_numLocalObjects; i++) { o = &(_vm->_objs[i]); if (o->obj_nr == 0) continue; int classData = (_vm->_game.version != 0 ? _vm->_classData[o->obj_nr] : 0); - DebugPrintf("|%4d|%4d|%4d|%5d|%6d|%5d|%2d|$%08x|\n", + debugPrintf("|%4d|%4d|%4d|%5d|%6d|%5d|%2d|$%08x|\n", o->obj_nr, o->x_pos, o->y_pos, o->width, o->height, o->state, o->fl_object_index, classData); } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } @@ -443,13 +454,13 @@ bool ScummDebugger::Cmd_Object(int argc, const char **argv) { int obj; if (argc < 3) { - DebugPrintf("Syntax: object <objectnum> <command> <parameter>\n"); + debugPrintf("Syntax: object <objectnum> <command> <parameter>\n"); return true; } obj = atoi(argv[1]); if (_vm->_game.version != 0 && obj >= _vm->_numGlobalObjects) { - DebugPrintf("Object %d is out of range (range: 1 - %d)\n", obj, _vm->_numGlobalObjects); + debugPrintf("Object %d is out of range (range: 1 - %d)\n", obj, _vm->_numGlobalObjects); return true; } @@ -479,12 +490,12 @@ bool ScummDebugger::Cmd_Object(int argc, const char **argv) { //is BgNeedsRedraw enough? _vm->_bgNeedsRedraw = true; } else { - DebugPrintf("State of object %d: %d\n", obj, _vm->getState(obj)); + debugPrintf("State of object %d: %d\n", obj, _vm->getState(obj)); } } else if (!strcmp(argv[2], "name")) { - DebugPrintf("Name of object %d: %s\n", obj, _vm->getObjOrActorName(obj)); + debugPrintf("Name of object %d: %s\n", obj, _vm->getObjOrActorName(obj)); } else { - DebugPrintf("Unknown object command '%s'\nUse <pickup | state | name> as command\n", argv[2]); + debugPrintf("Unknown object command '%s'\nUse <pickup | state | name> as command\n", argv[2]); } return true; @@ -495,9 +506,9 @@ bool ScummDebugger::Cmd_Debug(int argc, const char **argv) { // No parameters given: Print out a list of all channels and their status if (argc <= 1) { - DebugPrintf("Available debug channels:\n"); + debugPrintf("Available debug channels:\n"); for (Common::DebugManager::DebugChannelList::const_iterator i = lvls.begin(); i != lvls.end(); ++i) { - DebugPrintf("%c%s - %s (%s)\n", i->enabled ? '+' : ' ', + debugPrintf("%c%s - %s (%s)\n", i->enabled ? '+' : ' ', i->name.c_str(), i->description.c_str(), i->enabled ? "enabled" : "disabled"); } @@ -513,39 +524,18 @@ bool ScummDebugger::Cmd_Debug(int argc, const char **argv) { } if (result) { - DebugPrintf("%s %s\n", (argv[1][0] == '+') ? "Enabled" : "Disabled", argv[1] + 1); + debugPrintf("%s %s\n", (argv[1][0] == '+') ? "Enabled" : "Disabled", argv[1] + 1); } else { - DebugPrintf("Usage: debug [+CHANNEL|-CHANNEL]\n"); - DebugPrintf("Enables or disables the given debug channel.\n"); - DebugPrintf("When used without parameters, lists all available debug channels and their status.\n"); - } - - return true; -} - -bool ScummDebugger::Cmd_DebugLevel(int argc, const char **argv) { - if (argc == 1) { - if (_vm->_debugMode == false) - DebugPrintf("Debugging is not enabled at this time\n"); - else - DebugPrintf("Debugging is currently set at level %d\n", gDebugLevel); - } else { // set level - gDebugLevel = atoi(argv[1]); - if (gDebugLevel >= 0) { - _vm->_debugMode = true; - DebugPrintf("Debug level set to level %d\n", gDebugLevel); - } else if (gDebugLevel < 0) { - _vm->_debugMode = false; - DebugPrintf("Debugging is now disabled\n"); - } else - DebugPrintf("Not a valid debug level\n"); + debugPrintf("Usage: debug [+CHANNEL|-CHANNEL]\n"); + debugPrintf("Enables or disables the given debug channel.\n"); + debugPrintf("When used without parameters, lists all available debug channels and their status.\n"); } return true; } bool ScummDebugger::Cmd_Camera(int argc, const char **argv) { - DebugPrintf("Camera: cur (%d,%d) - dest (%d,%d) - accel (%d,%d) -- last (%d,%d)\n", + debugPrintf("Camera: cur (%d,%d) - dest (%d,%d) - accel (%d,%d) -- last (%d,%d)\n", _vm->camera._cur.x, _vm->camera._cur.y, _vm->camera._dest.x, _vm->camera._dest.y, _vm->camera._accel.x, _vm->camera._accel.y, _vm->camera._last.x, _vm->camera._last.y); @@ -560,7 +550,7 @@ bool ScummDebugger::Cmd_PrintBox(int argc, const char **argv) { printBox(atoi(argv[i])); } else { num = _vm->getNumBoxes(); - DebugPrintf("\nWalk boxes:\n"); + debugPrintf("\nWalk boxes:\n"); for (i = 0; i < num; i++) printBox(i); } @@ -572,29 +562,29 @@ bool ScummDebugger::Cmd_PrintBoxMatrix(int argc, const char **argv) { int num = _vm->getNumBoxes(); int i, j; - DebugPrintf("Walk matrix:\n"); + debugPrintf("Walk matrix:\n"); if (_vm->_game.version <= 2) boxm += num; for (i = 0; i < num; i++) { - DebugPrintf("%d: ", i); + debugPrintf("%d: ", i); if (_vm->_game.version <= 2) { for (j = 0; j < num; j++) - DebugPrintf("[%d] ", *boxm++); + debugPrintf("[%d] ", *boxm++); } else { while (*boxm != 0xFF) { - DebugPrintf("[%d-%d=>%d] ", boxm[0], boxm[1], boxm[2]); + debugPrintf("[%d-%d=>%d] ", boxm[0], boxm[1], boxm[2]); boxm += 3; } boxm++; } - DebugPrintf("\n"); + debugPrintf("\n"); } return true; } void ScummDebugger::printBox(int box) { if (box < 0 || box >= _vm->getNumBoxes()) { - DebugPrintf("%d is not a valid box!\n", box); + debugPrintf("%d is not a valid box!\n", box); return; } BoxCoords coords; @@ -605,7 +595,7 @@ void ScummDebugger::printBox(int box) { coords = _vm->getBoxCoordinates(box); // Print out coords, flags, zbuffer mask - DebugPrintf("%d: [%d x %d] [%d x %d] [%d x %d] [%d x %d], flags=0x%02x, mask=%d, scale=%d\n", + debugPrintf("%d: [%d x %d] [%d x %d] [%d x %d] [%d x %d], flags=0x%02x, mask=%d, scale=%d\n", box, coords.ul.x, coords.ul.y, coords.ll.x, coords.ll.y, coords.ur.x, coords.ur.y, coords.lr.x, coords.lr.y, @@ -746,7 +736,7 @@ bool ScummDebugger::Cmd_PrintDraft(int argc, const char **argv) { int i, base, draft; if (_vm->_game.id != GID_LOOM) { - DebugPrintf("Command only works with Loom/LoomCD\n"); + debugPrintf("Command only works with Loom/LoomCD\n"); return true; } @@ -797,7 +787,7 @@ bool ScummDebugger::Cmd_PrintDraft(int argc, const char **argv) { // the distaff, but I don't know if that's a safe // thing to do. - DebugPrintf("Learned all drafts and notes.\n"); + debugPrintf("Learned all drafts and notes.\n"); return true; } } @@ -806,7 +796,7 @@ bool ScummDebugger::Cmd_PrintDraft(int argc, const char **argv) { for (i = 0; i < 16; i++) { draft = _vm->_scummVars[base + i * 2]; - DebugPrintf("%d %-13s %c%c%c%c %c%c\n", + debugPrintf("%d %-13s %c%c%c%c %c%c\n", base + 2 * i, names[i], notes[draft & 0x0007], @@ -830,7 +820,7 @@ bool ScummDebugger::Cmd_Passcode(int argc, const char **argv) { _vm->runScript(61, 0, 0, args); if (_vm->_bootParam != _vm->_scummVars[411]){ - DebugPrintf("Invalid Passcode\n"); + debugPrintf("Invalid Passcode\n"); return true; } @@ -838,7 +828,7 @@ bool ScummDebugger::Cmd_Passcode(int argc, const char **argv) { detach(); } else { - DebugPrintf("Current Passcode is %d \nUse 'passcode <SEGA CD Passcode>'\n",_vm->_scummVars[411]); + debugPrintf("Current Passcode is %d \nUse 'passcode <SEGA CD Passcode>'\n",_vm->_scummVars[411]); return true; } return false; diff --git a/engines/scumm/debugger.h b/engines/scumm/debugger.h index 43bf9d6fd4..657f6be286 100644 --- a/engines/scumm/debugger.h +++ b/engines/scumm/debugger.h @@ -37,6 +37,9 @@ public: private: ScummEngine *_vm; + virtual void preEnter(); + virtual void postEnter(); + // Commands bool Cmd_Room(int argc, const char **argv); bool Cmd_LoadGame(int argc, const char **argv); @@ -58,7 +61,6 @@ private: bool Cmd_Passcode(int argc, const char **argv); bool Cmd_Debug(int argc, const char **argv); - bool Cmd_DebugLevel(int argc, const char **argv); bool Cmd_Show(int argc, const char **argv); bool Cmd_Hide(int argc, const char **argv); diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index 54f22ecad3..34c231e5d4 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -205,7 +205,7 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr) _lastInputScriptTime = 0; _bootParam = 0; _dumpScripts = false; - _debugMode = 0; + _debugMode = false; _objectOwnerTable = NULL; _objectRoomTable = NULL; _objectStateTable = NULL; @@ -2281,7 +2281,7 @@ void ScummEngine::scummLoop_updateScummVars() { VAR(VAR_MOUSE_Y) = _mouse.y; if (VAR_DEBUGMODE != 0xFF) { // This is NOT for the Mac version of Indy3/Loom - VAR(VAR_DEBUGMODE) = _debugMode; + VAR(VAR_DEBUGMODE) = (_debugMode ? 1 : 0); } } else if (_game.version >= 1) { // We use shifts below instead of dividing by V12_X_MULTIPLIER resp. diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h index b4afa09bb2..be5a83d8c9 100644 --- a/engines/scumm/scumm.h +++ b/engines/scumm/scumm.h @@ -586,7 +586,7 @@ protected: bool _dumpScripts; bool _hexdumpScripts; bool _showStack; - uint16 _debugMode; + bool _debugMode; // Save/Load class - some of this may be GUI byte _saveLoadFlag, _saveLoadSlot; diff --git a/engines/scumm/vars.cpp b/engines/scumm/vars.cpp index 73028c8513..79d7ed03da 100644 --- a/engines/scumm/vars.cpp +++ b/engines/scumm/vars.cpp @@ -805,7 +805,7 @@ void ScummEngine::resetScummVars() { } if (VAR_DEBUGMODE != 0xFF) { - VAR(VAR_DEBUGMODE) = _debugMode; + VAR(VAR_DEBUGMODE) = (_debugMode ? 1 : 0); if (_game.heversion >= 80 && _debugMode) VAR(85) = 1; } diff --git a/engines/sky/debug.cpp b/engines/sky/debug.cpp index 63da42eec2..d663bd206d 100644 --- a/engines/sky/debug.cpp +++ b/engines/sky/debug.cpp @@ -1087,14 +1087,14 @@ void Debug::mcode(uint32 mcode, uint32 a, uint32 b, uint32 c) { Debugger::Debugger(Logic *logic, Mouse *mouse, Screen *screen, SkyCompact *skyCompact) : GUI::Debugger(), _logic(logic), _mouse(mouse), _screen(screen), _skyCompact(skyCompact), _showGrid(false) { - DCmd_Register("info", WRAP_METHOD(Debugger, Cmd_Info)); - DCmd_Register("showgrid", WRAP_METHOD(Debugger, Cmd_ShowGrid)); - DCmd_Register("reloadgrid", WRAP_METHOD(Debugger, Cmd_ReloadGrid)); - DCmd_Register("compact", WRAP_METHOD(Debugger, Cmd_ShowCompact)); - DCmd_Register("logiccmd", WRAP_METHOD(Debugger, Cmd_LogicCommand)); - DCmd_Register("scriptvar", WRAP_METHOD(Debugger, Cmd_ScriptVar)); - DCmd_Register("section", WRAP_METHOD(Debugger, Cmd_Section)); - DCmd_Register("logiclist", WRAP_METHOD(Debugger, Cmd_LogicList)); + registerCmd("info", WRAP_METHOD(Debugger, Cmd_Info)); + registerCmd("showgrid", WRAP_METHOD(Debugger, Cmd_ShowGrid)); + registerCmd("reloadgrid", WRAP_METHOD(Debugger, Cmd_ReloadGrid)); + registerCmd("compact", WRAP_METHOD(Debugger, Cmd_ShowCompact)); + registerCmd("logiccmd", WRAP_METHOD(Debugger, Cmd_LogicCommand)); + registerCmd("scriptvar", WRAP_METHOD(Debugger, Cmd_ScriptVar)); + registerCmd("section", WRAP_METHOD(Debugger, Cmd_Section)); + registerCmd("logiclist", WRAP_METHOD(Debugger, Cmd_LogicList)); } Debugger::~Debugger() {} // we need this here for __SYMBIAN32__ @@ -1119,14 +1119,14 @@ static bool isNumeric(const char *arg) { bool Debugger::Cmd_ShowGrid(int argc, const char **argv) { _showGrid = !_showGrid; - DebugPrintf("Show grid: %s\n", _showGrid ? "On" : "Off"); + debugPrintf("Show grid: %s\n", _showGrid ? "On" : "Off"); if (!_showGrid) _screen->forceRefresh(); return true; } bool Debugger::Cmd_ReloadGrid(int argc, const char **argv) { _logic->_skyGrid->loadGrids(); - DebugPrintf("Grid reloaded\n"); + debugPrintf("Grid reloaded\n"); return true; } @@ -1143,35 +1143,35 @@ void Debugger::dumpCompact(uint16 cptId) { Compact *cpt = _skyCompact->fetchCptInfo(cptId, &size, &type, name); if (type == COMPACT) { - DebugPrintf("Compact %s: id = %04X, section %d, id %d\n", name, cptId, cptId >> 12, cptId & 0xFFF); - DebugPrintf("logic : %04X: %s\n", cpt->logic, (cpt->logic <= 16) ? logicTypes[cpt->logic] : "unknown"); - DebugPrintf("status : %04X\n", cpt->status); - DebugPrintf(" : background : %s\n", noYes[(cpt->status & ST_BACKGROUND) >> 0]); - DebugPrintf(" : foreground : %s\n", noYes[(cpt->status & ST_FOREGROUND) >> 1]); - DebugPrintf(" : sort list : %s\n", noYes[(cpt->status & ST_SORT) >> 2]); - DebugPrintf(" : recreate : %s\n", noYes[(cpt->status & ST_RECREATE) >> 3]); - DebugPrintf(" : mouse : %s\n", noYes[(cpt->status & ST_MOUSE) >> 4]); - DebugPrintf(" : collision : %s\n", noYes[(cpt->status & ST_COLLISION) >> 5]); - DebugPrintf(" : logic : %s\n", noYes[(cpt->status & ST_LOGIC) >> 6]); - DebugPrintf(" : on grid : %s\n", noYes[(cpt->status & ST_GRID_PLOT) >> 7]); - DebugPrintf(" : ar priority : %s\n", noYes[(cpt->status & ST_AR_PRIORITY) >> 8]); - DebugPrintf("sync : %04X\n", cpt->sync); - DebugPrintf("screen : %d\n", cpt->screen); + debugPrintf("Compact %s: id = %04X, section %d, id %d\n", name, cptId, cptId >> 12, cptId & 0xFFF); + debugPrintf("logic : %04X: %s\n", cpt->logic, (cpt->logic <= 16) ? logicTypes[cpt->logic] : "unknown"); + debugPrintf("status : %04X\n", cpt->status); + debugPrintf(" : background : %s\n", noYes[(cpt->status & ST_BACKGROUND) >> 0]); + debugPrintf(" : foreground : %s\n", noYes[(cpt->status & ST_FOREGROUND) >> 1]); + debugPrintf(" : sort list : %s\n", noYes[(cpt->status & ST_SORT) >> 2]); + debugPrintf(" : recreate : %s\n", noYes[(cpt->status & ST_RECREATE) >> 3]); + debugPrintf(" : mouse : %s\n", noYes[(cpt->status & ST_MOUSE) >> 4]); + debugPrintf(" : collision : %s\n", noYes[(cpt->status & ST_COLLISION) >> 5]); + debugPrintf(" : logic : %s\n", noYes[(cpt->status & ST_LOGIC) >> 6]); + debugPrintf(" : on grid : %s\n", noYes[(cpt->status & ST_GRID_PLOT) >> 7]); + debugPrintf(" : ar priority : %s\n", noYes[(cpt->status & ST_AR_PRIORITY) >> 8]); + debugPrintf("sync : %04X\n", cpt->sync); + debugPrintf("screen : %d\n", cpt->screen); _skyCompact->fetchCptInfo(cpt->place, NULL, NULL, name); - DebugPrintf("place : %04X: %s\n", cpt->place, name); + debugPrintf("place : %04X: %s\n", cpt->place, name); _skyCompact->fetchCptInfo(cpt->getToTableId, NULL, NULL, name); - DebugPrintf("get to tab : %04X: %s\n", cpt->getToTableId, name); - DebugPrintf("x/y : %d/%d\n", cpt->xcood, cpt->ycood); + debugPrintf("get to tab : %04X: %s\n", cpt->getToTableId, name); + debugPrintf("x/y : %d/%d\n", cpt->xcood, cpt->ycood); } else { - DebugPrintf("Can't dump binary data\n"); + debugPrintf("Can't dump binary data\n"); } } bool Debugger::Cmd_ShowCompact(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Example: \"%s foster\" dumps compact \"foster\"\n", argv[0]); - DebugPrintf("Example: \"%s list 1\" lists all compacts from section 1\n", argv[0]); - DebugPrintf("Example: \"%s list 1 all\" lists all entities from section 1\n", argv[0]); + debugPrintf("Example: \"%s foster\" dumps compact \"foster\"\n", argv[0]); + debugPrintf("Example: \"%s list 1\" lists all compacts from section 1\n", argv[0]); + debugPrintf("Example: \"%s list 1 all\" lists all entities from section 1\n", argv[0]); return true; } @@ -1181,7 +1181,7 @@ bool Debugger::Cmd_ShowCompact(int argc, const char **argv) { if (argc >= 3) { sectionNumber = atoi(argv[2]); if (sectionNumber >= _skyCompact->giveNumDataLists()) { - DebugPrintf("Section number %d does not exist\n", sectionNumber); + debugPrintf("Section number %d does not exist\n", sectionNumber); return true; } if ((argc == 4) && (scumm_stricmp(argv[3], "all") == 0)) @@ -1189,14 +1189,14 @@ bool Debugger::Cmd_ShowCompact(int argc, const char **argv) { } for (int sec = 0; sec < _skyCompact->giveNumDataLists(); sec++) { if ((sectionNumber == -1) || (sectionNumber == sec)) { - DebugPrintf("Compacts in section %d:\n", sec); + debugPrintf("Compacts in section %d:\n", sec); if (showAll) { char line[256]; char *linePos = line; for (int cpt = 0; cpt < _skyCompact->giveDataListLen(sec); cpt++) { if (cpt != 0) { if ((cpt % 3) == 0) { - DebugPrintf("%s\n", line); + debugPrintf("%s\n", line); linePos = line; } else linePos += sprintf(linePos, ", "); @@ -1208,7 +1208,7 @@ bool Debugger::Cmd_ShowCompact(int argc, const char **argv) { linePos += sprintf(linePos, "%04X: %10s %22s", cptId, _skyCompact->nameForType(type), name); } if (linePos != line) - DebugPrintf("%s\n", line); + debugPrintf("%s\n", line); } else { for (int cpt = 0; cpt < _skyCompact->giveDataListLen(sec); cpt++) { uint16 cptId = (uint16)((sec << 12) | cpt); @@ -1216,7 +1216,7 @@ bool Debugger::Cmd_ShowCompact(int argc, const char **argv) { char name[256]; _skyCompact->fetchCptInfo(cptId, &size, &type, name); if (type == COMPACT) - DebugPrintf("%04X: %s\n", cptId, name); + debugPrintf("%04X: %s\n", cptId, name); } } } @@ -1224,7 +1224,7 @@ bool Debugger::Cmd_ShowCompact(int argc, const char **argv) { } else { uint16 cptId = _skyCompact->findCptId(argv[1]); if (cptId == 0) - DebugPrintf("Unknown compact: '%s'\n", argv[1]); + debugPrintf("Unknown compact: '%s'\n", argv[1]); else dumpCompact(cptId); } @@ -1233,7 +1233,7 @@ bool Debugger::Cmd_ShowCompact(int argc, const char **argv) { bool Debugger::Cmd_LogicCommand(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Example: %s fn_printf 42\n", argv[0]); + debugPrintf("Example: %s fn_printf 42\n", argv[0]); return true; } @@ -1241,7 +1241,7 @@ bool Debugger::Cmd_LogicCommand(int argc, const char **argv) { if (0 == strcmp(argv[1], "list")) { for (int i = 0; i < numMCodes; ++i) { - DebugPrintf("%s\n", mcodes[i]); + debugPrintf("%s\n", mcodes[i]); } return true; } @@ -1264,21 +1264,21 @@ bool Debugger::Cmd_LogicCommand(int argc, const char **argv) { } } - DebugPrintf("Unknown function: '%s'\n", argv[1]); + debugPrintf("Unknown function: '%s'\n", argv[1]); return true; } bool Debugger::Cmd_Info(int argc, const char **argv) { - DebugPrintf("Beneath a Steel Sky version: 0.0%d\n", SkyEngine::_systemVars.gameVersion); - DebugPrintf("Speech: %s\n", (SkyEngine::_systemVars.systemFlags & SF_ALLOW_SPEECH) ? "on" : "off"); - DebugPrintf("Text : %s\n", (SkyEngine::_systemVars.systemFlags & SF_ALLOW_TEXT) ? "on" : "off"); + debugPrintf("Beneath a Steel Sky version: 0.0%d\n", SkyEngine::_systemVars.gameVersion); + debugPrintf("Speech: %s\n", (SkyEngine::_systemVars.systemFlags & SF_ALLOW_SPEECH) ? "on" : "off"); + debugPrintf("Text : %s\n", (SkyEngine::_systemVars.systemFlags & SF_ALLOW_TEXT) ? "on" : "off"); return true; } bool Debugger::Cmd_ScriptVar(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Example: %s lamb_friend <value>\n", argv[0]); + debugPrintf("Example: %s lamb_friend <value>\n", argv[0]); return true; } @@ -1286,7 +1286,7 @@ bool Debugger::Cmd_ScriptVar(int argc, const char **argv) { if (0 == strcmp(argv[1], "list")) { for (int i = 0; i < numScriptVars; ++i) { - DebugPrintf("%s\n", scriptVars[i]); + debugPrintf("%s\n", scriptVars[i]); } return true; } @@ -1296,13 +1296,13 @@ bool Debugger::Cmd_ScriptVar(int argc, const char **argv) { if (argc == 3) { Logic::_scriptVariables[i] = atoi(argv[2]); } - DebugPrintf("%s = %d\n", argv[1], Logic::_scriptVariables[i]); + debugPrintf("%s = %d\n", argv[1], Logic::_scriptVariables[i]); return true; } } - DebugPrintf("Unknown ScriptVar: '%s'\n", argv[1]); + debugPrintf("Unknown ScriptVar: '%s'\n", argv[1]); return true; } @@ -1317,30 +1317,30 @@ bool Debugger::Cmd_Section(int argc, const char **argv) { _logic->fnAssignBase(ID_FOSTER, baseId[section], 0); _skyCompact->fetchCpt(ID_FOSTER)->megaSet = 0; } else { - DebugPrintf("Section %d is out of range (range: %d - %d)\n", section, 0, 6); + debugPrintf("Section %d is out of range (range: %d - %d)\n", section, 0, 6); } } else { - DebugPrintf("Example: %s 4\n", argv[0]); + debugPrintf("Example: %s 4\n", argv[0]); } return true; } bool Debugger::Cmd_LogicList(int argc, const char **argv) { if (argc != 1) - DebugPrintf("%s does not expect any parameters\n", argv[0]); + debugPrintf("%s does not expect any parameters\n", argv[0]); char cptName[256]; uint16 numElems, type; uint16 *logicList = (uint16 *)_skyCompact->fetchCptInfo(Logic::_scriptVariables[LOGIC_LIST_NO], &numElems, &type, cptName); - DebugPrintf("Current LogicList: %04X (%s)\n", Logic::_scriptVariables[LOGIC_LIST_NO], cptName); + debugPrintf("Current LogicList: %04X (%s)\n", Logic::_scriptVariables[LOGIC_LIST_NO], cptName); while (*logicList != 0) { if (*logicList == 0xFFFF) { uint16 newList = logicList[1]; logicList = (uint16 *)_skyCompact->fetchCptInfo(newList, &numElems, &type, cptName); - DebugPrintf("New List: %04X (%s)\n", newList, cptName); + debugPrintf("New List: %04X (%s)\n", newList, cptName); } else { _skyCompact->fetchCptInfo(*logicList, &numElems, &type, cptName); - DebugPrintf(" Cpt %04X (%s) (%s)\n", *logicList, cptName, _skyCompact->nameForType(type)); + debugPrintf(" Cpt %04X (%s) (%s)\n", *logicList, cptName, _skyCompact->nameForType(type)); logicList++; } } diff --git a/engines/sword2/console.cpp b/engines/sword2/console.cpp index 4838bd15f6..0aa78f552b 100644 --- a/engines/sword2/console.cpp +++ b/engines/sword2/console.cpp @@ -82,55 +82,55 @@ Debugger::Debugger(Sword2Engine *vm) // Register commands - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("q", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("mem", WRAP_METHOD(Debugger, Cmd_Mem)); - DCmd_Register("tony", WRAP_METHOD(Debugger, Cmd_Tony)); - DCmd_Register("res", WRAP_METHOD(Debugger, Cmd_Res)); - DCmd_Register("reslist", WRAP_METHOD(Debugger, Cmd_ResList)); - DCmd_Register("starts", WRAP_METHOD(Debugger, Cmd_Starts)); - DCmd_Register("start", WRAP_METHOD(Debugger, Cmd_Start)); - DCmd_Register("s", WRAP_METHOD(Debugger, Cmd_Start)); - DCmd_Register("info", WRAP_METHOD(Debugger, Cmd_Info)); - DCmd_Register("walkgrid", WRAP_METHOD(Debugger, Cmd_WalkGrid)); - DCmd_Register("mouse", WRAP_METHOD(Debugger, Cmd_Mouse)); - DCmd_Register("player", WRAP_METHOD(Debugger, Cmd_Player)); - DCmd_Register("reslook", WRAP_METHOD(Debugger, Cmd_ResLook)); - DCmd_Register("cur", WRAP_METHOD(Debugger, Cmd_CurrentInfo)); - DCmd_Register("runlist", WRAP_METHOD(Debugger, Cmd_RunList)); - DCmd_Register("kill", WRAP_METHOD(Debugger, Cmd_Kill)); - DCmd_Register("nuke", WRAP_METHOD(Debugger, Cmd_Nuke)); - DCmd_Register("var", WRAP_METHOD(Debugger, Cmd_Var)); - DCmd_Register("rect", WRAP_METHOD(Debugger, Cmd_Rect)); - DCmd_Register("clear", WRAP_METHOD(Debugger, Cmd_Clear)); - DCmd_Register("debugon", WRAP_METHOD(Debugger, Cmd_DebugOn)); - DCmd_Register("debugoff", WRAP_METHOD(Debugger, Cmd_DebugOff)); - DCmd_Register("saverest", WRAP_METHOD(Debugger, Cmd_SaveRest)); - DCmd_Register("timeon", WRAP_METHOD(Debugger, Cmd_TimeOn)); - DCmd_Register("timeoff", WRAP_METHOD(Debugger, Cmd_TimeOff)); - DCmd_Register("text", WRAP_METHOD(Debugger, Cmd_Text)); - DCmd_Register("showvar", WRAP_METHOD(Debugger, Cmd_ShowVar)); - DCmd_Register("hidevar", WRAP_METHOD(Debugger, Cmd_HideVar)); - DCmd_Register("version", WRAP_METHOD(Debugger, Cmd_Version)); - DCmd_Register("animtest", WRAP_METHOD(Debugger, Cmd_AnimTest)); - DCmd_Register("texttest", WRAP_METHOD(Debugger, Cmd_TextTest)); - DCmd_Register("linetest", WRAP_METHOD(Debugger, Cmd_LineTest)); - DCmd_Register("events", WRAP_METHOD(Debugger, Cmd_Events)); - DCmd_Register("sfx", WRAP_METHOD(Debugger, Cmd_Sfx)); - DCmd_Register("english", WRAP_METHOD(Debugger, Cmd_English)); - DCmd_Register("finnish", WRAP_METHOD(Debugger, Cmd_Finnish)); - DCmd_Register("polish", WRAP_METHOD(Debugger, Cmd_Polish)); - DCmd_Register("fxq", WRAP_METHOD(Debugger, Cmd_FxQueue)); + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("q", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("mem", WRAP_METHOD(Debugger, Cmd_Mem)); + registerCmd("tony", WRAP_METHOD(Debugger, Cmd_Tony)); + registerCmd("res", WRAP_METHOD(Debugger, Cmd_Res)); + registerCmd("reslist", WRAP_METHOD(Debugger, Cmd_ResList)); + registerCmd("starts", WRAP_METHOD(Debugger, Cmd_Starts)); + registerCmd("start", WRAP_METHOD(Debugger, Cmd_Start)); + registerCmd("s", WRAP_METHOD(Debugger, Cmd_Start)); + registerCmd("info", WRAP_METHOD(Debugger, Cmd_Info)); + registerCmd("walkgrid", WRAP_METHOD(Debugger, Cmd_WalkGrid)); + registerCmd("mouse", WRAP_METHOD(Debugger, Cmd_Mouse)); + registerCmd("player", WRAP_METHOD(Debugger, Cmd_Player)); + registerCmd("reslook", WRAP_METHOD(Debugger, Cmd_ResLook)); + registerCmd("cur", WRAP_METHOD(Debugger, Cmd_CurrentInfo)); + registerCmd("runlist", WRAP_METHOD(Debugger, Cmd_RunList)); + registerCmd("kill", WRAP_METHOD(Debugger, Cmd_Kill)); + registerCmd("nuke", WRAP_METHOD(Debugger, Cmd_Nuke)); + registerCmd("var", WRAP_METHOD(Debugger, Cmd_Var)); + registerCmd("rect", WRAP_METHOD(Debugger, Cmd_Rect)); + registerCmd("clear", WRAP_METHOD(Debugger, Cmd_Clear)); + registerCmd("debugon", WRAP_METHOD(Debugger, Cmd_DebugOn)); + registerCmd("debugoff", WRAP_METHOD(Debugger, Cmd_DebugOff)); + registerCmd("saverest", WRAP_METHOD(Debugger, Cmd_SaveRest)); + registerCmd("timeon", WRAP_METHOD(Debugger, Cmd_TimeOn)); + registerCmd("timeoff", WRAP_METHOD(Debugger, Cmd_TimeOff)); + registerCmd("text", WRAP_METHOD(Debugger, Cmd_Text)); + registerCmd("showvar", WRAP_METHOD(Debugger, Cmd_ShowVar)); + registerCmd("hidevar", WRAP_METHOD(Debugger, Cmd_HideVar)); + registerCmd("version", WRAP_METHOD(Debugger, Cmd_Version)); + registerCmd("animtest", WRAP_METHOD(Debugger, Cmd_AnimTest)); + registerCmd("texttest", WRAP_METHOD(Debugger, Cmd_TextTest)); + registerCmd("linetest", WRAP_METHOD(Debugger, Cmd_LineTest)); + registerCmd("events", WRAP_METHOD(Debugger, Cmd_Events)); + registerCmd("sfx", WRAP_METHOD(Debugger, Cmd_Sfx)); + registerCmd("english", WRAP_METHOD(Debugger, Cmd_English)); + registerCmd("finnish", WRAP_METHOD(Debugger, Cmd_Finnish)); + registerCmd("polish", WRAP_METHOD(Debugger, Cmd_Polish)); + registerCmd("fxq", WRAP_METHOD(Debugger, Cmd_FxQueue)); } void Debugger::varGet(int var) { - DebugPrintf("%d\n", _vm->_logic->readVar(var)); + debugPrintf("%d\n", _vm->_logic->readVar(var)); } void Debugger::varSet(int var, int val) { - DebugPrintf("was %d, ", _vm->_logic->readVar(var)); + debugPrintf("was %d, ", _vm->_logic->readVar(var)); _vm->_logic->writeVar(var, val); - DebugPrintf("now %d\n", _vm->_logic->readVar(var)); + debugPrintf("now %d\n", _vm->_logic->readVar(var)); } void Debugger::preEnter() { @@ -184,8 +184,8 @@ bool Debugger::Cmd_Mem(int argc, const char **argv) { qsort(blocks, numBlocks, sizeof(MemBlock *), compare_blocks); - DebugPrintf(" size id res type name\n"); - DebugPrintf("---------------------------------------------------------------------------\n"); + debugPrintf(" size id res type name\n"); + debugPrintf("---------------------------------------------------------------------------\n"); for (i = 0; i < numBlocks; i++) { const char *type; @@ -235,21 +235,21 @@ bool Debugger::Cmd_Mem(int argc, const char **argv) { break; } - DebugPrintf("%9d %-3d %-4d %-20s %s\n", + debugPrintf("%9d %-3d %-4d %-20s %s\n", blocks[i]->size, blocks[i]->id, blocks[i]->uid, type, _vm->_resman->fetchName(blocks[i]->ptr)); } free(blocks); - DebugPrintf("---------------------------------------------------------------------------\n"); - DebugPrintf("%9d\n", _vm->_memory->getTotAlloc()); + debugPrintf("---------------------------------------------------------------------------\n"); + debugPrintf("%9d\n", _vm->_memory->getTotAlloc()); return true; } bool Debugger::Cmd_Tony(int argc, const char **argv) { - DebugPrintf("What about him?\n"); + debugPrintf("What about him?\n"); return true; } @@ -257,7 +257,7 @@ bool Debugger::Cmd_Res(int argc, const char **argv) { uint32 numClusters = _vm->_resman->getNumClusters(); if (!numClusters) { - DebugPrintf("Argh! No resources!\n"); + debugPrintf("Argh! No resources!\n"); return true; } @@ -266,10 +266,10 @@ bool Debugger::Cmd_Res(int argc, const char **argv) { for (uint i = 0; i < numClusters; i++) { const char *locStr[3] = { "HDD", "CD1", "CD2" }; - DebugPrintf("%-20s %s\n", resFiles[i].fileName, locStr[resFiles[i].cd]); + debugPrintf("%-20s %s\n", resFiles[i].fileName, locStr[resFiles[i].cd]); } - DebugPrintf("%d resources\n", _vm->_resman->getNumResFiles()); + debugPrintf("%d resources\n", _vm->_resman->getNumResFiles()); return true; } @@ -285,7 +285,7 @@ bool Debugger::Cmd_ResList(int argc, const char **argv) { for (uint i = 0; i < numResFiles; i++) { if (resList[i].ptr && resList[i].refCount >= minCount) { - DebugPrintf("%-4d: %-35s refCount: %-3d\n", i, _vm->_resman->fetchName(resList[i].ptr), resList[i].refCount); + debugPrintf("%-4d: %-35s refCount: %-3d\n", i, _vm->_resman->fetchName(resList[i].ptr), resList[i].refCount); } } @@ -296,21 +296,21 @@ bool Debugger::Cmd_Starts(int argc, const char **argv) { uint32 numStarts = _vm->getNumStarts(); if (!numStarts) { - DebugPrintf("Sorry - no startup positions registered?\n"); + debugPrintf("Sorry - no startup positions registered?\n"); uint32 numScreenManagers = _vm->getNumScreenManagers(); if (!numScreenManagers) - DebugPrintf("There is a problem with startup.inf\n"); + debugPrintf("There is a problem with startup.inf\n"); else - DebugPrintf(" (%d screen managers found in startup.inf)\n", numScreenManagers); + debugPrintf(" (%d screen managers found in startup.inf)\n", numScreenManagers); return true; } StartUp *startList = _vm->getStartList(); for (uint i = 0; i < numStarts; i++) - DebugPrintf("%d (%s)\n", i, startList[i].description); + debugPrintf("%d (%s)\n", i, startList[i].description); return true; } @@ -319,25 +319,25 @@ bool Debugger::Cmd_Start(int argc, const char **argv) { uint8 pal[3] = { 255, 255, 255 }; if (argc != 2) { - DebugPrintf("Usage: %s number\n", argv[0]); + debugPrintf("Usage: %s number\n", argv[0]); return true; } uint32 numStarts = _vm->getNumStarts(); if (!numStarts) { - DebugPrintf("Sorry - there are no startups!\n"); + debugPrintf("Sorry - there are no startups!\n"); return true; } int start = atoi(argv[1]); if (start < 0 || start >= (int)numStarts) { - DebugPrintf("Not a legal start position\n"); + debugPrintf("Not a legal start position\n"); return true; } - DebugPrintf("Running start %d\n", start); + debugPrintf("Running start %d\n", start); _vm->runStart(start); _vm->_screen->setPalette(187, 1, pal, RDPAL_INSTANT); @@ -348,9 +348,9 @@ bool Debugger::Cmd_Info(int argc, const char **argv) { _displayDebugText = !_displayDebugText; if (_displayDebugText) - DebugPrintf("Info text on\n"); + debugPrintf("Info text on\n"); else - DebugPrintf("Info Text off\n"); + debugPrintf("Info Text off\n"); return true; } @@ -359,9 +359,9 @@ bool Debugger::Cmd_WalkGrid(int argc, const char **argv) { _displayWalkGrid = !_displayWalkGrid; if (_displayWalkGrid) - DebugPrintf("Walk-grid display on\n"); + debugPrintf("Walk-grid display on\n"); else - DebugPrintf("Walk-grid display off\n"); + debugPrintf("Walk-grid display off\n"); return true; } @@ -370,9 +370,9 @@ bool Debugger::Cmd_Mouse(int argc, const char **argv) { _displayMouseMarker = !_displayMouseMarker; if (_displayMouseMarker) - DebugPrintf("Mouse marker on\n"); + debugPrintf("Mouse marker on\n"); else - DebugPrintf("Mouse marker off\n"); + debugPrintf("Mouse marker off\n"); return true; } @@ -381,16 +381,16 @@ bool Debugger::Cmd_Player(int argc, const char **argv) { _displayPlayerMarker = !_displayPlayerMarker; if (_displayPlayerMarker) - DebugPrintf("Player feet marker on\n"); + debugPrintf("Player feet marker on\n"); else - DebugPrintf("Player feet marker off\n"); + debugPrintf("Player feet marker off\n"); return true; } bool Debugger::Cmd_ResLook(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Usage: %s number\n", argv[0]); + debugPrintf("Usage: %s number\n", argv[0]); return true; } @@ -398,13 +398,13 @@ bool Debugger::Cmd_ResLook(int argc, const char **argv) { uint32 numResFiles = _vm->_resman->getNumResFiles(); if (res < 0 || res >= (int)numResFiles) { - DebugPrintf("Illegal resource %d. There are %d resources, 0-%d.\n", + debugPrintf("Illegal resource %d. There are %d resources, 0-%d.\n", res, numResFiles, numResFiles - 1); return true; } if (!_vm->_resman->checkValid(res)) { - DebugPrintf("%d is a null & void resource number\n", res); + debugPrintf("%d is a null & void resource number\n", res); return true; } @@ -413,40 +413,40 @@ bool Debugger::Cmd_ResLook(int argc, const char **argv) { switch (type) { case ANIMATION_FILE: - DebugPrintf("<anim> %s\n", _vm->_resman->fetchName(res)); + debugPrintf("<anim> %s\n", _vm->_resman->fetchName(res)); break; case SCREEN_FILE: - DebugPrintf("<layer> %s\n", _vm->_resman->fetchName(res)); + debugPrintf("<layer> %s\n", _vm->_resman->fetchName(res)); break; case GAME_OBJECT: - DebugPrintf("<game object> %s\n", _vm->_resman->fetchName(res)); + debugPrintf("<game object> %s\n", _vm->_resman->fetchName(res)); break; case WALK_GRID_FILE: - DebugPrintf("<walk grid> %s\n", _vm->_resman->fetchName(res)); + debugPrintf("<walk grid> %s\n", _vm->_resman->fetchName(res)); break; case GLOBAL_VAR_FILE: - DebugPrintf("<global variables> %s\n", _vm->_resman->fetchName(res)); + debugPrintf("<global variables> %s\n", _vm->_resman->fetchName(res)); break; case PARALLAX_FILE_null: - DebugPrintf("<parallax file NOT USED!> %s\n", _vm->_resman->fetchName(res)); + debugPrintf("<parallax file NOT USED!> %s\n", _vm->_resman->fetchName(res)); break; case RUN_LIST: - DebugPrintf("<run list> %s\n", _vm->_resman->fetchName(res)); + debugPrintf("<run list> %s\n", _vm->_resman->fetchName(res)); break; case TEXT_FILE: - DebugPrintf("<text file> %s\n", _vm->_resman->fetchName(res)); + debugPrintf("<text file> %s\n", _vm->_resman->fetchName(res)); break; case SCREEN_MANAGER: - DebugPrintf("<screen manager> %s\n", _vm->_resman->fetchName(res)); + debugPrintf("<screen manager> %s\n", _vm->_resman->fetchName(res)); break; case MOUSE_FILE: - DebugPrintf("<mouse pointer> %s\n", _vm->_resman->fetchName(res)); + debugPrintf("<mouse pointer> %s\n", _vm->_resman->fetchName(res)); break; case ICON_FILE: - DebugPrintf("<menu icon> %s\n", _vm->_resman->fetchName(res)); + debugPrintf("<menu icon> %s\n", _vm->_resman->fetchName(res)); break; default: - DebugPrintf("unrecognized fileType %d\n", type); + debugPrintf("unrecognized fileType %d\n", type); break; } @@ -458,13 +458,13 @@ bool Debugger::Cmd_CurrentInfo(int argc, const char **argv) { ScreenInfo *screenInfo = _vm->_screen->getScreenInfo(); if (screenInfo->background_layer_id) { - DebugPrintf("background layer id %d\n", screenInfo->background_layer_id); - DebugPrintf("%d wide, %d high\n", screenInfo->screen_wide, screenInfo->screen_deep); - DebugPrintf("%d normal layers\n", screenInfo->number_of_layers); + debugPrintf("background layer id %d\n", screenInfo->background_layer_id); + debugPrintf("%d wide, %d high\n", screenInfo->screen_wide, screenInfo->screen_deep); + debugPrintf("%d normal layers\n", screenInfo->number_of_layers); Cmd_RunList(argc, argv); } else - DebugPrintf("No screen\n"); + debugPrintf("No screen\n"); return true; } @@ -476,26 +476,26 @@ bool Debugger::Cmd_RunList(int argc, const char **argv) { readS.seek(ResHeader::size()); - DebugPrintf("Runlist number %d\n", runList); + debugPrintf("Runlist number %d\n", runList); while (1) { uint32 res = readS.readUint32LE(); if (!res) break; - DebugPrintf("%d %s\n", res, _vm->_resman->fetchName(res)); + debugPrintf("%d %s\n", res, _vm->_resman->fetchName(res)); } _vm->_resman->closeResource(runList); } else - DebugPrintf("No run list set\n"); + debugPrintf("No run list set\n"); return true; } bool Debugger::Cmd_Kill(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Usage: %s number\n", argv[0]); + debugPrintf("Usage: %s number\n", argv[0]); return true; } @@ -503,7 +503,7 @@ bool Debugger::Cmd_Kill(int argc, const char **argv) { uint32 numResFiles = _vm->_resman->getNumResFiles(); if (res < 0 || res >= (int)numResFiles) { - DebugPrintf("Illegal resource %d. There are %d resources, 0-%d.\n", + debugPrintf("Illegal resource %d. There are %d resources, 0-%d.\n", res, numResFiles, numResFiles - 1); return true; } @@ -511,22 +511,22 @@ bool Debugger::Cmd_Kill(int argc, const char **argv) { Resource *resList = _vm->_resman->getResList(); if (!resList[res].ptr) { - DebugPrintf("Resource %d is not in memory\n", res); + debugPrintf("Resource %d is not in memory\n", res); return true; } if (resList[res].refCount) { - DebugPrintf("Resource %d is open - cannot remove\n", res); + debugPrintf("Resource %d is open - cannot remove\n", res); return true; } _vm->_resman->remove(res); - DebugPrintf("Trashed %d\n", res); + debugPrintf("Trashed %d\n", res); return true; } bool Debugger::Cmd_Nuke(int argc, const char **argv) { - DebugPrintf("Killing all resources except variable file and player object\n"); + debugPrintf("Killing all resources except variable file and player object\n"); _vm->_resman->killAll(true); return true; } @@ -540,7 +540,7 @@ bool Debugger::Cmd_Var(int argc, const char **argv) { varSet(atoi(argv[1]), atoi(argv[2])); break; default: - DebugPrintf("Usage: %s number value\n", argv[0]); + debugPrintf("Usage: %s number value\n", argv[0]); break; } @@ -554,10 +554,10 @@ bool Debugger::Cmd_Rect(int argc, const char **argv) { if (_definingRectangles) { _vm->setInputEventFilter(filter & ~(RD_LEFTBUTTONUP | RD_RIGHTBUTTONUP)); - DebugPrintf("Mouse rectangles enabled\n"); + debugPrintf("Mouse rectangles enabled\n"); } else { _vm->setInputEventFilter(filter | RD_LEFTBUTTONUP | RD_RIGHTBUTTONUP); - DebugPrintf("Mouse rectangles disabled\n"); + debugPrintf("Mouse rectangles disabled\n"); } _draggingRectangle = 0; @@ -575,7 +575,7 @@ bool Debugger::Cmd_DebugOn(int argc, const char **argv) { _displayMouseMarker = true; _displayPlayerMarker = true; _displayTextNumbers = true; - DebugPrintf("Enabled all on-screen debug info\n"); + debugPrintf("Enabled all on-screen debug info\n"); return true; } @@ -585,7 +585,7 @@ bool Debugger::Cmd_DebugOff(int argc, const char **argv) { _displayMouseMarker = false; _displayPlayerMarker = false; _displayTextNumbers = false; - DebugPrintf("Disabled all on-screen debug info\n"); + debugPrintf("Disabled all on-screen debug info\n"); return true; } @@ -593,9 +593,9 @@ bool Debugger::Cmd_SaveRest(int argc, const char **argv) { _testingSnR = !_testingSnR; if (_testingSnR) - DebugPrintf("Enabled S&R logic_script stability checking\n"); + debugPrintf("Enabled S&R logic_script stability checking\n"); else - DebugPrintf("Disabled S&R logic_script stability checking\n"); + debugPrintf("Disabled S&R logic_script stability checking\n"); return true; } @@ -606,13 +606,13 @@ bool Debugger::Cmd_TimeOn(int argc, const char **argv) { else if (_startTime == 0) _startTime = _vm->_system->getMillis(); _displayTime = true; - DebugPrintf("Timer display on\n"); + debugPrintf("Timer display on\n"); return true; } bool Debugger::Cmd_TimeOff(int argc, const char **argv) { _displayTime = false; - DebugPrintf("Timer display off\n"); + debugPrintf("Timer display off\n"); return true; } @@ -620,9 +620,9 @@ bool Debugger::Cmd_Text(int argc, const char **argv) { _displayTextNumbers = !_displayTextNumbers; if (_displayTextNumbers) - DebugPrintf("Text numbers on\n"); + debugPrintf("Text numbers on\n"); else - DebugPrintf("Text numbers off\n"); + debugPrintf("Text numbers off\n"); return true; } @@ -632,7 +632,7 @@ bool Debugger::Cmd_ShowVar(int argc, const char **argv) { int32 varNo; if (argc != 2) { - DebugPrintf("Usage: %s number\n", argv[0]); + debugPrintf("Usage: %s number\n", argv[0]); return true; } @@ -649,11 +649,11 @@ bool Debugger::Cmd_ShowVar(int argc, const char **argv) { if (_showVar[showVarNo] == 0) { // empty slot - add it to the list at this slot _showVar[showVarNo] = varNo; - DebugPrintf("var(%d) added to the watch-list\n", varNo); + debugPrintf("var(%d) added to the watch-list\n", varNo); } else - DebugPrintf("var(%d) already in the watch-list!\n", varNo); + debugPrintf("var(%d) already in the watch-list!\n", varNo); } else - DebugPrintf("Sorry - no more allowed - hide one or extend the system watch-list\n"); + debugPrintf("Sorry - no more allowed - hide one or extend the system watch-list\n"); return true; } @@ -663,7 +663,7 @@ bool Debugger::Cmd_HideVar(int argc, const char **argv) { int32 varNo; if (argc != 2) { - DebugPrintf("Usage: %s number\n", argv[0]); + debugPrintf("Usage: %s number\n", argv[0]); return true; } @@ -676,9 +676,9 @@ bool Debugger::Cmd_HideVar(int argc, const char **argv) { if (showVarNo < MAX_SHOWVARS) { // We've found 'varNo' in the list - clear this slot _showVar[showVarNo] = 0; - DebugPrintf("var(%d) removed from watch-list\n", varNo); + debugPrintf("var(%d) removed from watch-list\n", varNo); } else - DebugPrintf("Sorry - can't find var(%d) in the list\n", varNo); + debugPrintf("Sorry - can't find var(%d) in the list\n", varNo); return true; } @@ -687,13 +687,13 @@ bool Debugger::Cmd_Version(int argc, const char **argv) { // This function used to print more information, but nothing we // particularly care about. - DebugPrintf("\"Broken Sword II\" (c) Revolution Software 1997.\n"); + debugPrintf("\"Broken Sword II\" (c) Revolution Software 1997.\n"); return true; } bool Debugger::Cmd_AnimTest(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Usage: %s value\n", argv[0]); + debugPrintf("Usage: %s value\n", argv[0]); return true; } @@ -703,13 +703,13 @@ bool Debugger::Cmd_AnimTest(int argc, const char **argv) { // Same as typing "VAR 912 <value>" at the console varSet(912, atoi(argv[1])); - DebugPrintf("Setting flag 'system_testing_anims'\n"); + debugPrintf("Setting flag 'system_testing_anims'\n"); return true; } bool Debugger::Cmd_TextTest(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Usage: %s value\n", argv[0]); + debugPrintf("Usage: %s value\n", argv[0]); return true; } @@ -721,14 +721,14 @@ bool Debugger::Cmd_TextTest(int argc, const char **argv) { _displayTextNumbers = true; - DebugPrintf("Setting flag 'system_testing_text'\n"); - DebugPrintf("Text numbers on\n"); + debugPrintf("Setting flag 'system_testing_text'\n"); + debugPrintf("Text numbers on\n"); return true; } bool Debugger::Cmd_LineTest(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Usage: %s value1 value2\n", argv[0]); + debugPrintf("Usage: %s value1 value2\n", argv[0]); return true; } @@ -743,24 +743,24 @@ bool Debugger::Cmd_LineTest(int argc, const char **argv) { _displayTextNumbers = true; - DebugPrintf("Setting flag 'system_testing_text'\n"); - DebugPrintf("Setting flag 'system_test_line_no'\n"); - DebugPrintf("Text numbers on\n"); + debugPrintf("Setting flag 'system_testing_text'\n"); + debugPrintf("Setting flag 'system_test_line_no'\n"); + debugPrintf("Text numbers on\n"); return true; } bool Debugger::Cmd_Events(int argc, const char **argv) { EventUnit *eventList = _vm->_logic->getEventList(); - DebugPrintf("EVENT LIST:\n"); + debugPrintf("EVENT LIST:\n"); for (uint32 i = 0; i < MAX_events; i++) { if (eventList[i].id) { uint32 target = eventList[i].id; uint32 script = eventList[i].interact_id; - DebugPrintf("slot %2d: id = %s (%d)\n", i, _vm->_resman->fetchName(target), target); - DebugPrintf(" script = %s (%d) pos %d\n", _vm->_resman->fetchName(script / 65536), script / 65536, script % 65536); + debugPrintf("slot %2d: id = %s (%d)\n", i, _vm->_resman->fetchName(target), target); + debugPrintf(" script = %s (%d) pos %d\n", _vm->_resman->fetchName(script / 65536), script / 65536, script % 65536); } } @@ -771,28 +771,28 @@ bool Debugger::Cmd_Sfx(int argc, const char **argv) { _vm->_wantSfxDebug = !_vm->_wantSfxDebug; if (_vm->_wantSfxDebug) - DebugPrintf("SFX logging activated\n"); + debugPrintf("SFX logging activated\n"); else - DebugPrintf("SFX logging deactivated\n"); + debugPrintf("SFX logging deactivated\n"); return true; } bool Debugger::Cmd_English(int argc, const char **argv) { _vm->initializeFontResourceFlags(DEFAULT_TEXT); - DebugPrintf("Default fonts selected\n"); + debugPrintf("Default fonts selected\n"); return true; } bool Debugger::Cmd_Finnish(int argc, const char **argv) { _vm->initializeFontResourceFlags(FINNISH_TEXT); - DebugPrintf("Finnish fonts selected\n"); + debugPrintf("Finnish fonts selected\n"); return true; } bool Debugger::Cmd_Polish(int argc, const char **argv) { _vm->initializeFontResourceFlags(POLISH_TEXT); - DebugPrintf("Polish fonts selected\n"); + debugPrintf("Polish fonts selected\n"); return true; } diff --git a/engines/sword2/resman.cpp b/engines/sword2/resman.cpp index a0561641d7..44027fd281 100644 --- a/engines/sword2/resman.cpp +++ b/engines/sword2/resman.cpp @@ -38,7 +38,7 @@ #include "sword2/screen.h" #include "sword2/sound.h" -#define Debug_Printf _vm->_debugger->DebugPrintf +#define Debug_Printf _vm->_debugger->debugPrintf namespace Sword2 { diff --git a/engines/sword2/sound.cpp b/engines/sword2/sound.cpp index aea33e99e3..1e1687b1e6 100644 --- a/engines/sword2/sound.cpp +++ b/engines/sword2/sound.cpp @@ -49,7 +49,7 @@ #include "audio/decoders/wave.h" #include "audio/decoders/xa.h" -#define Debug_Printf _vm->_debugger->DebugPrintf +#define Debug_Printf _vm->_debugger->debugPrintf namespace Sword2 { diff --git a/engines/teenagent/console.cpp b/engines/teenagent/console.cpp index 13d5c687ce..2304829782 100644 --- a/engines/teenagent/console.cpp +++ b/engines/teenagent/console.cpp @@ -26,24 +26,24 @@ namespace TeenAgent { Console::Console(TeenAgentEngine *engine) : _engine(engine) { - DCmd_Register("enable_object", WRAP_METHOD(Console, enableObject)); - DCmd_Register("disable_object", WRAP_METHOD(Console, enableObject)); - DCmd_Register("set_ons", WRAP_METHOD(Console, setOns)); - DCmd_Register("set_music", WRAP_METHOD(Console, setMusic)); - DCmd_Register("animation", WRAP_METHOD(Console, playAnimation)); - DCmd_Register("actor_animation", WRAP_METHOD(Console, playActorAnimation)); - DCmd_Register("call", WRAP_METHOD(Console, call)); + registerCmd("enable_object", WRAP_METHOD(Console, enableObject)); + registerCmd("disable_object", WRAP_METHOD(Console, enableObject)); + registerCmd("set_ons", WRAP_METHOD(Console, setOns)); + registerCmd("set_music", WRAP_METHOD(Console, setMusic)); + registerCmd("animation", WRAP_METHOD(Console, playAnimation)); + registerCmd("actor_animation", WRAP_METHOD(Console, playActorAnimation)); + registerCmd("call", WRAP_METHOD(Console, call)); } bool Console::enableObject(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("usage: %s object_id [scene_id]\n", argv[0]); + debugPrintf("usage: %s object_id [scene_id]\n", argv[0]); return true; } int id = atoi(argv[1]); if (id < 0) { - DebugPrintf("object id %d is invalid\n", id); + debugPrintf("object id %d is invalid\n", id); return true; } @@ -51,7 +51,7 @@ bool Console::enableObject(int argc, const char **argv) { if (argc > 2) { scene_id = atoi(argv[2]); if (scene_id < 0) { - DebugPrintf("scene id %d is invalid\n", scene_id); + debugPrintf("scene id %d is invalid\n", scene_id); return true; } } @@ -66,20 +66,20 @@ bool Console::enableObject(int argc, const char **argv) { bool Console::setOns(int argc, const char **argv) { if (argc < 3) { - DebugPrintf("usage: %s index(0-3) value [scene_id]\n", argv[0]); + debugPrintf("usage: %s index(0-3) value [scene_id]\n", argv[0]); return true; } int index = atoi(argv[1]); if (index < 0 || index > 3) { - DebugPrintf("index %d is invalid\n", index); + debugPrintf("index %d is invalid\n", index); return true; } int value = 0; value = atoi(argv[2]); if (value < 0) { - DebugPrintf("invalid value\n"); + debugPrintf("invalid value\n"); return true; } @@ -87,7 +87,7 @@ bool Console::setOns(int argc, const char **argv) { if (argc > 3) { scene_id = atoi(argv[3]); if (scene_id < 0) { - DebugPrintf("scene id %d is invalid\n", scene_id); + debugPrintf("scene id %d is invalid\n", scene_id); return true; } } @@ -98,13 +98,13 @@ bool Console::setOns(int argc, const char **argv) { bool Console::setMusic(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("usage: %s index(1-11)\n", argv[0]); + debugPrintf("usage: %s index(1-11)\n", argv[0]); return true; } int index = atoi(argv[1]); if (index <= 0 || index > 11) { - DebugPrintf("invalid value\n"); + debugPrintf("invalid value\n"); return true; } @@ -114,14 +114,14 @@ bool Console::setMusic(int argc, const char **argv) { bool Console::playAnimation(int argc, const char **argv) { if (argc < 3) { - DebugPrintf("usage: %s id slot(0-3)\n", argv[0]); + debugPrintf("usage: %s id slot(0-3)\n", argv[0]); return true; } int id = atoi(argv[1]); int slot = atoi(argv[2]); if (id < 0 || slot < 0 || slot > 3) { - DebugPrintf("invalid slot or animation id\n"); + debugPrintf("invalid slot or animation id\n"); return true; } @@ -131,13 +131,13 @@ bool Console::playAnimation(int argc, const char **argv) { bool Console::playActorAnimation(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("usage: %s id\n", argv[0]); + debugPrintf("usage: %s id\n", argv[0]); return true; } int id = atoi(argv[1]); if (id < 0) { - DebugPrintf("invalid animation id\n"); + debugPrintf("invalid animation id\n"); return true; } @@ -147,18 +147,18 @@ bool Console::playActorAnimation(int argc, const char **argv) { bool Console::call(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("usage: %s 0xHEXADDR\n", argv[0]); + debugPrintf("usage: %s 0xHEXADDR\n", argv[0]); return true; } uint addr; if (sscanf(argv[1], "0x%x", &addr) != 1) { - DebugPrintf("invalid address\n"); + debugPrintf("invalid address\n"); return true; } if (!_engine->processCallback(addr)) - DebugPrintf("calling callback %04x failed\n", addr); + debugPrintf("calling callback %04x failed\n", addr); return true; } diff --git a/engines/tinsel/debugger.cpp b/engines/tinsel/debugger.cpp index 45e3a05903..1dbb19d383 100644 --- a/engines/tinsel/debugger.cpp +++ b/engines/tinsel/debugger.cpp @@ -62,11 +62,11 @@ int strToInt(const char *s) { //----------------- CONSOLE CLASS --------------------- Console::Console() : GUI::Debugger() { - DCmd_Register("item", WRAP_METHOD(Console, cmd_item)); - DCmd_Register("scene", WRAP_METHOD(Console, cmd_scene)); - DCmd_Register("music", WRAP_METHOD(Console, cmd_music)); - DCmd_Register("sound", WRAP_METHOD(Console, cmd_sound)); - DCmd_Register("string", WRAP_METHOD(Console, cmd_string)); + registerCmd("item", WRAP_METHOD(Console, cmd_item)); + registerCmd("scene", WRAP_METHOD(Console, cmd_scene)); + registerCmd("music", WRAP_METHOD(Console, cmd_music)); + registerCmd("sound", WRAP_METHOD(Console, cmd_sound)); + registerCmd("string", WRAP_METHOD(Console, cmd_string)); } Console::~Console() { @@ -74,8 +74,8 @@ Console::~Console() { bool Console::cmd_item(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("%s item_number\n", argv[0]); - DebugPrintf("Sets the currently active 'held' item\n"); + debugPrintf("%s item_number\n", argv[0]); + debugPrintf("Sets the currently active 'held' item\n"); return true; } @@ -86,14 +86,14 @@ bool Console::cmd_item(int argc, const char **argv) { bool Console::cmd_scene(int argc, const char **argv) { if (argc < 1 || argc > 3) { - DebugPrintf("%s [scene_number [entry number]]\n", argv[0]); - DebugPrintf("If no parameters are given, prints the current scene.\n"); - DebugPrintf("Otherwise changes to the specified scene number. Entry number defaults to 1 if none provided\n"); + debugPrintf("%s [scene_number [entry number]]\n", argv[0]); + debugPrintf("If no parameters are given, prints the current scene.\n"); + debugPrintf("Otherwise changes to the specified scene number. Entry number defaults to 1 if none provided\n"); return true; } if (argc == 1) { - DebugPrintf("Current scene is %d\n", GetSceneHandle() >> SCNHANDLE_SHIFT); + debugPrintf("Current scene is %d\n", GetSceneHandle() >> SCNHANDLE_SHIFT); return true; } @@ -106,15 +106,15 @@ bool Console::cmd_scene(int argc, const char **argv) { bool Console::cmd_music(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("%s track_number or %s -offset\n", argv[0], argv[0]); - DebugPrintf("Plays the MIDI track number provided, or the offset inside midi.dat\n"); - DebugPrintf("A positive number signifies a track number, whereas a negative signifies an offset\n"); + debugPrintf("%s track_number or %s -offset\n", argv[0], argv[0]); + debugPrintf("Plays the MIDI track number provided, or the offset inside midi.dat\n"); + debugPrintf("A positive number signifies a track number, whereas a negative signifies an offset\n"); return true; } int param = strToInt(argv[1]); if (param == 0) { - DebugPrintf("Track number/offset can't be 0!\n"); + debugPrintf("Track number/offset can't be 0!\n"); } else if (param > 0) { // Track provided PlayMidiSequence(GetTrackOffset(param - 1), false); @@ -128,8 +128,8 @@ bool Console::cmd_music(int argc, const char **argv) { bool Console::cmd_sound(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("%s id\n", argv[0]); - DebugPrintf("Plays the sound with the given ID\n"); + debugPrintf("%s id\n", argv[0]); + debugPrintf("Plays the sound with the given ID\n"); return true; } @@ -140,7 +140,7 @@ bool Console::cmd_sound(int argc, const char **argv) { else _vm->_sound->playSample(id, 0, false, 0, 0, PRIORITY_TALK, Audio::Mixer::kSpeechSoundType); } else { - DebugPrintf("Sample %d does not exist!\n", id); + debugPrintf("Sample %d does not exist!\n", id); } return true; @@ -148,15 +148,15 @@ bool Console::cmd_sound(int argc, const char **argv) { bool Console::cmd_string(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("%s id\n", argv[0]); - DebugPrintf("Prints the string with the given ID\n"); + debugPrintf("%s id\n", argv[0]); + debugPrintf("Prints the string with the given ID\n"); return true; } char tmp[TBUFSZ]; int id = strToInt(argv[1]); LoadStringRes(id, tmp, TBUFSZ); - DebugPrintf("%s\n", tmp); + debugPrintf("%s\n", tmp); return true; } diff --git a/engines/toltecs/console.cpp b/engines/toltecs/console.cpp index f84a8e3c44..5a0c66c7b0 100644 --- a/engines/toltecs/console.cpp +++ b/engines/toltecs/console.cpp @@ -31,8 +31,8 @@ namespace Toltecs { Console::Console(ToltecsEngine *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("room", WRAP_METHOD(Console, Cmd_Room)); - DCmd_Register("dump", WRAP_METHOD(Console, Cmd_Dump)); + registerCmd("room", WRAP_METHOD(Console, Cmd_Room)); + registerCmd("dump", WRAP_METHOD(Console, Cmd_Dump)); } Console::~Console() { @@ -40,10 +40,10 @@ Console::~Console() { bool Console::Cmd_Room(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Current room number is %d\n", _vm->_sceneResIndex); + debugPrintf("Current room number is %d\n", _vm->_sceneResIndex); #if 0 - DebugPrintf("Calling this command with the room number changes the room\n"); - DebugPrintf("WARNING: It's a bad idea to warp to rooms with this, as the room object scripts are not loaded\n"); + debugPrintf("Calling this command with the room number changes the room\n"); + debugPrintf("WARNING: It's a bad idea to warp to rooms with this, as the room object scripts are not loaded\n"); #endif return true; #if 0 @@ -65,13 +65,13 @@ bool Console::Cmd_Room(int argc, const char **argv) { bool Console::Cmd_Dump(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: dump <resource number>\n"); + debugPrintf("Usage: dump <resource number>\n"); return true; } int resNum = atoi(argv[1]); _vm->_arc->dump(resNum); - DebugPrintf("Resource %d has been dumped to disk\n", resNum); + debugPrintf("Resource %d has been dumped to disk\n", resNum); return true; } diff --git a/engines/tony/debugger.cpp b/engines/tony/debugger.cpp index 22c218a19c..e192c53d2b 100644 --- a/engines/tony/debugger.cpp +++ b/engines/tony/debugger.cpp @@ -28,9 +28,9 @@ namespace Tony { Debugger::Debugger() : GUI::Debugger() { - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("scene", WRAP_METHOD(Debugger, Cmd_Scene)); - DCmd_Register("dirty_rects", WRAP_METHOD(Debugger, Cmd_DirtyRects)); + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("scene", WRAP_METHOD(Debugger, Cmd_Scene)); + registerCmd("dirty_rects", WRAP_METHOD(Debugger, Cmd_DirtyRects)); } static int strToInt(const char *s) { @@ -82,13 +82,13 @@ void DebugChangeScene(CORO_PARAM, const void *param) { */ bool Debugger::Cmd_Scene(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: %s <scene number> [<x> <y>]\n", argv[0]); + debugPrintf("Usage: %s <scene number> [<x> <y>]\n", argv[0]); return true; } int sceneNumber = strToInt(argv[1]); if (sceneNumber >= g_vm->_theBoxes.getLocBoxesCount()) { - DebugPrintf("Invalid scene\n"); + debugPrintf("Invalid scene\n"); return true; } @@ -118,7 +118,7 @@ bool Debugger::Cmd_Scene(int argc, const char **argv) { */ bool Debugger::Cmd_DirtyRects(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Usage; %s [on | off]\n", argv[0]); + debugPrintf("Usage; %s [on | off]\n", argv[0]); return true; } else { g_vm->_window.showDirtyRects(strcmp(argv[1], "on") == 0); diff --git a/engines/tony/detection_tables.h b/engines/tony/detection_tables.h index ce4651f0ab..28dcaac752 100644 --- a/engines/tony/detection_tables.h +++ b/engines/tony/detection_tables.h @@ -217,7 +217,7 @@ static const TonyGameDescription gameDescriptions[] = { // Tony Tough German "Shoe Box", reported in bug #3582420 { "tony", - 0, + 0, { {"roasted.mpr", 0, "06203dbbc85fdd1e6dc8fc211c1a6207", 135911071}, {"roasted.mpc", 0, "bc3471f098e591dc509dcad401a8d8a5", 389554}, @@ -230,6 +230,23 @@ static const TonyGameDescription gameDescriptions[] = { }, }, + { + // Tony Tough Russian, reported in bug #6589 + { + "tony", + 0, + { + {"roasted.mpr", 0, "06203dbbc85fdd1e6dc8fc211c1a6207", 135911071}, + {"roasted.mpc", 0, "377d6e24adeedc6c5c09c31b92231218", 391536}, + AD_LISTEND + }, + Common::RU_RUS, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO1(GUIO_NONE) + }, + }, + { AD_TABLE_END_MARKER } }; diff --git a/engines/toon/character.cpp b/engines/toon/character.cpp index cab31795f7..51e8dee19f 100644 --- a/engines/toon/character.cpp +++ b/engines/toon/character.cpp @@ -1059,12 +1059,14 @@ void Character::playAnim(int32 animId, int32 unused, int32 flags) { _specialAnim->loadAnimation(animName); _animSpecialId = animId; - - _animationInstance->setAnimation(_specialAnim); - _animationInstance->setAnimationRange(0, _specialAnim->_numFrames - 1); - _animationInstance->reset(); - _animationInstance->stopAnimation(); - _animationInstance->setLooping(false); + + if (_animationInstance) { + _animationInstance->setAnimation(_specialAnim); + _animationInstance->setAnimationRange(0, _specialAnim->_numFrames - 1); + _animationInstance->reset(); + _animationInstance->stopAnimation(); + _animationInstance->setLooping(false); + } } int32 Character::getAnimFlag() { diff --git a/engines/touche/console.cpp b/engines/touche/console.cpp index c4272038dc..472863c817 100644 --- a/engines/touche/console.cpp +++ b/engines/touche/console.cpp @@ -26,8 +26,8 @@ namespace Touche { ToucheConsole::ToucheConsole(ToucheEngine *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("startMusic", WRAP_METHOD(ToucheConsole, Cmd_StartMusic)); - DCmd_Register("stopMusic", WRAP_METHOD(ToucheConsole, Cmd_StopMusic)); + registerCmd("startMusic", WRAP_METHOD(ToucheConsole, Cmd_StartMusic)); + registerCmd("stopMusic", WRAP_METHOD(ToucheConsole, Cmd_StopMusic)); } ToucheConsole::~ToucheConsole() { @@ -35,7 +35,7 @@ ToucheConsole::~ToucheConsole() { bool ToucheConsole::Cmd_StartMusic(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Usage: startMusic <num>\n"); + debugPrintf("Usage: startMusic <num>\n"); return true; } diff --git a/engines/touche/menu.cpp b/engines/touche/menu.cpp index 19c10af8de..b94776eee5 100644 --- a/engines/touche/menu.cpp +++ b/engines/touche/menu.cpp @@ -31,96 +31,6 @@ namespace Touche { -enum ActionId { - kActionNone, - - // settings menu - kActionLoadMenu, - kActionSaveMenu, - kActionRestartGame, - kActionPlayGame, - kActionQuitGame, - kActionTextOnly, - kActionVoiceOnly, - kActionTextAndVoice, - kActionLowerVolume, - kActionUpperVolume, - - // saveLoad menu - kActionGameState1, - kActionGameState2, - kActionGameState3, - kActionGameState4, - kActionGameState5, - kActionGameState6, - kActionGameState7, - kActionGameState8, - kActionGameState9, - kActionGameState10, - kActionScrollUpSaves, - kActionScrollDownSaves, - kActionPerformSaveLoad, - kActionCancelSaveLoad -}; - -enum MenuMode { - kMenuSettingsMode = 0, - kMenuLoadStateMode, - kMenuSaveStateMode -}; - -enum ButtonFlags { - kButtonBorder = 1 << 0, - kButtonText = 1 << 1, - kButtonArrow = 1 << 2 -}; - -struct Button { - int x, y; - int w, h; - ActionId action; - int data; - uint8 flags; -}; - -struct MenuData { - MenuMode mode; - Button *buttonsTable; - uint buttonsCount; - bool quit; - bool exit; - char saveLoadDescriptionsTable[kMaxSaveStates][33]; - - void removeLastCharFromDescription(int slot) { - char *description = saveLoadDescriptionsTable[slot]; - int descriptionLen = strlen(description); - if (descriptionLen > 0) { - --descriptionLen; - description[descriptionLen] = 0; - } - } - - void addCharToDescription(int slot, char chr) { - char *description = saveLoadDescriptionsTable[slot]; - int descriptionLen = strlen(description); - if (descriptionLen < 32 && Common::isPrint(chr)) { - description[descriptionLen] = chr; - description[descriptionLen + 1] = 0; - } - } - - const Button *findButtonUnderCursor(int cursorX, int cursorY) const { - for (uint i = 0; i < buttonsCount; ++i) { - const Button *button = &buttonsTable[i]; - if (cursorX >= button->x && cursorX < button->x + button->w && - cursorY >= button->y && cursorY < button->y + button->h) { - return button; - } - } - return 0; - } -}; - static void drawArrow(uint8 *dst, int dstPitch, int x, int y, int delta, uint8 color) { static const int8 arrowCoordsTable[7][4] = { { 5, 0, 9, 0 }, @@ -140,25 +50,24 @@ static void drawArrow(uint8 *dst, int dstPitch, int x, int y, int delta, uint8 c } } -void ToucheEngine::drawButton(void *button) { - Button *b = (Button *)button; - if (b->flags & kButtonBorder) { - Graphics::drawRect(_offscreenBuffer, kScreenWidth, b->x, b->y, b->w, b->h, 0xF7, 0xF9); +void ToucheEngine::drawButton(Button *button) { + if (button->flags & kButtonBorder) { + Graphics::drawRect(_offscreenBuffer, kScreenWidth, button->x, button->y, button->w, button->h, 0xF7, 0xF9); } - if (b->flags & kButtonText) { - if (b->data != 0) { - const char *str = getString(b->data); - const int w = getStringWidth(b->data); + if (button->flags & kButtonText) { + if (button->data != 0) { + const char *str = getString(button->data); + const int w = getStringWidth(button->data); const int h = kTextHeight; - const int x = b->x + (b->w - w) / 2; - const int y = b->y + (b->h - h) / 2; + const int x = button->x + (button->w - w) / 2; + const int y = button->y + (button->h - h) / 2; Graphics::drawString16(_offscreenBuffer, kScreenWidth, 0xFF, x, y, str); } } - if (b->flags & kButtonArrow) { + if (button->flags & kButtonArrow) { int dx = 0; int dy = 0; - switch (b->data) { + switch (button->data) { case 2000: // up arrow dx = 1; dy = 2; @@ -168,8 +77,8 @@ void ToucheEngine::drawButton(void *button) { dy = -2; break; } - const int x = b->x + b->w / 2; - const int y = b->y + b->h / 2; + const int x = button->x + button->w / 2; + const int y = button->y + button->h / 2; drawArrow(_offscreenBuffer, kScreenWidth, x, y + dy + 1, dx, 0xD2); drawArrow(_offscreenBuffer, kScreenWidth, x, y + dy, dx, 0xFF); } @@ -253,49 +162,47 @@ static void setupMenu(MenuMode mode, MenuData *menuData) { } } -void ToucheEngine::redrawMenu(void *menu) { - MenuData *menuData = (MenuData *)menu; +void ToucheEngine::redrawMenu(MenuData *menu) { Graphics::fillRect(_offscreenBuffer, kScreenWidth, 90, 102, 460, 196, 0xF8); Graphics::drawRect(_offscreenBuffer, kScreenWidth, 90, 102, 460, 196, 0xF7, 0xF9); Graphics::drawRect(_offscreenBuffer, kScreenWidth, 106, 118, 340, 164, 0xF9, 0xF7); - switch (menuData->mode) { + switch (menu->mode) { case kMenuSettingsMode: drawVolumeSlideBar(_offscreenBuffer, kScreenWidth, getMusicVolume()); - menuData->buttonsTable[5].data = 0; - menuData->buttonsTable[6].data = 0; - menuData->buttonsTable[7].data = 0; - menuData->buttonsTable[5 + _talkTextMode].data = -86; + menu->buttonsTable[5].data = 0; + menu->buttonsTable[6].data = 0; + menu->buttonsTable[7].data = 0; + menu->buttonsTable[5 + _talkTextMode].data = -86; break; case kMenuLoadStateMode: case kMenuSaveStateMode: - drawSaveGameStateDescriptions(_offscreenBuffer, kScreenWidth, menuData, _saveLoadCurrentPage, _saveLoadCurrentSlot); + drawSaveGameStateDescriptions(_offscreenBuffer, kScreenWidth, menu, _saveLoadCurrentPage, _saveLoadCurrentSlot); break; } - for (uint i = 0; i < menuData->buttonsCount; ++i) { - drawButton(&menuData->buttonsTable[i]); + for (uint i = 0; i < menu->buttonsCount; ++i) { + drawButton(&menu->buttonsTable[i]); } } -void ToucheEngine::handleMenuAction(void *menu, int actionId) { - MenuData *menuData = (MenuData *)menu; +void ToucheEngine::handleMenuAction(MenuData *menu, int actionId) { switch (actionId) { case kActionLoadMenu: - menuData->mode = kMenuLoadStateMode; + menu->mode = kMenuLoadStateMode; break; case kActionSaveMenu: _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); - menuData->mode = kMenuSaveStateMode; + menu->mode = kMenuSaveStateMode; break; case kActionRestartGame: restart(); - menuData->quit = true; + menu->quit = true; break; case kActionPlayGame: - menuData->quit = true; + menu->quit = true; break; case kActionQuitGame: quitGame(); - menuData->quit = true; + menu->quit = true; break; case kActionTextOnly: _talkTextMode = kTalkModeTextOnly; @@ -327,23 +234,23 @@ void ToucheEngine::handleMenuAction(void *menu, int actionId) { _saveLoadCurrentSlot = _saveLoadCurrentPage * 10 + (_saveLoadCurrentSlot % 10); break; case kActionPerformSaveLoad: - if (menuData->mode == kMenuLoadStateMode) { + if (menu->mode == kMenuLoadStateMode) { if (loadGameState(_saveLoadCurrentSlot).getCode() == Common::kNoError) { - menuData->quit = true; + menu->quit = true; } - } else if (menuData->mode == kMenuSaveStateMode) { + } else if (menu->mode == kMenuSaveStateMode) { _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); - const char *description = menuData->saveLoadDescriptionsTable[_saveLoadCurrentSlot]; + const char *description = menu->saveLoadDescriptionsTable[_saveLoadCurrentSlot]; if (strlen(description) > 0) { if (saveGameState(_saveLoadCurrentSlot, description).getCode() == Common::kNoError) { - menuData->quit = true; + menu->quit = true; } } } break; case kActionCancelSaveLoad: _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); - menuData->mode = kMenuSettingsMode; + menu->mode = kMenuSettingsMode; break; default: if (actionId >= kActionGameState1 && actionId <= kActionGameState10) { diff --git a/engines/touche/resource.cpp b/engines/touche/resource.cpp index 16a95d307f..467d2bed90 100644 --- a/engines/touche/resource.cpp +++ b/engines/touche/resource.cpp @@ -150,38 +150,38 @@ void ToucheEngine::res_allocateTables() { void ToucheEngine::res_deallocateTables() { free(_textData); - _textData = 0; + _textData = nullptr; free(_backdropBuffer); - _backdropBuffer = 0; + _backdropBuffer = nullptr; free(_menuKitData); - _menuKitData = 0; + _menuKitData = nullptr; free(_convKitData); - _convKitData = 0; + _convKitData = nullptr; for (int i = 0; i < NUM_SEQUENCES; ++i) { free(_sequenceDataTable[i]); - _sequenceDataTable[i] = 0; + _sequenceDataTable[i] = nullptr; } free(_programData); - _programData = 0; + _programData = nullptr; free(_mouseData); - _mouseData = 0; + _mouseData = nullptr; free(_iconData); - _iconData = 0; + _iconData = nullptr; for (int i = 0; i < NUM_SPRITES; ++i) { free(_spritesTable[i].ptr); - _spritesTable[i].ptr = 0; + _spritesTable[i].ptr = nullptr; } free(_offscreenBuffer); - _offscreenBuffer = 0; + _offscreenBuffer = nullptr; } uint32 ToucheEngine::res_getDataOffset(ResourceType type, int num, uint32 *size) { diff --git a/engines/touche/touche.cpp b/engines/touche/touche.cpp index 09697d0e4a..ff4f41f44d 100644 --- a/engines/touche/touche.cpp +++ b/engines/touche/touche.cpp @@ -46,32 +46,32 @@ namespace Touche { ToucheEngine::ToucheEngine(OSystem *system, Common::Language language) - : Engine(system), _midiPlayer(0), _language(language), _rnd("touche") { + : Engine(system), _midiPlayer(nullptr), _language(language), _rnd("touche") { _saveLoadCurrentPage = 0; _saveLoadCurrentSlot = 0; _hideInventoryTexts = false; _numOpcodes = 0; _compressedSpeechData = 0; - _textData = 0; - _backdropBuffer = 0; - _menuKitData = 0; - _convKitData = 0; + _textData = nullptr; + _backdropBuffer = nullptr; + _menuKitData = nullptr; + _convKitData = nullptr; for (int i = 0; i < NUM_SEQUENCES; i++) - _sequenceDataTable[i] = 0; + _sequenceDataTable[i] = nullptr; - _programData = 0; + _programData = nullptr; _programDataSize = 0; - _mouseData = 0; - _iconData = 0; + _mouseData = nullptr; + _iconData = nullptr; _currentBitmapWidth = 0; _currentBitmapHeight = 0; _currentImageWidth = 0; _currentImageHeight = 0; _roomWidth = 0; - _programTextDataPtr = 0; - _offscreenBuffer = 0; + _programTextDataPtr = nullptr; + _offscreenBuffer = nullptr; _screenRect = Common::Rect(kScreenWidth, kScreenHeight); _roomAreaRect = Common::Rect(kScreenWidth, kRoomHeight); @@ -124,11 +124,11 @@ ToucheEngine::ToucheEngine(OSystem *system, Common::Language language) _script.opcodeNum = 0; _script.dataOffset = 0; _script.keyCharNum = 0; - _script.dataPtr = 0; - _script.stackDataPtr = 0; - _script.stackDataBasePtr = 0; + _script.dataPtr = nullptr; + _script.stackDataPtr = nullptr; + _script.stackDataBasePtr = nullptr; _script.quitFlag = 0; - _opcodesTable = 0; + _opcodesTable = nullptr; for (uint i = 0; i < NUM_SPRITES; i++) memset(&_spritesTable[i], 0, sizeof(SpriteData)); @@ -138,10 +138,10 @@ ToucheEngine::ToucheEngine(OSystem *system, Common::Language language) _talkListEnd = 0; _talkListCurrent = 0; - _talkTextRectDefined = 0; - _talkTextDisplayed = 0; - _talkTextInitialized = 0; - _skipTalkText = 0; + _talkTextRectDefined = false; + _talkTextDisplayed = false; + _talkTextInitialized = false; + _skipTalkText = false; _talkTextSpeed = 0; _keyCharTalkCounter = 0; _talkTableLastTalkingKeyChar = 0; @@ -151,14 +151,14 @@ ToucheEngine::ToucheEngine(OSystem *system, Common::Language language) for (uint i = 0; i < NUM_TALK_ENTRIES; i++) memset(&_talkTable[i], 0, sizeof(TalkEntry)); - _conversationChoicesUpdated = 0; + _conversationChoicesUpdated = false; _conversationReplyNum = 0; - _conversationEnded = 0; + _conversationEnded = false; _conversationNum = 0; _scrollConversationChoiceOffset = 0; _currentConversation = 0; - _disableConversationScript = 0; - _conversationAreaCleared = 0; + _disableConversationScript = false; + _conversationAreaCleared = false; for (uint i = 0; i < NUM_CONVERSATION_CHOICES; i++) memset(&_conversationChoicesTable[i], 0, sizeof(ConversationChoice)); @@ -167,6 +167,26 @@ ToucheEngine::ToucheEngine(OSystem *system, Common::Language language) _sortedKeyCharsTable[i] = 0; _currentKeyCharNum = 0; + _inp_leftMouseButtonPressed = false; + _inp_rightMouseButtonPressed = false; + _disabledInputCounter = 0; + _gameState = kGameStateNone; + _displayQuitDialog = false; + _newMusicNum = 0; + _currentMusicNum = 0; + _newSoundNum = 0; + _newSoundDelay = 0; + _newSoundPriority = 0; + for (int i = 0; i < 3; ++i) { + _inventoryStateTable[i].displayOffset = 0; + _inventoryStateTable[i].lastItem = 0; + _inventoryStateTable[i].itemsPerLine = 0; + _inventoryStateTable[i].itemsList = nullptr; + } + _inventoryVar1 = nullptr; + _inventoryVar2 = nullptr; + _currentCursorObject = 0; + _talkTextMode = 0; } ToucheEngine::~ToucheEngine() { @@ -3094,12 +3114,12 @@ void ToucheEngine::buildWalkPath(int dstPosX, int dstPosY, int keyChar) { for (uint i = 0; i < _programWalkTable.size(); ++i) { const ProgramWalkData *pwd = &_programWalkTable[i]; if ((pwd->point1 & 0x4000) == 0) { - int distance = 32000; ProgramPointData *pts1 = &_programPointsTable[pwd->point1]; ProgramPointData *pts2 = &_programPointsTable[pwd->point2]; if (pts1->order != 0) { int dx = pts2->x - pts1->x; int dy = pts2->y - pts1->y; + int distance = 32000; if (dx == 0) { if (dstPosY > MIN(pts2->y, pts1->y) && dstPosY < MAX(pts2->y, pts1->y)) { int d = ABS(dstPosX - pts1->x); diff --git a/engines/touche/touche.h b/engines/touche/touche.h index 3da33f593b..20bf723553 100644 --- a/engines/touche/touche.h +++ b/engines/touche/touche.h @@ -346,16 +346,108 @@ enum StringType { kStringTypeConversation }; -void readGameStateDescription(Common::ReadStream *f, char *description, int len); -Common::String generateGameStateFileName(const char *target, int slot, bool prefixOnly = false); -int getGameStateFileSlot(const char *filename); - enum GameState { kGameStateGameLoop, kGameStateOptionsDialog, - kGameStateQuitDialog + kGameStateQuitDialog, + kGameStateNone +}; + +enum ActionId { + kActionNone, + + // settings menu + kActionLoadMenu, + kActionSaveMenu, + kActionRestartGame, + kActionPlayGame, + kActionQuitGame, + kActionTextOnly, + kActionVoiceOnly, + kActionTextAndVoice, + kActionLowerVolume, + kActionUpperVolume, + + // saveLoad menu + kActionGameState1, + kActionGameState2, + kActionGameState3, + kActionGameState4, + kActionGameState5, + kActionGameState6, + kActionGameState7, + kActionGameState8, + kActionGameState9, + kActionGameState10, + kActionScrollUpSaves, + kActionScrollDownSaves, + kActionPerformSaveLoad, + kActionCancelSaveLoad +}; + +enum MenuMode { + kMenuSettingsMode = 0, + kMenuLoadStateMode, + kMenuSaveStateMode +}; + +enum ButtonFlags { + kButtonBorder = 1 << 0, + kButtonText = 1 << 1, + kButtonArrow = 1 << 2 }; +struct Button { + int x, y; + int w, h; + ActionId action; + int data; + uint8 flags; +}; + +struct MenuData { + MenuMode mode; + Button *buttonsTable; + uint buttonsCount; + bool quit; + bool exit; + char saveLoadDescriptionsTable[kMaxSaveStates][33]; + + void removeLastCharFromDescription(int slot) { + char *description = saveLoadDescriptionsTable[slot]; + int descriptionLen = strlen(description); + if (descriptionLen > 0) { + --descriptionLen; + description[descriptionLen] = 0; + } + } + + void addCharToDescription(int slot, char chr) { + char *description = saveLoadDescriptionsTable[slot]; + int descriptionLen = strlen(description); + if (descriptionLen < 32 && Common::isPrint(chr)) { + description[descriptionLen] = chr; + description[descriptionLen + 1] = 0; + } + } + + const Button *findButtonUnderCursor(int cursorX, int cursorY) const { + for (uint i = 0; i < buttonsCount; ++i) { + const Button *button = &buttonsTable[i]; + if (cursorX >= button->x && cursorX < button->x + button->w && + cursorY >= button->y && cursorY < button->y + button->h) { + return button; + } + } + return 0; + } +}; + + +void readGameStateDescription(Common::ReadStream *f, char *description, int len); +Common::String generateGameStateFileName(const char *target, int slot, bool prefixOnly = false); +int getGameStateFileSlot(const char *filename); + class MidiPlayer; class ToucheEngine: public Engine { @@ -631,9 +723,9 @@ protected: void res_loadSpeechSegment(int num); void res_stopSpeech(); - void drawButton(void *button); - void redrawMenu(void *menu); - void handleMenuAction(void *menu, int actionId); + void drawButton(Button *button); + void redrawMenu(MenuData *menu); + void handleMenuAction(MenuData *menu, int actionId); void handleOptions(int forceDisplay); void drawActionsPanel(int dstX, int dstY, int deltaX, int deltaY); void drawConversationPanelBorder(int dstY, int srcX, int srcY); diff --git a/engines/tsage/debugger.cpp b/engines/tsage/debugger.cpp index 5a520b0e89..b647807f8a 100644 --- a/engines/tsage/debugger.cpp +++ b/engines/tsage/debugger.cpp @@ -30,19 +30,19 @@ namespace TsAGE { Debugger::Debugger() : GUI::Debugger() { - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("scene", WRAP_METHOD(Debugger, Cmd_Scene)); - DCmd_Register("walk_regions", WRAP_METHOD(Debugger, Cmd_WalkRegions)); - DCmd_Register("priority_regions", WRAP_METHOD(Debugger, Cmd_PriorityRegions)); - DCmd_Register("scene_regions", WRAP_METHOD(Debugger, Cmd_SceneRegions)); - DCmd_Register("setflag", WRAP_METHOD(Debugger, Cmd_SetFlag)); - DCmd_Register("getflag", WRAP_METHOD(Debugger, Cmd_GetFlag)); - DCmd_Register("clearflag", WRAP_METHOD(Debugger, Cmd_ClearFlag)); - DCmd_Register("listobjects", WRAP_METHOD(Debugger, Cmd_ListObjects)); - DCmd_Register("moveobject", WRAP_METHOD(Debugger, Cmd_MoveObject)); - DCmd_Register("hotspots", WRAP_METHOD(Debugger, Cmd_Hotspots)); - DCmd_Register("sound", WRAP_METHOD(Debugger, Cmd_Sound)); - DCmd_Register("setdebug", WRAP_METHOD(Debugger, Cmd_SetDebug)); + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("scene", WRAP_METHOD(Debugger, Cmd_Scene)); + registerCmd("walk_regions", WRAP_METHOD(Debugger, Cmd_WalkRegions)); + registerCmd("priority_regions", WRAP_METHOD(Debugger, Cmd_PriorityRegions)); + registerCmd("scene_regions", WRAP_METHOD(Debugger, Cmd_SceneRegions)); + registerCmd("setflag", WRAP_METHOD(Debugger, Cmd_SetFlag)); + registerCmd("getflag", WRAP_METHOD(Debugger, Cmd_GetFlag)); + registerCmd("clearflag", WRAP_METHOD(Debugger, Cmd_ClearFlag)); + registerCmd("listobjects", WRAP_METHOD(Debugger, Cmd_ListObjects)); + registerCmd("moveobject", WRAP_METHOD(Debugger, Cmd_MoveObject)); + registerCmd("hotspots", WRAP_METHOD(Debugger, Cmd_Hotspots)); + registerCmd("sound", WRAP_METHOD(Debugger, Cmd_Sound)); + registerCmd("setdebug", WRAP_METHOD(Debugger, Cmd_SetDebug)); } static int strToInt(const char *s) { @@ -66,7 +66,7 @@ static int strToInt(const char *s) { */ bool Debugger::Cmd_Scene(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: %s <scene number> [prior scene #]\n", argv[0]); + debugPrintf("Usage: %s <scene number> [prior scene #]\n", argv[0]); return true; } @@ -82,7 +82,7 @@ bool Debugger::Cmd_Scene(int argc, const char **argv) { */ bool Debugger::Cmd_WalkRegions(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Usage: %s\n", argv[0]); return true; } @@ -120,8 +120,8 @@ bool Debugger::Cmd_WalkRegions(int argc, const char **argv) { // Mark the scene as requiring a full redraw g_globals->_paneRefreshFlag[0] = 2; - DebugPrintf("Total regions = %d\n", g_globals->_walkRegions._regionList.size()); - DebugPrintf("%s\n", regionsDesc.c_str()); + debugPrintf("Total regions = %d\n", g_globals->_walkRegions._regionList.size()); + debugPrintf("%s\n", regionsDesc.c_str()); return false; } @@ -172,8 +172,8 @@ bool Debugger::Cmd_PriorityRegions(int argc, const char **argv) { // Mark the scene as requiring a full redraw g_globals->_paneRefreshFlag[0] = 2; - DebugPrintf("Total regions = %d\n", count); - DebugPrintf("%s", regionsDesc.c_str()); + debugPrintf("Total regions = %d\n", count); + debugPrintf("%s", regionsDesc.c_str()); return true; } @@ -225,8 +225,8 @@ bool Debugger::Cmd_SceneRegions(int argc, const char **argv) { // Mark the scene as requiring a full redraw g_globals->_paneRefreshFlag[0] = 2; - DebugPrintf("Total regions = %d\n", count); - DebugPrintf("%s", regionsDesc.c_str()); + debugPrintf("Total regions = %d\n", count); + debugPrintf("%s", regionsDesc.c_str()); return true; } @@ -237,7 +237,7 @@ bool Debugger::Cmd_SceneRegions(int argc, const char **argv) { bool Debugger::Cmd_SetFlag(int argc, const char **argv) { // Check for a flag to set if (argc != 2) { - DebugPrintf("Usage: %s <flag number>\n", argv[0]); + debugPrintf("Usage: %s <flag number>\n", argv[0]); return true; } @@ -252,12 +252,12 @@ bool Debugger::Cmd_SetFlag(int argc, const char **argv) { bool Debugger::Cmd_GetFlag(int argc, const char **argv) { // Check for an flag to display if (argc != 2) { - DebugPrintf("Usage: %s <flag number>\n", argv[0]); + debugPrintf("Usage: %s <flag number>\n", argv[0]); return true; } int flagNum = strToInt(argv[1]); - DebugPrintf("Value: %d\n", g_globals->getFlag(flagNum)); + debugPrintf("Value: %d\n", g_globals->getFlag(flagNum)); return true; } @@ -267,7 +267,7 @@ bool Debugger::Cmd_GetFlag(int argc, const char **argv) { bool Debugger::Cmd_ClearFlag(int argc, const char **argv) { // Check for a flag to clear if (argc != 2) { - DebugPrintf("Usage: %s <flag number>\n", argv[0]); + debugPrintf("Usage: %s <flag number>\n", argv[0]); return true; } @@ -332,7 +332,7 @@ bool Debugger::Cmd_Hotspots(int argc, const char **argv) { */ bool Debugger::Cmd_Sound(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Usage: %s <sound number>\n", argv[0]); + debugPrintf("Usage: %s <sound number>\n", argv[0]); return true; } @@ -345,7 +345,7 @@ bool Debugger::Cmd_Sound(int argc, const char **argv) { * Activate internal debugger, when available */ bool Debugger::Cmd_SetDebug(int argc, const char **argv) { - DebugPrintf("Not available in this game\n"); + debugPrintf("Not available in this game\n"); return true; } @@ -353,12 +353,12 @@ bool Debugger::Cmd_SetDebug(int argc, const char **argv) { * This command lists the objects available, and their ID */ bool DemoDebugger::Cmd_ListObjects(int argc, const char **argv) { - DebugPrintf("Not available in Demo\n"); + debugPrintf("Not available in Demo\n"); return true; } bool DemoDebugger::Cmd_MoveObject(int argc, const char **argv) { - DebugPrintf("Not available in Demo\n"); + debugPrintf("Not available in Demo\n"); return true; } @@ -367,44 +367,44 @@ bool DemoDebugger::Cmd_MoveObject(int argc, const char **argv) { */ bool RingworldDebugger::Cmd_ListObjects(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Usage: %s\n", argv[0]); return true; } - DebugPrintf("Available objects for this game are:\n"); - DebugPrintf("0 - Stunner\n"); - DebugPrintf("1 - Scanner\n"); - DebugPrintf("2 - Stasis Box\n"); - DebugPrintf("3 - Info Disk\n"); - DebugPrintf("4 - Stasis Negator\n"); - DebugPrintf("5 - Key Device\n"); - DebugPrintf("6 - Medkit\n"); - DebugPrintf("7 - Ladder\n"); - DebugPrintf("8 - Rope\n"); - DebugPrintf("9 - Key\n"); - DebugPrintf("10 - Translator\n"); - DebugPrintf("11 - Ale\n"); - DebugPrintf("12 - Paper\n"); - DebugPrintf("13 - Waldos\n"); - DebugPrintf("14 - Stasis Box 2\n"); - DebugPrintf("15 - Ring\n"); - DebugPrintf("16 - Cloak\n"); - DebugPrintf("17 - Tunic\n"); - DebugPrintf("18 - Candle\n"); - DebugPrintf("19 - Straw\n"); - DebugPrintf("20 - Scimitar\n"); - DebugPrintf("21 - Sword\n"); - DebugPrintf("22 - Helmet\n"); - DebugPrintf("23 - Items\n"); - DebugPrintf("24 - Concentrator\n"); - DebugPrintf("25 - Nullifier\n"); - DebugPrintf("26 - Peg\n"); - DebugPrintf("27 - Vial\n"); - DebugPrintf("28 - Jacket\n"); - DebugPrintf("29 - Tunic 2\n"); - DebugPrintf("30 - Bone\n"); - DebugPrintf("31 - Empty Jar\n"); - DebugPrintf("32 - Jar\n"); + debugPrintf("Available objects for this game are:\n"); + debugPrintf("0 - Stunner\n"); + debugPrintf("1 - Scanner\n"); + debugPrintf("2 - Stasis Box\n"); + debugPrintf("3 - Info Disk\n"); + debugPrintf("4 - Stasis Negator\n"); + debugPrintf("5 - Key Device\n"); + debugPrintf("6 - Medkit\n"); + debugPrintf("7 - Ladder\n"); + debugPrintf("8 - Rope\n"); + debugPrintf("9 - Key\n"); + debugPrintf("10 - Translator\n"); + debugPrintf("11 - Ale\n"); + debugPrintf("12 - Paper\n"); + debugPrintf("13 - Waldos\n"); + debugPrintf("14 - Stasis Box 2\n"); + debugPrintf("15 - Ring\n"); + debugPrintf("16 - Cloak\n"); + debugPrintf("17 - Tunic\n"); + debugPrintf("18 - Candle\n"); + debugPrintf("19 - Straw\n"); + debugPrintf("20 - Scimitar\n"); + debugPrintf("21 - Sword\n"); + debugPrintf("22 - Helmet\n"); + debugPrintf("23 - Items\n"); + debugPrintf("24 - Concentrator\n"); + debugPrintf("25 - Nullifier\n"); + debugPrintf("26 - Peg\n"); + debugPrintf("27 - Vial\n"); + debugPrintf("28 - Jacket\n"); + debugPrintf("29 - Tunic 2\n"); + debugPrintf("30 - Bone\n"); + debugPrintf("31 - Empty Jar\n"); + debugPrintf("32 - Jar\n"); return true; } @@ -414,8 +414,8 @@ bool RingworldDebugger::Cmd_ListObjects(int argc, const char **argv) { bool RingworldDebugger::Cmd_MoveObject(int argc, const char **argv) { // Check for a flag to clear if ((argc < 2) || (argc > 3)){ - DebugPrintf("Usage: %s <object number> [<scene number>]\n", argv[0]); - DebugPrintf("If no scene is specified, the object will be added to inventory\n"); + debugPrintf("Usage: %s <object number> [<scene number>]\n", argv[0]); + debugPrintf("If no scene is specified, the object will be added to inventory\n"); return true; } @@ -525,7 +525,7 @@ bool RingworldDebugger::Cmd_MoveObject(int argc, const char **argv) { RING_INVENTORY._jar._sceneNumber = sceneNum; break; default: - DebugPrintf("Invalid object Id %s\n", argv[1]); + debugPrintf("Invalid object Id %s\n", argv[1]); break; } @@ -537,83 +537,83 @@ bool RingworldDebugger::Cmd_MoveObject(int argc, const char **argv) { */ bool BlueForceDebugger::Cmd_ListObjects(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Usage: %s\n", argv[0]); return true; } - DebugPrintf("Available objects for this game are:\n"); - DebugPrintf("1 - INV_COLT45\n"); - DebugPrintf("2 - INV_AMMO_CLIP\n"); - DebugPrintf("3 - INV_SPARE_CLIP\n"); - DebugPrintf("4 - INV_HANDCUFFS\n"); - DebugPrintf("5 - INV_GREENS_GUN\n"); - DebugPrintf("6 - INV_TICKET_BOOK\n"); - DebugPrintf("7 - INV_MIRANDA_CARD\n"); - DebugPrintf("8 - INV_FOREST_RAP\n"); - DebugPrintf("9 - INV_GREEN_ID\n"); - DebugPrintf("10 - INV_BASEBALL_CARD\n"); - DebugPrintf("11 - INV_BOOKING_GREEN\n"); - DebugPrintf("12 - INV_FLARE\n"); - DebugPrintf("13 - INV_COBB_RAP\n"); - DebugPrintf("14 - INV_22_BULLET\n"); - DebugPrintf("15 - INV_AUTO_RIFLE\n"); - DebugPrintf("16 - INV_WIG\n"); - DebugPrintf("17 - INV_FRANKIE_ID\n"); - DebugPrintf("18 - INV_TYRONE_ID\n"); - DebugPrintf("19 - INV_22_SNUB\n"); - DebugPrintf("20 - INV_BOOKING_FRANKIE\n"); - DebugPrintf("21 - INV_BOOKING_GANG\n"); - DebugPrintf("22 - INV_FBI_TELETYPE\n"); - DebugPrintf("23 - INV_DA_NOTE\n"); - DebugPrintf("24 - INV_PRINT_OUT\n"); - DebugPrintf("25 - INV_WAREHOUSE_KEYS\n"); - DebugPrintf("26 - INV_CENTER_PUNCH\n"); - DebugPrintf("27 - INV_TRANQ_GUN\n"); - DebugPrintf("28 - INV_HOOK\n"); - DebugPrintf("29 - INV_RAGS\n"); - DebugPrintf("30 - INV_JAR\n"); - DebugPrintf("31 - INV_SCREWDRIVER\n"); - DebugPrintf("32 - INV_D_FLOPPY\n"); - DebugPrintf("33 - INV_BLANK_DISK\n"); - DebugPrintf("34 - INV_STICK\n"); - DebugPrintf("35 - INV_CRATE1\n"); - DebugPrintf("36 - INV_CRATE2\n"); - DebugPrintf("37 - INV_SHOEBOX\n"); - DebugPrintf("38 - INV_BADGE\n"); - DebugPrintf("39 - INV_RENTAL_COUPON\n"); - DebugPrintf("40 - INV_NICKEL\n"); - DebugPrintf("41 - INV_LYLE_CARD\n"); - DebugPrintf("42 - INV_CARTER_NOTE\n"); - DebugPrintf("43 - INV_MUG_SHOT\n"); - DebugPrintf("44 - INV_CLIPPING\n"); - DebugPrintf("45 - INV_MICROFILM \n"); - DebugPrintf("46 - INV_WAVE_KEYS\n"); - DebugPrintf("47 - INV_RENTAL_KEYS\n"); - DebugPrintf("48 - INV_NAPKIN\n"); - DebugPrintf("49 - INV_DMV_PRINTOUT\n"); - DebugPrintf("50 - INV_FISHING_NET\n"); - DebugPrintf("51 - INV_ID\n"); - DebugPrintf("52 - INV_9MM_BULLETS\n"); - DebugPrintf("53 - INV_SCHEDULE\n"); - DebugPrintf("54 - INV_GRENADES\n"); - DebugPrintf("55 - INV_YELLOW_CORD\n"); - DebugPrintf("56 - INV_HALF_YELLOW_CORD\n"); - DebugPrintf("57 - INV_BLACK_CORD\n"); - DebugPrintf("58 - INV_HALF_BLACK_CORD\n"); - DebugPrintf("59 - INV_WARRANT\n"); - DebugPrintf("60 - INV_JACKET\n"); - DebugPrintf("61 - INV_GREENS_KNIFE\n"); - DebugPrintf("62 - INV_DOG_WHISTLE\n"); - DebugPrintf("63 - INV_AMMO_BELT\n"); - DebugPrintf("64 - INV_CARAVAN_KEY\n"); + debugPrintf("Available objects for this game are:\n"); + debugPrintf("1 - INV_COLT45\n"); + debugPrintf("2 - INV_AMMO_CLIP\n"); + debugPrintf("3 - INV_SPARE_CLIP\n"); + debugPrintf("4 - INV_HANDCUFFS\n"); + debugPrintf("5 - INV_GREENS_GUN\n"); + debugPrintf("6 - INV_TICKET_BOOK\n"); + debugPrintf("7 - INV_MIRANDA_CARD\n"); + debugPrintf("8 - INV_FOREST_RAP\n"); + debugPrintf("9 - INV_GREEN_ID\n"); + debugPrintf("10 - INV_BASEBALL_CARD\n"); + debugPrintf("11 - INV_BOOKING_GREEN\n"); + debugPrintf("12 - INV_FLARE\n"); + debugPrintf("13 - INV_COBB_RAP\n"); + debugPrintf("14 - INV_22_BULLET\n"); + debugPrintf("15 - INV_AUTO_RIFLE\n"); + debugPrintf("16 - INV_WIG\n"); + debugPrintf("17 - INV_FRANKIE_ID\n"); + debugPrintf("18 - INV_TYRONE_ID\n"); + debugPrintf("19 - INV_22_SNUB\n"); + debugPrintf("20 - INV_BOOKING_FRANKIE\n"); + debugPrintf("21 - INV_BOOKING_GANG\n"); + debugPrintf("22 - INV_FBI_TELETYPE\n"); + debugPrintf("23 - INV_DA_NOTE\n"); + debugPrintf("24 - INV_PRINT_OUT\n"); + debugPrintf("25 - INV_WAREHOUSE_KEYS\n"); + debugPrintf("26 - INV_CENTER_PUNCH\n"); + debugPrintf("27 - INV_TRANQ_GUN\n"); + debugPrintf("28 - INV_HOOK\n"); + debugPrintf("29 - INV_RAGS\n"); + debugPrintf("30 - INV_JAR\n"); + debugPrintf("31 - INV_SCREWDRIVER\n"); + debugPrintf("32 - INV_D_FLOPPY\n"); + debugPrintf("33 - INV_BLANK_DISK\n"); + debugPrintf("34 - INV_STICK\n"); + debugPrintf("35 - INV_CRATE1\n"); + debugPrintf("36 - INV_CRATE2\n"); + debugPrintf("37 - INV_SHOEBOX\n"); + debugPrintf("38 - INV_BADGE\n"); + debugPrintf("39 - INV_RENTAL_COUPON\n"); + debugPrintf("40 - INV_NICKEL\n"); + debugPrintf("41 - INV_LYLE_CARD\n"); + debugPrintf("42 - INV_CARTER_NOTE\n"); + debugPrintf("43 - INV_MUG_SHOT\n"); + debugPrintf("44 - INV_CLIPPING\n"); + debugPrintf("45 - INV_MICROFILM \n"); + debugPrintf("46 - INV_WAVE_KEYS\n"); + debugPrintf("47 - INV_RENTAL_KEYS\n"); + debugPrintf("48 - INV_NAPKIN\n"); + debugPrintf("49 - INV_DMV_PRINTOUT\n"); + debugPrintf("50 - INV_FISHING_NET\n"); + debugPrintf("51 - INV_ID\n"); + debugPrintf("52 - INV_9MM_BULLETS\n"); + debugPrintf("53 - INV_SCHEDULE\n"); + debugPrintf("54 - INV_GRENADES\n"); + debugPrintf("55 - INV_YELLOW_CORD\n"); + debugPrintf("56 - INV_HALF_YELLOW_CORD\n"); + debugPrintf("57 - INV_BLACK_CORD\n"); + debugPrintf("58 - INV_HALF_BLACK_CORD\n"); + debugPrintf("59 - INV_WARRANT\n"); + debugPrintf("60 - INV_JACKET\n"); + debugPrintf("61 - INV_GREENS_KNIFE\n"); + debugPrintf("62 - INV_DOG_WHISTLE\n"); + debugPrintf("63 - INV_AMMO_BELT\n"); + debugPrintf("64 - INV_CARAVAN_KEY\n"); return true; } bool BlueForceDebugger::Cmd_MoveObject(int argc, const char **argv) { // Check for a flag to clear if ((argc < 2) || (argc > 3)){ - DebugPrintf("Usage: %s <object number> [<scene number>]\n", argv[0]); - DebugPrintf("If no scene is specified, the object will be added to inventory\n"); + debugPrintf("Usage: %s <object number> [<scene number>]\n", argv[0]); + debugPrintf("If no scene is specified, the object will be added to inventory\n"); return true; } @@ -625,7 +625,7 @@ bool BlueForceDebugger::Cmd_MoveObject(int argc, const char **argv) { if ((objNum > 0) && (objNum < 65)) BF_INVENTORY.setObjectScene(objNum, sceneNum); else - DebugPrintf("Invalid object Id %s\n", argv[1]); + debugPrintf("Invalid object Id %s\n", argv[1]); return true; } @@ -635,63 +635,63 @@ bool BlueForceDebugger::Cmd_MoveObject(int argc, const char **argv) { */ bool Ringworld2Debugger::Cmd_ListObjects(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Usage: %s\n", argv[0]); return true; } - DebugPrintf("Available objects for this game are:\n"); - DebugPrintf("1 - Scene %d - R2_OPTO_DISK\n", BF_INVENTORY.getObjectScene(1)); - DebugPrintf("2 - Scene %d - R2_READER\n", BF_INVENTORY.getObjectScene(2)); - DebugPrintf("3 - Scene %d - R2_NEGATOR_GUN\n", BF_INVENTORY.getObjectScene(3)); - DebugPrintf("4 - Scene %d - R2_STEPPING_DISKS\n", BF_INVENTORY.getObjectScene(4)); - DebugPrintf("5 - Scene %d - R2_ATTRACTOR_UNIT\n", BF_INVENTORY.getObjectScene(5)); - DebugPrintf("6 - Scene %d - R2_SENSOR_PROBE\n", BF_INVENTORY.getObjectScene(6)); - DebugPrintf("7 - Scene %d - R2_SONIC_STUNNER\n", BF_INVENTORY.getObjectScene(7)); - DebugPrintf("8 - Scene %d - R2_CABLE_HARNESS\n", BF_INVENTORY.getObjectScene(8)); - DebugPrintf("9 - Scene %d - R2_COM_SCANNER\n", BF_INVENTORY.getObjectScene(9)); - DebugPrintf("10 - Scene %d - R2_SPENT_POWER_CAPSULE\n", BF_INVENTORY.getObjectScene(10)); - DebugPrintf("11 - Scene %d - R2_CHARGED_POWER_CAPSULE\n", BF_INVENTORY.getObjectScene(11)); - DebugPrintf("12 - Scene %d - R2_AEROSOL\n", BF_INVENTORY.getObjectScene(12)); - DebugPrintf("13 - Scene %d - R2_REMOTE_CONTROL\n", BF_INVENTORY.getObjectScene(13)); - DebugPrintf("14 - Scene %d - R2_OPTICAL_FIBER\n", BF_INVENTORY.getObjectScene(14)); - DebugPrintf("15 - Scene %d - R2_CLAMP\n", BF_INVENTORY.getObjectScene(15)); - DebugPrintf("16 - Scene %d - R2_ATTRACTOR_CABLE_HARNESS\n", BF_INVENTORY.getObjectScene(16)); - DebugPrintf("17 - Scene %d - R2_FUEL_CELL\n", BF_INVENTORY.getObjectScene(17)); - DebugPrintf("18 - Scene %d - R2_GYROSCOPE\n", BF_INVENTORY.getObjectScene(18)); - DebugPrintf("19 - Scene %d - R2_AIRBAG\n", BF_INVENTORY.getObjectScene(19)); - DebugPrintf("20 - Scene %d - R2_REBREATHER_TANK\n", BF_INVENTORY.getObjectScene(20)); - DebugPrintf("21 - Scene %d - R2_RESERVE_REBREATHER_TANK\n", BF_INVENTORY.getObjectScene(21)); - DebugPrintf("22 - Scene %d - R2_GUIDANCE_MODULE\n", BF_INVENTORY.getObjectScene(22)); - DebugPrintf("23 - Scene %d - R2_THRUSTER_VALVE\n", BF_INVENTORY.getObjectScene(23)); - DebugPrintf("24 - Scene %d - R2_BALLOON_BACKPACK\n", BF_INVENTORY.getObjectScene(24)); - DebugPrintf("25 - Scene %d - R2_RADAR_MECHANISM\n", BF_INVENTORY.getObjectScene(25)); - DebugPrintf("26 - Scene %d - R2_JOYSTICK\n", BF_INVENTORY.getObjectScene(26)); - DebugPrintf("27 - Scene %d - R2_IGNITOR\n", BF_INVENTORY.getObjectScene(27)); - DebugPrintf("28 - Scene %d - R2_DIAGNOSTICS_DISPLAY\n", BF_INVENTORY.getObjectScene(28)); - DebugPrintf("29 - Scene %d - R2_GLASS_DOME\n", BF_INVENTORY.getObjectScene(29)); - DebugPrintf("30 - Scene %d - R2_WICK_LAMP\n", BF_INVENTORY.getObjectScene(30)); - DebugPrintf("31 - Scene %d - R2_SCRITH_KEY\n", BF_INVENTORY.getObjectScene(31)); - DebugPrintf("32 - Scene %d - R2_TANNER_MASK\n", BF_INVENTORY.getObjectScene(32)); - DebugPrintf("33 - Scene %d - R2_PURE_GRAIN_ALCOHOL\n", BF_INVENTORY.getObjectScene(33)); - DebugPrintf("34 - Scene %d - R2_SAPPHIRE_BLUE\n", BF_INVENTORY.getObjectScene(34)); - DebugPrintf("35 - Scene %d - R2_ANCIENT_SCROLLS\n", BF_INVENTORY.getObjectScene(35)); - DebugPrintf("36 - Scene %d - R2_FLUTE\n", BF_INVENTORY.getObjectScene(36)); - DebugPrintf("37 - Scene %d - R2_GUNPOWDER\n", BF_INVENTORY.getObjectScene(37)); - DebugPrintf("38 - Scene %d - R2_NONAME\n", BF_INVENTORY.getObjectScene(38)); - DebugPrintf("39 - Scene %d - R2_COM_SCANNER_2\n", BF_INVENTORY.getObjectScene(39)); - DebugPrintf("40 - Scene %d - R2_SUPERCONDUCTOR_WIRE\n", BF_INVENTORY.getObjectScene(40)); - DebugPrintf("41 - Scene %d - R2_PILLOW\n", BF_INVENTORY.getObjectScene(41)); - DebugPrintf("42 - Scene %d - R2_FOOD_TRAY\n", BF_INVENTORY.getObjectScene(42)); - DebugPrintf("43 - Scene %d - R2_LASER_HACKSAW\n", BF_INVENTORY.getObjectScene(43)); - DebugPrintf("44 - Scene %d - R2_PHOTON_STUNNER\n", BF_INVENTORY.getObjectScene(44)); - DebugPrintf("45 - Scene %d - R2_BATTERY\n", BF_INVENTORY.getObjectScene(45)); - DebugPrintf("46 - Scene %d - R2_SOAKED_FACEMASK\n", BF_INVENTORY.getObjectScene(46)); - DebugPrintf("47 - Scene %d - R2_LIGHT_BULB\n", BF_INVENTORY.getObjectScene(47)); - DebugPrintf("48 - Scene %d - R2_ALCOHOL_LAMP\n", BF_INVENTORY.getObjectScene(48)); - DebugPrintf("49 - Scene %d - R2_ALCOHOL_LAMP_2\n", BF_INVENTORY.getObjectScene(49)); - DebugPrintf("50 - Scene %d - R2_ALCOHOL_LAMP_3\n", BF_INVENTORY.getObjectScene(50)); - DebugPrintf("51 - Scene %d - R2_BROKEN_DISPLAY\n", BF_INVENTORY.getObjectScene(51)); - DebugPrintf("52 - Scene %d - R2_TOOLBOX\n", BF_INVENTORY.getObjectScene(52)); + debugPrintf("Available objects for this game are:\n"); + debugPrintf("1 - Scene %d - R2_OPTO_DISK\n", BF_INVENTORY.getObjectScene(1)); + debugPrintf("2 - Scene %d - R2_READER\n", BF_INVENTORY.getObjectScene(2)); + debugPrintf("3 - Scene %d - R2_NEGATOR_GUN\n", BF_INVENTORY.getObjectScene(3)); + debugPrintf("4 - Scene %d - R2_STEPPING_DISKS\n", BF_INVENTORY.getObjectScene(4)); + debugPrintf("5 - Scene %d - R2_ATTRACTOR_UNIT\n", BF_INVENTORY.getObjectScene(5)); + debugPrintf("6 - Scene %d - R2_SENSOR_PROBE\n", BF_INVENTORY.getObjectScene(6)); + debugPrintf("7 - Scene %d - R2_SONIC_STUNNER\n", BF_INVENTORY.getObjectScene(7)); + debugPrintf("8 - Scene %d - R2_CABLE_HARNESS\n", BF_INVENTORY.getObjectScene(8)); + debugPrintf("9 - Scene %d - R2_COM_SCANNER\n", BF_INVENTORY.getObjectScene(9)); + debugPrintf("10 - Scene %d - R2_SPENT_POWER_CAPSULE\n", BF_INVENTORY.getObjectScene(10)); + debugPrintf("11 - Scene %d - R2_CHARGED_POWER_CAPSULE\n", BF_INVENTORY.getObjectScene(11)); + debugPrintf("12 - Scene %d - R2_AEROSOL\n", BF_INVENTORY.getObjectScene(12)); + debugPrintf("13 - Scene %d - R2_REMOTE_CONTROL\n", BF_INVENTORY.getObjectScene(13)); + debugPrintf("14 - Scene %d - R2_OPTICAL_FIBER\n", BF_INVENTORY.getObjectScene(14)); + debugPrintf("15 - Scene %d - R2_CLAMP\n", BF_INVENTORY.getObjectScene(15)); + debugPrintf("16 - Scene %d - R2_ATTRACTOR_CABLE_HARNESS\n", BF_INVENTORY.getObjectScene(16)); + debugPrintf("17 - Scene %d - R2_FUEL_CELL\n", BF_INVENTORY.getObjectScene(17)); + debugPrintf("18 - Scene %d - R2_GYROSCOPE\n", BF_INVENTORY.getObjectScene(18)); + debugPrintf("19 - Scene %d - R2_AIRBAG\n", BF_INVENTORY.getObjectScene(19)); + debugPrintf("20 - Scene %d - R2_REBREATHER_TANK\n", BF_INVENTORY.getObjectScene(20)); + debugPrintf("21 - Scene %d - R2_RESERVE_REBREATHER_TANK\n", BF_INVENTORY.getObjectScene(21)); + debugPrintf("22 - Scene %d - R2_GUIDANCE_MODULE\n", BF_INVENTORY.getObjectScene(22)); + debugPrintf("23 - Scene %d - R2_THRUSTER_VALVE\n", BF_INVENTORY.getObjectScene(23)); + debugPrintf("24 - Scene %d - R2_BALLOON_BACKPACK\n", BF_INVENTORY.getObjectScene(24)); + debugPrintf("25 - Scene %d - R2_RADAR_MECHANISM\n", BF_INVENTORY.getObjectScene(25)); + debugPrintf("26 - Scene %d - R2_JOYSTICK\n", BF_INVENTORY.getObjectScene(26)); + debugPrintf("27 - Scene %d - R2_IGNITOR\n", BF_INVENTORY.getObjectScene(27)); + debugPrintf("28 - Scene %d - R2_DIAGNOSTICS_DISPLAY\n", BF_INVENTORY.getObjectScene(28)); + debugPrintf("29 - Scene %d - R2_GLASS_DOME\n", BF_INVENTORY.getObjectScene(29)); + debugPrintf("30 - Scene %d - R2_WICK_LAMP\n", BF_INVENTORY.getObjectScene(30)); + debugPrintf("31 - Scene %d - R2_SCRITH_KEY\n", BF_INVENTORY.getObjectScene(31)); + debugPrintf("32 - Scene %d - R2_TANNER_MASK\n", BF_INVENTORY.getObjectScene(32)); + debugPrintf("33 - Scene %d - R2_PURE_GRAIN_ALCOHOL\n", BF_INVENTORY.getObjectScene(33)); + debugPrintf("34 - Scene %d - R2_SAPPHIRE_BLUE\n", BF_INVENTORY.getObjectScene(34)); + debugPrintf("35 - Scene %d - R2_ANCIENT_SCROLLS\n", BF_INVENTORY.getObjectScene(35)); + debugPrintf("36 - Scene %d - R2_FLUTE\n", BF_INVENTORY.getObjectScene(36)); + debugPrintf("37 - Scene %d - R2_GUNPOWDER\n", BF_INVENTORY.getObjectScene(37)); + debugPrintf("38 - Scene %d - R2_NONAME\n", BF_INVENTORY.getObjectScene(38)); + debugPrintf("39 - Scene %d - R2_COM_SCANNER_2\n", BF_INVENTORY.getObjectScene(39)); + debugPrintf("40 - Scene %d - R2_SUPERCONDUCTOR_WIRE\n", BF_INVENTORY.getObjectScene(40)); + debugPrintf("41 - Scene %d - R2_PILLOW\n", BF_INVENTORY.getObjectScene(41)); + debugPrintf("42 - Scene %d - R2_FOOD_TRAY\n", BF_INVENTORY.getObjectScene(42)); + debugPrintf("43 - Scene %d - R2_LASER_HACKSAW\n", BF_INVENTORY.getObjectScene(43)); + debugPrintf("44 - Scene %d - R2_PHOTON_STUNNER\n", BF_INVENTORY.getObjectScene(44)); + debugPrintf("45 - Scene %d - R2_BATTERY\n", BF_INVENTORY.getObjectScene(45)); + debugPrintf("46 - Scene %d - R2_SOAKED_FACEMASK\n", BF_INVENTORY.getObjectScene(46)); + debugPrintf("47 - Scene %d - R2_LIGHT_BULB\n", BF_INVENTORY.getObjectScene(47)); + debugPrintf("48 - Scene %d - R2_ALCOHOL_LAMP\n", BF_INVENTORY.getObjectScene(48)); + debugPrintf("49 - Scene %d - R2_ALCOHOL_LAMP_2\n", BF_INVENTORY.getObjectScene(49)); + debugPrintf("50 - Scene %d - R2_ALCOHOL_LAMP_3\n", BF_INVENTORY.getObjectScene(50)); + debugPrintf("51 - Scene %d - R2_BROKEN_DISPLAY\n", BF_INVENTORY.getObjectScene(51)); + debugPrintf("52 - Scene %d - R2_TOOLBOX\n", BF_INVENTORY.getObjectScene(52)); return true; } @@ -699,8 +699,8 @@ bool Ringworld2Debugger::Cmd_ListObjects(int argc, const char **argv) { bool Ringworld2Debugger::Cmd_MoveObject(int argc, const char **argv) { // Check for a flag to clear if ((argc < 2) || (argc > 3)){ - DebugPrintf("Usage: %s <object number> [<scene number>]\n", argv[0]); - DebugPrintf("If no scene is specified, the object will be added to inventory\n"); + debugPrintf("Usage: %s <object number> [<scene number>]\n", argv[0]); + debugPrintf("If no scene is specified, the object will be added to inventory\n"); return true; } @@ -712,7 +712,7 @@ bool Ringworld2Debugger::Cmd_MoveObject(int argc, const char **argv) { if ((objNum > 0) && (objNum < 53)) R2_INVENTORY.setObjectScene(objNum, sceneNum); else - DebugPrintf("Invalid object Id %s\n", argv[1]); + debugPrintf("Invalid object Id %s\n", argv[1]); return true; } @@ -722,7 +722,7 @@ bool Ringworld2Debugger::Cmd_MoveObject(int argc, const char **argv) { */ bool Ringworld2Debugger::Cmd_SetDebug(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Usage: %s\n", argv[0]); return true; } diff --git a/engines/tucker/resource.cpp b/engines/tucker/resource.cpp index 5f06334720..9cba7b523d 100644 --- a/engines/tucker/resource.cpp +++ b/engines/tucker/resource.cpp @@ -535,7 +535,10 @@ void TuckerEngine::loadObj() { return; } debug(2, "loadObj() partNum %d locationNum %d", _partNum, _locationNum); - if ((_gameFlags & kGameFlagDemo) == 0) { + // If a savegame is loaded from the launcher, skip the display chapter + if (_startSlot != -1) + _startSlot = -1; + else if ((_gameFlags & kGameFlagDemo) == 0) { handleNewPartSequence(); } _currentPartNum = _partNum; @@ -662,15 +665,13 @@ void TuckerEngine::loadData4() { t.findNextToken(kDataTokenDw); _gameDebug = t.getNextInteger() != 0; _displayGameHints = t.getNextInteger() != 0; - // forces game hints feature -// _displayGameHints = true; _locationObjectsCount = 0; if (t.findIndex(_locationNum)) { while (t.findNextToken(kDataTokenDw)) { int i = t.getNextInteger(); - if (i < 0) { + if (i < 0) break; - } + assert(_locationObjectsCount < kLocationObjectsTableSize); LocationObject *d = &_locationObjectsTable[_locationObjectsCount++]; d->_xPos = i; @@ -851,60 +852,63 @@ void TuckerEngine::unloadSprC02_01() { void TuckerEngine::loadFx() { loadFile("fx.c", _loadTempBuf); DataTokenizer t(_loadTempBuf, _fileLoadSize); - t.findIndex(_locationNum); - t.findNextToken(kDataTokenDw); - _locationSoundsCount = t.getNextInteger(); - _currentFxSet = 0; - for (int i = 0; i < _locationSoundsCount; ++i) { - LocationSound *s = &_locationSoundsTable[i]; - s->_offset = 0; - s->_num = t.getNextInteger(); - s->_volume = t.getNextInteger(); - s->_type = t.getNextInteger(); - switch (s->_type) { - case 5: - _currentFxSet = 1; - _currentFxIndex = i; - _currentFxVolume = s->_volume; - _currentFxDist = t.getNextInteger(); - _currentFxScale = t.getNextInteger(); - break; - case 6: - case 7: - case 8: - s->_startFxSpriteState = t.getNextInteger(); - s->_startFxSpriteNum = t.getNextInteger(); - s->_updateType = t.getNextInteger(); - if (s->_type == 7) { - s->_flagNum = t.getNextInteger(); - s->_flagValueStartFx = t.getNextInteger(); - s->_stopFxSpriteState = t.getNextInteger(); - s->_stopFxSpriteNum = t.getNextInteger(); - s->_flagValueStopFx = t.getNextInteger(); + if (t.findIndex(_locationNum)) { + t.findNextToken(kDataTokenDw); + _locationSoundsCount = t.getNextInteger(); + _currentFxSet = 0; + for (int i = 0; i < _locationSoundsCount; ++i) { + LocationSound *s = &_locationSoundsTable[i]; + s->_offset = 0; + s->_num = t.getNextInteger(); + s->_volume = t.getNextInteger(); + s->_type = t.getNextInteger(); + switch (s->_type) { + case 5: + _currentFxSet = 1; + _currentFxIndex = i; + _currentFxVolume = s->_volume; + _currentFxDist = t.getNextInteger(); + _currentFxScale = t.getNextInteger(); + break; + case 6: + case 7: + case 8: + s->_startFxSpriteState = t.getNextInteger(); + s->_startFxSpriteNum = t.getNextInteger(); + s->_updateType = t.getNextInteger(); + if (s->_type == 7) { + s->_flagNum = t.getNextInteger(); + s->_flagValueStartFx = t.getNextInteger(); + s->_stopFxSpriteState = t.getNextInteger(); + s->_stopFxSpriteNum = t.getNextInteger(); + s->_flagValueStopFx = t.getNextInteger(); + } + break; + } + if (s->_type == 8) { + s->_type = 6; } - break; - } - if (s->_type == 8) { - s->_type = 6; } - } - t.findNextToken(kDataTokenDw); - int count = t.getNextInteger(); - _locationMusicsCount = 0; - for (int i = 0; i < count; ++i) { - int flagNum = t.getNextInteger(); - int flagValue = t.getNextInteger(); - if (flagValue == _flagsTable[flagNum]) { - LocationMusic *m = &_locationMusicsTable[_locationMusicsCount++]; - m->_offset = 0; - m->_num = t.getNextInteger(); - m->_volume = t.getNextInteger(); - m->_flag = t.getNextInteger(); - } else { - for (int j = 0; j < 3; ++j) { - t.getNextInteger(); + t.findNextToken(kDataTokenDw); + int count = t.getNextInteger(); + _locationMusicsCount = 0; + for (int i = 0; i < count; ++i) { + int flagNum = t.getNextInteger(); + int flagValue = t.getNextInteger(); + if (flagValue == _flagsTable[flagNum]) { + LocationMusic *m = &_locationMusicsTable[_locationMusicsCount++]; + m->_offset = 0; + m->_num = t.getNextInteger(); + m->_volume = t.getNextInteger(); + m->_flag = t.getNextInteger(); + } else { + for (int j = 0; j < 3; ++j) { + t.getNextInteger(); + } } } + } else { + error("loadFx() - Index not found for location %d", _locationNum); } } diff --git a/engines/tucker/sequences.cpp b/engines/tucker/sequences.cpp index 2fb881f77e..d9f284e443 100644 --- a/engines/tucker/sequences.cpp +++ b/engines/tucker/sequences.cpp @@ -40,7 +40,7 @@ void TuckerEngine::handleIntroSequence() { _player = new AnimationSequencePlayer(_system, _mixer, _eventMan, &_compressedSound, firstSequence); _player->mainLoop(); delete _player; - _player = 0; + _player = nullptr; } void TuckerEngine::handleCreditsSequence() { @@ -115,7 +115,8 @@ void TuckerEngine::handleCreditsSequence() { if (counter4 == _creditsSequenceTimecounts[num]) { _fadePaletteCounter = 0; clearSprites(); - ++num; + if (num < 6) + ++num; Common::String filename; if (num == 6) { for (int i = 0; i < 16; ++i) { @@ -123,6 +124,7 @@ void TuckerEngine::handleCreditsSequence() { loadImage(filename.c_str(), imgBuf + i * 64000, 2); } } else { + filename = ""; switch (num) { case 1: filename = "loc75.pcx"; @@ -140,7 +142,8 @@ void TuckerEngine::handleCreditsSequence() { filename = "loc78.pcx"; break; } - loadImage(filename.c_str(), _quadBackgroundGfxBuf, 2); + if (filename != "") + loadImage(filename.c_str(), _quadBackgroundGfxBuf, 2); } _spritesCount = _creditsSequenceSpriteCounts[num]; ++_flagsTable[236]; diff --git a/engines/tucker/tucker.cpp b/engines/tucker/tucker.cpp index adf4be6b65..de555cd7b6 100644 --- a/engines/tucker/tucker.cpp +++ b/engines/tucker/tucker.cpp @@ -50,6 +50,7 @@ TuckerEngine::TuckerEngine(OSystem *system, Common::Language language, uint32 fl _currentSaveLoadGameState = 1; _fileLoadSize = 0; _csDataSize = 0; + _startSlot = ConfMan.hasKey("save_slot") ? ConfMan.getInt("save_slot") : -1; _player = nullptr; _loadTempBuf = nullptr; @@ -91,7 +92,8 @@ Common::Error TuckerEngine::run() { initGraphics(kScreenWidth, kScreenHeight, false); syncSoundSettings(); _compressedSound.openFile(); - handleIntroSequence(); + if (_startSlot == -1) + handleIntroSequence(); if ((_gameFlags & kGameFlagIntroOnly) == 0 && !shouldQuit()) { mainLoop(); } @@ -604,6 +606,7 @@ void TuckerEngine::mainLoop() { _flagsTable[236] = 74; } } + if (_flagsTable[236] > 70) { handleCreditsSequence(); _quitGame = true; @@ -890,9 +893,8 @@ void TuckerEngine::updateCharPosition() { if (action->_testFlag1Num < 500) { if (action->_testFlag1Num >= 300) error("updateCharPosition() - Unexpected value for _testFlag1Num : %d", action->_testFlag1Num); - if (_flagsTable[action->_testFlag1Num] != action->_testFlag1Value) { + if (_flagsTable[action->_testFlag1Num] != action->_testFlag1Value) skip = false; - } } else if (_inventoryItemsState[action->_testFlag1Num - 500] != action->_testFlag1Value) { skip = false; } @@ -900,9 +902,10 @@ void TuckerEngine::updateCharPosition() { } if (action->_testFlag2Num != 0) { if (action->_testFlag2Num < 500) { - if (_flagsTable[action->_testFlag2Num] != action->_testFlag2Value) { + if (action->_testFlag2Num >= 300) + error("updateCharPosition() - Unexpected value for _testFlag1Num : %d", action->_testFlag1Num); + if (_flagsTable[action->_testFlag2Num] != action->_testFlag2Value) skip = false; - } } else if (_inventoryItemsState[action->_testFlag2Num - 500] != action->_testFlag2Value) { skip = false; } diff --git a/engines/tucker/tucker.h b/engines/tucker/tucker.h index adcd02b2fe..a423915a5f 100644 --- a/engines/tucker/tucker.h +++ b/engines/tucker/tucker.h @@ -613,6 +613,7 @@ protected: CompressedSound _compressedSound; Common::Language _gameLang; uint32 _gameFlags; + int _startSlot; bool _quitGame; bool _fastMode; diff --git a/engines/voyeur/animation.cpp b/engines/voyeur/animation.cpp index c1ded75f02..62b37346da 100644 --- a/engines/voyeur/animation.cpp +++ b/engines/voyeur/animation.cpp @@ -48,7 +48,7 @@ RL2Decoder::~RL2Decoder() { } bool RL2Decoder::loadVideo(int videoId) { - Common::String filename = Common::String::format("%s.rl2", + Common::String filename = Common::String::format("%s.rl2", ::Voyeur::SZ_FILENAMES[videoId * 2]); return loadRL2File(filename, false); } @@ -121,7 +121,7 @@ void RL2Decoder::readNextPacket() { if (_soundFrameNumber == -1) _soundFrameNumber = (frameNumber == -1) ? 0 : frameNumber; - while (audioTrack->numQueuedStreams() < SOUND_FRAMES_READAHEAD && + while (audioTrack->numQueuedStreams() < SOUND_FRAMES_READAHEAD && (_soundFrameNumber < (int)_soundFrames.size())) { _fileStream->seek(_soundFrames[_soundFrameNumber]._offset); audioTrack->queueSound(_fileStream, _soundFrames[_soundFrameNumber]._size); @@ -217,13 +217,13 @@ bool RL2Decoder::RL2FileHeader::isValid() const { } Common::Rational RL2Decoder::RL2FileHeader::getFrameRate() const { - return (_soundRate > 0) ? Common::Rational(_rate, _defSoundSize) : + return (_soundRate > 0) ? Common::Rational(_rate, _defSoundSize) : Common::Rational(11025, 1103); } /*------------------------------------------------------------------------*/ -RL2Decoder::RL2VideoTrack::RL2VideoTrack(const RL2FileHeader &header, RL2AudioTrack *audioTrack, +RL2Decoder::RL2VideoTrack::RL2VideoTrack(const RL2FileHeader &header, RL2AudioTrack *audioTrack, Common::SeekableReadStream *stream): _header(header), _fileStream(stream) { _frameOffsets = nullptr; @@ -261,7 +261,7 @@ void RL2Decoder::RL2VideoTrack::initBackSurface() { bool RL2Decoder::RL2VideoTrack::seek(const Audio::Timestamp &time) { int frame = getFrameAtTime(time); - + if (frame < 0 || frame >= _header._numFrames) return false; @@ -287,7 +287,7 @@ const Graphics::Surface *RL2Decoder::RL2VideoTrack::decodeNextFrame() { _fileStream->seek(0x324); rl2DecodeFrameWithoutTransparency(0); - Common::copy((byte *)_surface->getPixels(), (byte *)_surface->getPixels() + (320 * 200), + Common::copy((byte *)_surface->getPixels(), (byte *)_surface->getPixels() + (320 * 200), (byte *)_backSurface->getPixels()); _dirtyRects.push_back(Common::Rect(0, 0, _surface->w, _surface->h)); _initialFrame = false; @@ -433,7 +433,7 @@ Graphics::Surface *RL2Decoder::RL2VideoTrack::getBackSurface() { /*------------------------------------------------------------------------*/ -RL2Decoder::RL2AudioTrack::RL2AudioTrack(const RL2FileHeader &header, Common::SeekableReadStream *stream, Audio::Mixer::SoundType soundType): +RL2Decoder::RL2AudioTrack::RL2AudioTrack(const RL2FileHeader &header, Common::SeekableReadStream *stream, Audio::Mixer::SoundType soundType): _header(header), _soundType(soundType) { // Create audio straem for the audio track _audStream = Audio::makeQueuingAudioStream(_header._rate, _header._channels == 2); @@ -450,7 +450,7 @@ void RL2Decoder::RL2AudioTrack::queueSound(Common::SeekableReadStream *stream, i Common::MemoryReadStream *memoryStream = new Common::MemoryReadStream(data, size, DisposeAfterUse::YES); - _audStream->queueAudioStream(Audio::makeRawStream(memoryStream, _header._rate, + _audStream->queueAudioStream(Audio::makeRawStream(memoryStream, _header._rate, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES), DisposeAfterUse::YES); } @@ -458,7 +458,7 @@ Audio::AudioStream *RL2Decoder::RL2AudioTrack::getAudioStream() const { return _audStream; } -void RL2Decoder::play(VoyeurEngine *vm, int resourceOffset, +void RL2Decoder::play(VoyeurEngine *vm, int resourceOffset, byte *frames, byte *imgPos) { vm->flipPageAndWait(); int paletteStart = getPaletteStart(); @@ -472,14 +472,14 @@ void RL2Decoder::play(VoyeurEngine *vm, int resourceOffset, vm->_graphicsManager->setPalette128(palette, paletteStart, paletteCount); } - + if (needsUpdate()) { if (frames) { // If reached a point where a new background is needed, load it // and copy over to the video decoder if (getCurFrame() >= READ_LE_UINT16(frames + picCtr * 4)) { PictureResource *newPic = vm->_bVoy->boltEntry(0x302 + picCtr)._picResource; - Common::Point pt(READ_LE_UINT16(imgPos + 4 * picCtr) - 32, + Common::Point pt(READ_LE_UINT16(imgPos + 4 * picCtr) - 32, READ_LE_UINT16(imgPos + 4 * picCtr + 2) - 20); vm->_graphicsManager->sDrawPic(newPic, &videoFrame, pt); @@ -492,7 +492,7 @@ void RL2Decoder::play(VoyeurEngine *vm, int resourceOffset, Common::copy((const byte *)frame->getPixels(), (const byte *)frame->getPixels() + 320 * 200, (byte *)vm->_graphicsManager->_screenSurface.getPixels()); } - + vm->_eventsManager->getMouseInfo(); g_system->delayMillis(10); } diff --git a/engines/voyeur/animation.h b/engines/voyeur/animation.h index b17e998214..bc6d8a361a 100644 --- a/engines/voyeur/animation.h +++ b/engines/voyeur/animation.h @@ -105,7 +105,7 @@ private: class RL2VideoTrack : public FixedRateVideoTrack { public: - RL2VideoTrack(const RL2FileHeader &header, RL2AudioTrack *audioTrack, + RL2VideoTrack(const RL2FileHeader &header, RL2AudioTrack *audioTrack, Common::SeekableReadStream *stream); ~RL2VideoTrack(); diff --git a/engines/voyeur/data.cpp b/engines/voyeur/data.cpp index cc0b81a313..b8c987f18b 100644 --- a/engines/voyeur/data.cpp +++ b/engines/voyeur/data.cpp @@ -94,7 +94,7 @@ SVoy::SVoy(VoyeurEngine *vm):_vm(vm) { _evCmPtrs[i] = nullptr; } -void SVoy::addEvent(int hour, int minute, VoyeurEventType type, int audioVideoId, +void SVoy::addEvent(int hour, int minute, VoyeurEventType type, int audioVideoId, int on, int off, int dead) { VoyeurEvent &e = _events[_eventCount++]; @@ -309,7 +309,7 @@ bool SVoy::checkForKey() { if (e._audioVideoId == 40 && e._computerOn < 2 && e._computerOff > 6) state->_victimEvidenceIndex = 4; break; - + default: break; } @@ -321,7 +321,7 @@ bool SVoy::checkForKey() { if (e._audioVideoId == 8 && e._computerOn < 2 && e._computerOff > 26) state->_victimEvidenceIndex = 1; break; - + case 3: if (e._audioVideoId == 20 && e._computerOn < 2 && e._computerOff > 28) state->_victimEvidenceIndex = 3; diff --git a/engines/voyeur/data.h b/engines/voyeur/data.h index 98c884d0c1..a18ad84f51 100644 --- a/engines/voyeur/data.h +++ b/engines/voyeur/data.h @@ -101,7 +101,7 @@ public: */ bool isInRange(int slotIndex, int hotspotIndex, int v) const { return _min[slotIndex][hotspotIndex] <= v && - v < _max[slotIndex][hotspotIndex]; + v < _max[slotIndex][hotspotIndex]; } }; @@ -164,7 +164,7 @@ public: /** * Add an event to the list of game events that have occurred */ - void addEvent(int hour, int minute, VoyeurEventType type, int audioVideoId, + void addEvent(int hour, int minute, VoyeurEventType type, int audioVideoId, int on, int off, int dead); /** @@ -181,7 +181,7 @@ public: * Adds the start of an audio event happening */ void addAudioEventStart(); - + /** * Adsd the finish of an audio event happening */ @@ -191,17 +191,17 @@ public: * Adds the start of an evidence event happening */ void addEvidEventStart(int v); - + /** * Adds the finish of an evidence event happening */ void addEvidEventEnd(int totalPages); - + /** * Adds the start of a computer event happening */ void addComputerEventStart(); - + /** * Adds the finish of a computer event happening */ diff --git a/engines/voyeur/debugger.cpp b/engines/voyeur/debugger.cpp index 234300bce5..e9a12180da 100644 --- a/engines/voyeur/debugger.cpp +++ b/engines/voyeur/debugger.cpp @@ -29,11 +29,10 @@ namespace Voyeur { Debugger::Debugger(VoyeurEngine *vm) : GUI::Debugger(), _vm(vm) { // Register methods - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("exit", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("time", WRAP_METHOD(Debugger, Cmd_Time)); - DCmd_Register("hotspots", WRAP_METHOD(Debugger, Cmd_Hotspots)); - DCmd_Register("mouse", WRAP_METHOD(Debugger, Cmd_Mouse)); + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("time", WRAP_METHOD(Debugger, Cmd_Time)); + registerCmd("hotspots", WRAP_METHOD(Debugger, Cmd_Hotspots)); + registerCmd("mouse", WRAP_METHOD(Debugger, Cmd_Mouse)); // Set fields _isTimeActive = true; @@ -46,44 +45,44 @@ static const int TIME_STATES[] = { bool Debugger::Cmd_Time(int argc, const char **argv) { if (argc < 2) { - // Get the current day and time of day + // Get the current day and time of day Common::String dtString = _vm->getDayName(); Common::String timeString = _vm->getTimeOfDay(); if (!timeString.empty()) dtString += " " + timeString; - DebugPrintf("Time period = %d, date/time is: %s, time is %s\n", + debugPrintf("Time period = %d, date/time is: %s, time is %s\n", _vm->_voy->_transitionId, dtString.c_str(), _isTimeActive ? "on" : "off"); - DebugPrintf("Format: %s [on | off | 1..17 | val <amount>]\n\n", argv[0]); + debugPrintf("Format: %s [on | off | 1..17 | val <amount>]\n\n", argv[0]); } else { if (!strcmp(argv[1], "on")) { _isTimeActive = true; - DebugPrintf("Time is now on\n\n"); + debugPrintf("Time is now on\n\n"); } else if (!strcmp(argv[1], "off")) { _isTimeActive = false; - DebugPrintf("Time is now off\n\n"); + debugPrintf("Time is now off\n\n"); } else if (!strcmp(argv[1], "val")) { if (argc < 3) { - DebugPrintf("Time expired is currently %d.\n", _vm->_voy->_RTVNum); + debugPrintf("Time expired is currently %d.\n", _vm->_voy->_RTVNum); } else { _vm->_voy->_RTVNum = atoi(argv[2]); - DebugPrintf("Time expired is now %d.\n", _vm->_voy->_RTVNum); + debugPrintf("Time expired is now %d.\n", _vm->_voy->_RTVNum); } } else { int timeId = atoi(argv[1]); if (timeId >= 1 && timeId < 17) { int stateId = TIME_STATES[timeId - 1]; if (!stateId) { - DebugPrintf("Given time period is not used in-game\n"); + debugPrintf("Given time period is not used in-game\n"); } else { - DebugPrintf("Changing to time period: %d\n", timeId); + debugPrintf("Changing to time period: %d\n", timeId); if (_vm->_mainThread->goToState(-1, stateId)) _vm->_mainThread->parsePlayCommands(); return false; } } else { - DebugPrintf("Unknown parameter\n\n"); + debugPrintf("Unknown parameter\n\n"); } } } @@ -93,7 +92,7 @@ bool Debugger::Cmd_Time(int argc, const char **argv) { bool Debugger::Cmd_Hotspots(int argc, const char **argv) { if (_vm->_voy->_computerTextId >= 0) { - DebugPrintf("Hotspot Computer Screen %d - %d,%d->%d,%d\n", + debugPrintf("Hotspot Computer Screen %d - %d,%d->%d,%d\n", _vm->_voy->_computerTextId, _vm->_voy->_computerScreenRect.left, _vm->_voy->_computerScreenRect.top, @@ -112,9 +111,9 @@ bool Debugger::Cmd_Hotspots(int argc, const char **argv) { hotspots[hotspotIdx].right, hotspots[hotspotIdx].bottom); int arrIndex = hotspots[hotspotIdx]._arrIndex; if (_vm->_voy->_roomHotspotsEnabled[arrIndex - 1]) { - DebugPrintf("Hotspot Room %d - %s - Enabled\n", arrIndex, pos); + debugPrintf("Hotspot Room %d - %s - Enabled\n", arrIndex, pos); } else { - DebugPrintf("Hotspot Room - %s - Disabled\n", pos); + debugPrintf("Hotspot Room - %s - Disabled\n", pos); } } } @@ -132,14 +131,14 @@ bool Debugger::Cmd_Hotspots(int argc, const char **argv) { for (int arrIndex = 0; arrIndex < 3; ++arrIndex) { if (_vm->_voy->_audioHotspotTimes._min[arrIndex][hotspotIdx] != 9999) { - DebugPrintf("Hotspot %d %s Audio slot %d, time: %d to %d\n", + debugPrintf("Hotspot %d %s Audio slot %d, time: %d to %d\n", hotspotIdx, pos.c_str(), arrIndex, _vm->_voy->_audioHotspotTimes._min[arrIndex][hotspotIdx], _vm->_voy->_audioHotspotTimes._max[arrIndex][hotspotIdx]); } if (_vm->_voy->_evidenceHotspotTimes._min[arrIndex][hotspotIdx] != 9999) { - DebugPrintf("Hotspot %d %s Evidence slot %d, time: %d to %d\n", + debugPrintf("Hotspot %d %s Evidence slot %d, time: %d to %d\n", hotspotIdx, pos.c_str(), arrIndex, _vm->_voy->_evidenceHotspotTimes._min[arrIndex][hotspotIdx], _vm->_voy->_evidenceHotspotTimes._max[arrIndex][hotspotIdx]); @@ -148,7 +147,7 @@ bool Debugger::Cmd_Hotspots(int argc, const char **argv) { for (int arrIndex = 0; arrIndex < 8; ++arrIndex) { if (_vm->_voy->_videoHotspotTimes._min[arrIndex][hotspotIdx] != 9999) { - DebugPrintf("Hotspot %d %s Video slot %d, time: %d to %d\n", + debugPrintf("Hotspot %d %s Video slot %d, time: %d to %d\n", hotspotIdx, pos.c_str(), arrIndex, _vm->_voy->_videoHotspotTimes._min[arrIndex][hotspotIdx], _vm->_voy->_videoHotspotTimes._max[arrIndex][hotspotIdx]); @@ -157,16 +156,16 @@ bool Debugger::Cmd_Hotspots(int argc, const char **argv) { } } - DebugPrintf("\nEnd of list\n"); + debugPrintf("\nEnd of list\n"); return true; } bool Debugger::Cmd_Mouse(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("mouse [ on | off ]\n"); + debugPrintf("mouse [ on | off ]\n"); } else { _showMousePosition = !strcmp(argv[1], "on"); - DebugPrintf("Mouse position is now %s\n", _showMousePosition ? "on" : "off"); + debugPrintf("Mouse position is now %s\n", _showMousePosition ? "on" : "off"); } return true; diff --git a/engines/voyeur/events.cpp b/engines/voyeur/events.cpp index 9a3c6d00ff..7ce7351e65 100644 --- a/engines/voyeur/events.cpp +++ b/engines/voyeur/events.cpp @@ -73,7 +73,7 @@ EventsManager::EventsManager(VoyeurEngine *vm) : _intPtr(_gameData), Common::fill(&_cycleTime[0], &_cycleTime[4], 0); Common::fill(&_cycleNext[0], &_cycleNext[4], (byte *)nullptr); _cyclePtr = NULL; - + _leftClick = _rightClick = false; _mouseClicked = _newMouseClicked = false; _newLeftClick = _newRightClick = false;; @@ -158,7 +158,7 @@ void EventsManager::checkForNextFrameCounter() { showMousePosition(); // Display the frame - g_system->copyRectToScreen((byte *)_vm->_graphicsManager->_screenSurface.getPixels(), + g_system->copyRectToScreen((byte *)_vm->_graphicsManager->_screenSurface.getPixels(), SCREEN_WIDTH, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); g_system->updateScreen(); @@ -218,7 +218,7 @@ void EventsManager::videoTimer() { _gameData._hasPalette = false; g_system->getPaletteManager()->setPalette(_gameData._palette + - _gameData._palStartIndex * 3, _gameData._palStartIndex, + _gameData._palStartIndex * 3, _gameData._palStartIndex, _gameData._palEndIndex - _gameData._palStartIndex + 1); } } @@ -241,7 +241,7 @@ void EventsManager::delayClick(int cycles) { do { g_system->delayMillis(10); getMouseInfo(); - } while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd + } while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd && !_vm->_eventsManager->_mouseClicked); } @@ -315,7 +315,7 @@ void EventsManager::startFade(CMapResource *cMap) { palEntry._bEntry = vgaP[2] << 8; int bDiff = (cMap->_entries[mapIndex * 3 + 2] << 8) - palEntry._bEntry; palEntry._bChange = bDiff / cMap->_steps; - + palEntry._palIndex = idx; if (!(cMap->_fadeStatus & 1)) ++mapIndex; @@ -431,12 +431,12 @@ void EventsManager::vDoCycleInt() { byte b = pPal[start * 3 + 2]; Common::copy(&pPal[start * 3 + 3], &pPal[end * 3 + 3], &pPal[start * 3]); - + // Place the original saved entry at the end of the range pPal[end * 3] = r; pPal[end * 3 + 1] = g; pPal[end * 3 + 2] = b; - + if (_fadeStatus & 1) { //dx = start, di = end warning("TODO: Adjustment of ViewPortListResource"); @@ -454,12 +454,12 @@ void EventsManager::vDoCycleInt() { // Move the remainder of the range forwards one entry Common::copy_backward(&pPal[start * 3], &pPal[end * 3], &pPal[end * 3 + 3]); - + // Place the original saved entry at the end of the range pPal[start * 3] = r; pPal[start * 3 + 1] = g; pPal[start * 3 + 2] = b; - + if (_fadeStatus & 1) { //dx = start, di = end warning("TODO: Adjustment of ViewPortListResource"); diff --git a/engines/voyeur/events.h b/engines/voyeur/events.h index 5e0bfe6404..0c1cef0955 100644 --- a/engines/voyeur/events.h +++ b/engines/voyeur/events.h @@ -38,7 +38,7 @@ class CMapResource; #define GAME_FRAME_TIME (1000 / GAME_FRAME_RATE) typedef void (EventsManager::*EventMethodPtr)(); - + class IntNode { public: EventMethodPtr _intFunc; diff --git a/engines/voyeur/files.cpp b/engines/voyeur/files.cpp index 7369d9280e..346fd2419e 100644 --- a/engines/voyeur/files.cpp +++ b/engines/voyeur/files.cpp @@ -421,8 +421,8 @@ byte *BoltFile::getBoltMember(uint32 id) { } void BoltFile::initDefault() { - _state._curMemberPtr->_data = _state.decompress(NULL, _state._curMemberPtr->_size, - _state._curMemberPtr->_mode); + _state._curMemberPtr->_data = _state.decompress(NULL, _state._curMemberPtr->_size, + _state._curMemberPtr->_mode); } /*------------------------------------------------------------------------*/ @@ -505,7 +505,7 @@ void BVoyBoltFile::initSoundMap() { } void BVoyBoltFile::sInitRect() { - _state._curMemberPtr->_data = _state.decompress(NULL, _state._curMemberPtr->_size, + _state._curMemberPtr->_data = _state.decompress(NULL, _state._curMemberPtr->_size, _state._curMemberPtr->_mode); // Check whether the resource Id is in the list of extended rects @@ -522,7 +522,7 @@ void BVoyBoltFile::sInitRect() { void BVoyBoltFile::sInitPic() { // Read in the header data _state._curMemberPtr->_data = _state.decompress(NULL, 24, _state._curMemberPtr->_mode); - _state._curMemberPtr->_picResource = new PictureResource(_state, + _state._curMemberPtr->_picResource = new PictureResource(_state, _state._curMemberPtr->_data); } @@ -567,14 +567,14 @@ void StampBoltFile::initResource(int resType) { void StampBoltFile::initThread() { initDefault(); - _state._curMemberPtr->_threadResource = new ThreadResource(_state, + _state._curMemberPtr->_threadResource = new ThreadResource(_state, _state._curMemberPtr->_data); } void StampBoltFile::initPtr() { initDefault(); - _state._curMemberPtr->_ptrResource = new PtrResource(_state, + _state._curMemberPtr->_ptrResource = new PtrResource(_state, _state._curMemberPtr->_data); } @@ -585,7 +585,7 @@ void StampBoltFile::initControl() { initDefault(); ControlResource *res; - _state._curMemberPtr->_controlResource = res = new ControlResource(_state, + _state._curMemberPtr->_controlResource = res = new ControlResource(_state, _state._curMemberPtr->_data); _state._vm->_controlGroupPtr = _state._curGroupPtr; @@ -596,7 +596,7 @@ void StampBoltFile::initState() { initDefault(); assert(_state._curMemberPtr->_size == 16); - _state._curMemberPtr->_stateResource = new StateResource(_state, + _state._curMemberPtr->_stateResource = new StateResource(_state, _state._curMemberPtr->_data); } @@ -658,7 +658,7 @@ BoltEntry::BoltEntry(Common::SeekableReadStream *f, uint16 id): _file(f), _id(id _mode = buffer[0]; _initMethod = buffer[3]; _size = READ_LE_UINT32(&buffer[4]) & 0xffffff; - _fileOffset = READ_LE_UINT32(&buffer[8]); + _fileOffset = READ_LE_UINT32(&buffer[8]); } BoltEntry::~BoltEntry() { @@ -687,7 +687,7 @@ void BoltEntry::load() { */ bool BoltEntry::hasResource() const { return _rectResource || _picResource || _viewPortResource || _viewPortListResource - || _fontResource || _fontInfoResource || _cMapResource || _vInitCycleResource + || _fontResource || _fontInfoResource || _cMapResource || _vInitCycleResource || _ptrResource || _controlResource || _stateResource || _threadResource; } @@ -719,7 +719,7 @@ RectResource::RectResource(const byte *src, int size, bool isExtendedRects) { int x1 = READ_LE_UINT16(src); int y1 = READ_LE_UINT16(src + 2); - int x2 = READ_LE_UINT16(src + 4); + int x2 = READ_LE_UINT16(src + 4); int y2 = READ_LE_UINT16(src + 6); _entries.push_back(RectEntry(x1, y1, x2, y2, arrIndex, rectCount)); @@ -896,7 +896,7 @@ int DisplayResource::drawText(const Common::String &msg) { viewPort->_fontRect.top -= fontInfo._shadow.y; } } - } + } if (gfxManager._saveBack && fontInfo._fontSaveBack && (_flags & DISPFLAG_VIEWPORT)) { viewPort->addSaveRect(viewPort->_pageIndex, viewPort->_fontRect); @@ -971,7 +971,7 @@ int DisplayResource::drawText(const Common::String &msg) { fontChar._imgData = fontData._charImages + offset * 2; gfxManager.sDrawPic(&fontChar, this, Common::Point(xp, yp)); - + fontChar._imgData = NULL; xp += charWidth + padding; msgWidth += charWidth + padding; @@ -1056,7 +1056,7 @@ PictureResource::PictureResource(BoltFilesState &state, const byte *src): byte *imgData = state._curLibPtr->boltEntry(id)._picResource->_imgData; _freeImgData = DisposeAfterUse::NO; - // TODO: Double check code below. Despite different coding in the + // TODO: Double check code below. Despite different coding in the // original, both looked like they do the same formula if (_flags & PICFLAG_PIC_OFFSET) { _imgData = imgData + (READ_LE_UINT32(&src[18]) & 0xffff); @@ -1082,7 +1082,7 @@ PictureResource::PictureResource(BoltFilesState &state, const byte *src): if (mode != state._vm->_graphicsManager->_SVGAMode) { state._vm->_graphicsManager->_SVGAMode = mode; - state._vm->_graphicsManager->clearPalette(); + state._vm->_graphicsManager->clearPalette(); } int screenOffset = READ_LE_UINT32(&src[18]) & 0xffff; @@ -1118,7 +1118,7 @@ PictureResource::PictureResource(BoltFilesState &state, const byte *src): _imgData = new byte[nbytes]; Common::fill(_imgData, _imgData + nbytes, 0); } else { - _imgData = state.decompress(NULL, nbytes, state._curMemberPtr->_mode); + _imgData = state.decompress(NULL, nbytes, state._curMemberPtr->_mode); } } } @@ -1131,7 +1131,7 @@ PictureResource::PictureResource(Graphics::Surface *surface) { _maskData = 0; _planeSize = 0; _keyColor = 0; - + _bounds = Common::Rect(0, 0, surface->w, surface->h); _imgData = (byte *)surface->getPixels(); _freeImgData = DisposeAfterUse::NO; @@ -1150,7 +1150,7 @@ PictureResource::PictureResource() { _freeImgData = DisposeAfterUse::NO; } -PictureResource::PictureResource(int flags, int select, int pick, int onOff, +PictureResource::PictureResource(int flags, int select, int pick, int onOff, const Common::Rect &bounds, int maskData, byte *imgData, int planeSize) { _flags = flags; _select = select; @@ -1189,7 +1189,7 @@ void PictureResource::flipVertical(const byte *data) { for (int y = 0; y < _bounds.height(); ++y) { Common::copy(srcP, srcP + _bounds.width(), destP); srcP += _bounds.width(); - destP -= _bounds.width(); + destP -= _bounds.width(); } } @@ -1205,7 +1205,7 @@ ViewPortResource::ViewPortResource(BoltFilesState &state, const byte *src): int xs = READ_LE_UINT16(src + 12); int ys = READ_LE_UINT16(src + 14); - _bounds = Common::Rect(xs, ys, xs + READ_LE_UINT16(src + 16), + _bounds = Common::Rect(xs, ys, xs + READ_LE_UINT16(src + 16), ys + READ_LE_UINT16(src + 18)); _currentPic = state._curLibPtr->getPictureResource(READ_LE_UINT32(src + 0x20)); @@ -1285,7 +1285,7 @@ void ViewPortResource::setupViewPort(PictureResource *page, Common::Rect *clippi yDiff = r.bottom - page->_bounds.bottom; if (xDiff > 0) - r.setWidth(xDiff <= r.width() ? r.width() - xDiff : 0); + r.setWidth(xDiff <= r.width() ? r.width() - xDiff : 0); if (yDiff > 0) r.setHeight(yDiff <= r.height() ? r.height() - yDiff : 0); } @@ -1305,7 +1305,7 @@ void ViewPortResource::setupViewPort(PictureResource *page, Common::Rect *clippi r.top = clippingRect->top; r.setHeight(yDiff <= height ? height - yDiff : 0); } - + xDiff = r.right - clippingRect->right; yDiff = r.bottom - clippingRect->bottom; @@ -1339,7 +1339,7 @@ void ViewPortResource::setupViewPort(PictureResource *pic, Common::Rect *clippin void ViewPortResource::addSaveRect(int pageIndex, const Common::Rect &r) { Common::Rect rect = r; - + if (clipRect(rect)) { if (_addFn) { (_state._vm->_graphicsManager->*_addFn)(this, pageIndex, rect); @@ -1355,21 +1355,21 @@ void ViewPortResource::fillPic(byte onOff) { void ViewPortResource::drawIfaceTime() { // Hour display - _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort, + _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort, (_state._vm->_gameHour / 10) == 0 ? 10 : _state._vm->_gameHour / 10, Common::Point(161, 25)); - _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort, + _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort, _state._vm->_gameHour % 10, Common::Point(172, 25)); // Minute display - _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort, + _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort, _state._vm->_gameMinute / 10, Common::Point(190, 25)); - _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort, + _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort, _state._vm->_gameMinute % 10, Common::Point(201, 25)); // AM/PM indicator PictureResource *pic = _state._vm->_bVoy->boltEntry(_state._vm->_voy->_isAM ? 272 : 273)._picResource; - _state._vm->_graphicsManager->sDrawPic(pic, _state._vm->_graphicsManager->_vPort, + _state._vm->_graphicsManager->sDrawPic(pic, _state._vm->_graphicsManager->_vPort, Common::Point(215, 27)); } @@ -1488,9 +1488,9 @@ FontInfoResource::FontInfoResource() { _shadowColor = 0; } -FontInfoResource::FontInfoResource(byte picFlags, byte picSelect, byte picPick, byte picOnOff, - byte fontFlags, FontJustify justify, int fontSaveBack, const Common::Point &pos, - int justifyWidth, int justifyHeight, const Common::Point &shadow, int foreColor, +FontInfoResource::FontInfoResource(byte picFlags, byte picSelect, byte picPick, byte picOnOff, + byte fontFlags, FontJustify justify, int fontSaveBack, const Common::Point &pos, + int justifyWidth, int justifyHeight, const Common::Point &shadow, int foreColor, int backColor, int shadowColor) { _curFont = NULL; _picFlags = picFlags; @@ -1516,7 +1516,7 @@ CMapResource::CMapResource(BoltFilesState &state, const byte *src): _vm(state._v _fadeStatus = src[1]; _start = READ_LE_UINT16(src + 2); _end = READ_LE_UINT16(src + 4); - + int count = _end - _start + 1; _entries = new byte[count * 3]; Common::copy(src + 6, src + 6 + 3 * count, _entries); @@ -1607,7 +1607,7 @@ ControlResource::ControlResource(BoltFilesState &state, const byte *src) { /*------------------------------------------------------------------------*/ StateResource::StateResource(BoltFilesState &state, const byte *src): - _victimIndex(_vals[1]), _victimEvidenceIndex(_vals[2]), + _victimIndex(_vals[1]), _victimEvidenceIndex(_vals[2]), _victimMurderIndex(_vals[3]) { for (int i = 0; i < 4; ++i) _vals[i] = READ_LE_UINT32(src + i * 4); diff --git a/engines/voyeur/files.h b/engines/voyeur/files.h index 49c0b2c8a4..eef5df497c 100644 --- a/engines/voyeur/files.h +++ b/engines/voyeur/files.h @@ -114,7 +114,7 @@ public: void resolveIt(uint32 id, byte **p); void resolveFunction(uint32 id, GraphicMethodPtr *fn); - BoltEntry &boltEntry(uint16 id); + BoltEntry &boltEntry(uint16 id); BoltEntry &getBoltEntryFromLong(uint32 id); PictureResource *getPictureResource(uint32 id); CMapResource *getCMapResource(uint32 id); @@ -160,7 +160,7 @@ public: int _fileOffset; Common::Array<BoltEntry> _entries; public: - BoltGroup(Common::SeekableReadStream *f); + BoltGroup(Common::SeekableReadStream *f); virtual ~BoltGroup(); void load(uint16 groupId); @@ -234,15 +234,15 @@ public: /* bvoy.blt resource types */ enum PictureFlag { - PICFLAG_2 = 2, PICFLAG_PIC_OFFSET = 8, PICFLAG_CLEAR_SCREEN = 0x10, + PICFLAG_2 = 2, PICFLAG_PIC_OFFSET = 8, PICFLAG_CLEAR_SCREEN = 0x10, PICFLAG_20 = 0x20, PICFLAG_HFLIP = 0x40, PICFLAG_VFLIP = 0x80, PICFLAG_100 = 0x100, - PICFLAG_CLEAR_SCREEN00 = 0x1000 + PICFLAG_CLEAR_SCREEN00 = 0x1000 }; enum DisplayFlag { - DISPFLAG_1 = 1, DISPFLAG_2 = 2, DISPFLAG_4 = 4, DISPFLAG_8 = 8, + DISPFLAG_1 = 1, DISPFLAG_2 = 2, DISPFLAG_4 = 4, DISPFLAG_8 = 8, DISPFLAG_10 = 0x10, DISPFLAG_20 = 0x20, DISPFLAG_40 = 0x40, DISPFLAG_80 = 0x80, - DISPFLAG_100 = 0x100, DISPFLAG_200 = 0x200, DISPFLAG_400 = 0x400, + DISPFLAG_100 = 0x100, DISPFLAG_200 = 0x200, DISPFLAG_400 = 0x400, DISPFLAG_800 = 0x800, DISPFLAG_1000 = 0x1000, DISPFLAG_2000 = 0x2000, DISPFLAG_4000 = 0x4000, DISPFLAG_VIEWPORT = 0x8000, DISPFLAG_CURSOR = 0x10000, DISPFLAG_NONE = 0}; @@ -256,7 +256,7 @@ public: DisplayResource(); DisplayResource(VoyeurEngine *vm); - /** + /** * Fill a box of the given size at the current _drawPtr location */ void sFillBox(int width, int height); @@ -308,7 +308,7 @@ public: DisposeAfterUse::Flag _freeImgData; public: PictureResource(BoltFilesState &state, const byte *src); - PictureResource(int flags, int select, int pick, int onOff, + PictureResource(int flags, int select, int pick, int onOff, const Common::Rect &bounds, int maskData, byte *imgData, int planeSize); PictureResource(Graphics::Surface *surface); PictureResource(); @@ -334,7 +334,7 @@ public: PictureResource *_pages[2]; // Rect lists and counts. Note that _rectListCount values of '-1' seem to have - // special significance, which is why I'm not making them redundant in favor + // special significance, which is why I'm not making them redundant in favor // of the arrays' .size() method Common::Array<Common::Rect> *_rectListPtr[3]; int _rectListCount[3]; @@ -413,9 +413,9 @@ public: public: FontInfoResource(BoltFilesState &state, const byte *src); FontInfoResource(); - FontInfoResource(byte picFlags, byte picSelect, byte picPick, byte picOnOff, byte fontFlags, - FontJustify justify, int fontSaveBack, const Common::Point &pos, int justifyWidth, - int justifyHeight, const Common::Point &shadow, int foreColor, int backColor, + FontInfoResource(byte picFlags, byte picSelect, byte picPick, byte picOnOff, byte fontFlags, + FontJustify justify, int fontSaveBack, const Common::Point &pos, int justifyWidth, + int justifyHeight, const Common::Point &shadow, int foreColor, int backColor, int shadowColor); }; diff --git a/engines/voyeur/files_threads.cpp b/engines/voyeur/files_threads.cpp index 700944f7ef..b1960a23ac 100644 --- a/engines/voyeur/files_threads.cpp +++ b/engines/voyeur/files_threads.cpp @@ -97,7 +97,7 @@ void ThreadResource::unloadAStack(int stackId) { } bool ThreadResource::doState() { - if (!getStateInfo()) + if (!getStateInfo()) return false; getButtonsFlags(); @@ -122,7 +122,7 @@ bool ThreadResource::getStateInfo() { uint32 fld = READ_LE_UINT32(_ctlPtr + 2); fld += _stateId << 3; _nextStateId = READ_LE_UINT32(_ctlPtr + fld + 4); - + fld = READ_LE_UINT32(_ctlPtr + fld); byte *baseP = _ctlPtr + fld; _stateCount = READ_LE_UINT16(baseP); @@ -133,7 +133,7 @@ bool ThreadResource::getStateInfo() { _playCommandsPtr += (READ_LE_UINT32(baseP + 6) / 2) << 1; _threadInfoPtr = baseP + 10; - + getButtonsText(); return true; } @@ -146,7 +146,7 @@ byte *ThreadResource::getDataOffset() { void ThreadResource::getButtonsText() { int idx = 0; - + for (const byte *p = _threadInfoPtr; *p != 0x49; p = getNextRecord(p)) { if (*p == 0xC0) { ++p; @@ -162,7 +162,7 @@ void ThreadResource::getButtonsText() { void ThreadResource::getButtonsFlags() { int idx = 0; - + for (const byte *p = _threadInfoPtr; *p != 0x49; p = getNextRecord(p)) { if (*p == 0xC0) { if (*++p & 0x20) @@ -379,9 +379,9 @@ void ThreadResource::parsePlayCommands() { _vm->_eventsManager->incrementTime(1); _vm->_audioVideoId = -1; parseIndex = 999; - } - } - + } + } + dataP += 8; break; @@ -408,7 +408,7 @@ void ThreadResource::parsePlayCommands() { _vm->_voy->_eventFlags |= EVTFLAG_TIME_DISABLED; _vm->_voy->addVideoEventEnd(); _vm->_eventsManager->incrementTime(1); - + _vm->_audioVideoId = -1; _vm->_playStampGroupId = -1; @@ -494,7 +494,7 @@ void ThreadResource::parsePlayCommands() { _vm->_audioVideoId = -1; parseIndex = 999; } - break; + break; case 5: // Check whether transition to a given time period is allowed, and @@ -587,8 +587,8 @@ void ThreadResource::parsePlayCommands() { case 10: // Pick the person who is to die, during startup if (_vm->_iForceDeath == -1) { - // No specific person has been preset to be killed, so pick one randomly. - // The loop below was used because the victim was persisted from the previous + // No specific person has been preset to be killed, so pick one randomly. + // The loop below was used because the victim was persisted from the previous // play-through, so it ensured that a different victim is picked. int randomVal; do { @@ -663,7 +663,7 @@ void ThreadResource::parsePlayCommands() { if (v2 == 0 || _vm->_controlPtr->_state->_victimIndex == v2) _vm->_voy->_murderThreshold = v3; - + dataP += 4; break; @@ -819,7 +819,7 @@ const byte *ThreadResource::cardPerform(const byte *card) { case 24: case 27: case 28: - subId -= 3; + subId -= 3; // Deliberate fall-through case 21: @@ -858,13 +858,13 @@ const byte *ThreadResource::cardPerform(const byte *card) { ++count; } } - + ++card; } else { if (cardPerform2(card, id)) { card += subId; card = cardPerform(card); - while (*card++ != 61) ; + while (*card++ != 61) ; } else { card += subId; while (*card != 61 && *card != 29) @@ -878,7 +878,7 @@ const byte *ThreadResource::cardPerform(const byte *card) { assert(bVal < 8); card += 6; break; - + case 45: _newStateId = _nextStateId; _newStackId = _stackId; @@ -929,12 +929,12 @@ bool ThreadResource::cardPerform2(const byte *pSrc, int cardCmdId) { return vLong != vLong2; case 25: - vLong = _vm->_controlPtr->_state->_vals[*pSrc]; + vLong = _vm->_controlPtr->_state->_vals[*pSrc]; vLong2 = (int32)READ_LE_UINT32(pSrc + 1); return vLong < vLong2; case 26: - vLong = _vm->_controlPtr->_state->_vals[*pSrc]; + vLong = _vm->_controlPtr->_state->_vals[*pSrc]; vLong2 = (int32)READ_LE_UINT32(pSrc + 1); return vLong > vLong2; @@ -951,13 +951,13 @@ bool ThreadResource::cardPerform2(const byte *pSrc, int cardCmdId) { default: return false; } -} +} int ThreadResource::doApt() { loadTheApt(); _vm->_currentVocId = 151; - _vm->_voy->_viewBounds = _vm->_bVoy->boltEntry(_vm->_playStampGroupId)._rectResource; + _vm->_voy->_viewBounds = _vm->_bVoy->boltEntry(_vm->_playStampGroupId)._rectResource; Common::Array<RectEntry> &hotspots = _vm->_bVoy->boltEntry( _vm->_playStampGroupId + 1)._rectResource->_entries; _vm->_eventsManager->getMouseInfo(); @@ -1039,7 +1039,7 @@ int ThreadResource::doApt() { hotspotId = 5; // Draw the text description for the highlighted hotspot - pic = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + + pic = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + hotspotId + 6)._picResource; _vm->_graphicsManager->sDrawPic(pic, _vm->_graphicsManager->_vPort, Common::Point(106, 200)); @@ -1101,10 +1101,10 @@ int ThreadResource::doApt() { void ThreadResource::doRoom() { VoyeurEngine &vm = *_vm; SVoy voy = *vm._voy; - + vm.makeViewFinderP(); voy._fadingType = 0; - + if (!vm._bVoy->getBoltGroup(vm._playStampGroupId)) return; @@ -1116,7 +1116,7 @@ void ThreadResource::doRoom() { voy._fadingStep1 = 2; voy._fadingStep2 = 0; voy._fadingType = 1; - + Common::Array<RectEntry> &hotspots = vm._bVoy->boltEntry(vm._playStampGroupId + 4)._rectResource->_entries; int hotspotId = -1; @@ -1214,7 +1214,7 @@ void ThreadResource::doRoom() { vm._eventsManager->_mouseClicked = false; vm._eventsManager->startCursorBlink(); - int totalChars = vm.doComputerText(9999); + int totalChars = vm.doComputerText(9999); if (totalChars) vm._voy->addComputerEventEnd(totalChars); @@ -1345,12 +1345,12 @@ int ThreadResource::doInterface() { Common::String fname = _vm->_soundManager->getVOCFileName(_vm->_currentVocId); _vm->_soundManager->startVOCPlay(fname); _vm->_eventsManager->getMouseInfo(); - + _vm->_graphicsManager->setColor(240, 220, 220, 220); _vm->_eventsManager->_intPtr._hasPalette = true; _vm->_voy->_eventFlags &= ~EVTFLAG_TIME_DISABLED; - // Set the cusor + // Set the cusor PictureResource *crosshairsCursor = _vm->_bVoy->boltEntry(0x112)._picResource; PictureResource *eyeCursor = _vm->_bVoy->boltEntry(0x113)._picResource; PictureResource *listenCursor = _vm->_bVoy->boltEntry(0x114)._picResource; @@ -1382,7 +1382,7 @@ int ThreadResource::doInterface() { if (!mansionViewBounds.contains(pt)) pt = Common::Point(-1, -1); else - pt = _vm->_mansionViewPos + + pt = _vm->_mansionViewPos + Common::Point(pt.x - MANSION_VIEW_X, pt.y - MANSION_VIEW_Y); regionIndex = -1; @@ -1420,20 +1420,20 @@ int ThreadResource::doInterface() { // Regularly update the time display if (_vm->_voy->_RTANum & 2) { - _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort, + _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort, _vm->_gameMinute / 10, Common::Point(190, 25)); - _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort, + _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort, _vm->_gameMinute % 10, Common::Point(201, 25)); if (_vm->_voy->_RTANum & 4) { int v = _vm->_gameHour / 10; - _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort, + _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort, v == 0 ? 10 : v, Common::Point(161, 25)); - _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort, + _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort, _vm->_gameHour % 10, Common::Point(172, 25)); pic = _vm->_bVoy->boltEntry(_vm->_voy->_isAM ? 272 : 273)._picResource; - _vm->_graphicsManager->sDrawPic(pic, _vm->_graphicsManager->_vPort, + _vm->_graphicsManager->sDrawPic(pic, _vm->_graphicsManager->_vPort, Common::Point(215, 27)); } } @@ -1462,7 +1462,7 @@ int ThreadResource::doInterface() { _vm->makeViewFinder(); _vm->initIFace(); - + hotspots = &_vm->_bVoy->boltEntry(_vm->_playStampGroupId + 1)._rectResource->_entries; _vm->_eventsManager->getMouseInfo(); @@ -1471,7 +1471,7 @@ int ThreadResource::doInterface() { _vm->_eventsManager->_intPtr._flashTimer = 0; } } - } while (!_vm->_eventsManager->_rightClick && !_vm->shouldQuit() && + } while (!_vm->_eventsManager->_rightClick && !_vm->shouldQuit() && (!_vm->_eventsManager->_leftClick || regionIndex == -1)); _vm->_eventsManager->hideCursor(); @@ -1612,7 +1612,7 @@ void ThreadResource::loadTheApt() { } CMapResource *pal = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + 4)._cMapResource; - pal->_steps = 1; + pal->_steps = 1; pal->startFade(); _vm->flipPageAndWaitForFade(); } @@ -1715,7 +1715,7 @@ void ThreadResource::doAptAnim(int mode) { void ThreadResource::synchronize(Common::Serializer &s) { s.syncAsSint16LE(_aptPos.x); s.syncAsSint16LE(_aptPos.y); - + int stateId = _stateId; int stackId = _stackId; s.syncAsSint16LE(stateId); diff --git a/engines/voyeur/graphics.cpp b/engines/voyeur/graphics.cpp index f756b9cc85..68a30e41f4 100644 --- a/engines/voyeur/graphics.cpp +++ b/engines/voyeur/graphics.cpp @@ -97,9 +97,9 @@ void GraphicsManager::restoreMCGASaveRect(ViewPortResource *viewPort) { restoreBack(*viewPort->_rectListPtr[1], viewPort->_rectListCount[1], viewPort->_pages[0], viewPort->_pages[1]); - + int count = viewPort->_rectListCount[0]; - restoreBack(*viewPort->_rectListPtr[0], viewPort->_rectListCount[0], + restoreBack(*viewPort->_rectListPtr[0], viewPort->_rectListCount[0], viewPort->_activePage, viewPort->_currentPic); SWAP(viewPort->_rectListPtr[0], viewPort->_rectListPtr[1]); @@ -150,7 +150,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des destPic = (PictureResource *)destDisplay; } - Common::Point offset = Common::Point(initialOffset.x + srcPic->_bounds.left - destPic->_bounds.left, + Common::Point offset = Common::Point(initialOffset.x + srcPic->_bounds.left - destPic->_bounds.left, initialOffset.y + srcPic->_bounds.top - destPic->_bounds.top); width1 = width2 = srcPic->_bounds.width(); height1 = srcPic->_bounds.height(); @@ -178,7 +178,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des srcOffset -= tmpHeight * width2; height1 += tmpHeight; offset.y = newBounds.top; - + if (height1 <= 0) return; @@ -258,7 +258,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des for (uint idx = 0; idx < srcPic->_maskData; ++idx) { if (imageDataShift < 4) ++imageDataShift; - } + } } else { srcImgData = srcPic->_imgData; destImgData = destPic->_imgData; @@ -367,7 +367,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des width2 = srcPic->_bounds.width(); height1 = tmpHeight + height1; - + for (int yp = 0; yp < height1; ++yp) { runLength = 0; @@ -509,7 +509,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des if (srcFlags & DISPFLAG_2) { if (!(srcFlags & DISPFLAG_8)) { srcP = srcImgData + srcOffset; - + if (destFlags & DISPFLAG_8) { // loc_272C3 error("TODO: sDrawPic variation"); @@ -786,7 +786,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des } else { // loc_271F0 srcP = srcImgData; - + if (isClipped) { // loc_2700A tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0; @@ -886,7 +886,7 @@ void GraphicsManager::flipPage() { for (uint idx = 0; idx < viewPorts.size(); ++idx) { if (viewPorts[idx]->_flags & DISPFLAG_20) { - if ((viewPorts[idx]->_flags & (DISPFLAG_8 || DISPFLAG_1)) + if ((viewPorts[idx]->_flags & (DISPFLAG_8 || DISPFLAG_1)) == (DISPFLAG_8 || DISPFLAG_1)) { if (_planeSelect == idx) sDisplayPic(viewPorts[idx]->_currentPic); @@ -992,7 +992,7 @@ void GraphicsManager::screenReset() { _backgroundPage = NULL; _vPort->setupViewPort(NULL); - fillPic(_vPort, 0); + fillPic(_vPort, 0); _vm->flipPageAndWait(); } diff --git a/engines/voyeur/graphics.h b/engines/voyeur/graphics.h index 221d31061d..e4d0b38650 100644 --- a/engines/voyeur/graphics.h +++ b/engines/voyeur/graphics.h @@ -54,14 +54,13 @@ public: DrawInfo(int penColor, const Common::Point &pos); }; -typedef void (GraphicsManager::*GraphicMethodPtr)(); +typedef void (GraphicsManager::*GraphicMethodPtr)(); typedef void (GraphicsManager::*ViewPortSetupPtr)(ViewPortResource *); typedef void (GraphicsManager::*ViewPortAddPtr)(ViewPortResource *, int idx, const Common::Rect &bounds); typedef void (GraphicsManager::*ViewPortRestorePtr)(ViewPortResource *); class GraphicsManager { public: - VoyeurEngine *_vm; byte _VGAColors[PALETTE_SIZE]; PictureResource *_backgroundPage; int _SVGAMode; @@ -77,6 +76,8 @@ public: DrawInfo *_drawPtr; DrawInfo _defaultDrawInfo; private: + VoyeurEngine *_vm; + void restoreBack(Common::Array<Common::Rect> &rectList, int rectListCount, PictureResource *srcPic, PictureResource *destPic); public: @@ -86,7 +87,7 @@ public: void sInitGraphics(); void setupMCGASaveRect(ViewPortResource *viewPort); - void addRectOptSaveRect(ViewPortResource *viewPort, int idx, const Common::Rect &bounds); + void addRectOptSaveRect(ViewPortResource *viewPort, int idx, const Common::Rect &bounds); void restoreMCGASaveRect(ViewPortResource *viewPort); void addRectNoSaveBack(ViewPortResource *viewPort, int idx, const Common::Rect &bounds); @@ -101,7 +102,7 @@ public: void resetPalette(); void setColor(int idx, byte r, byte g, byte b); void setOneColor(int idx, byte r, byte g, byte b); - void setColors(int start, int count, const byte *pal); + void setColors(int start, int count, const byte *pal); void screenReset(); void fadeDownICF1(int steps); void fadeUpICF1(int steps = 0); diff --git a/engines/voyeur/sound.cpp b/engines/voyeur/sound.cpp index 26145bd743..c0e5a043cd 100644 --- a/engines/voyeur/sound.cpp +++ b/engines/voyeur/sound.cpp @@ -62,7 +62,7 @@ void SoundManager::startVOCPlay(const Common::String &filename) { if (!f.open(filename)) error("Could not find voc file - %s", filename.c_str()); - Audio::SeekableAudioStream *audioStream = Audio::makeVOCStream(f.readStream(f.size()), + Audio::SeekableAudioStream *audioStream = Audio::makeVOCStream(f.readStream(f.size()), Audio::FLAG_UNSIGNED, DisposeAfterUse::YES); _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, audioStream); diff --git a/engines/voyeur/staticres.cpp b/engines/voyeur/staticres.cpp index 7016793ddc..372da508f1 100644 --- a/engines/voyeur/staticres.cpp +++ b/engines/voyeur/staticres.cpp @@ -43,7 +43,7 @@ const int RESOLVE_TABLE[] = { 0x7500 }; -const int LEVEL_H[] = { +const int LEVEL_H[] = { 4, 7, 7, 8, 9, 10, 2, 2, 4, 8, 8, 9, 9, 10, 10, 11, 11 }; @@ -58,40 +58,40 @@ const int BLIND_TABLE[] = { }; const int COMPUTER_SCREEN_TABLE[] = { - 269, 128, 307, 163, - 269, 128, 307, 163, - 68, 79, 98, 102, - 68, 79, 98, 102, - 68, 79, 98, 102, + 269, 128, 307, 163, + 269, 128, 307, 163, + 68, 79, 98, 102, + 68, 79, 98, 102, + 68, 79, 98, 102, + 68, 79, 98, 102, + 248, 138, 291, 163, + 83, 132, 143, 156, + 248, 138, 291, 163, + 83, 132, 143, 156, + 83, 132, 143, 156, + 248, 138, 291, 163, 68, 79, 98, 102, - 248, 138, 291, 163, - 83, 132, 143, 156, - 248, 138, 291, 163, - 83, 132, 143, 156, - 83, 132, 143, 156, - 248, 138, 291, 163, - 68, 79, 98, 102, 68, 79, 98, 102 }; const char *const SZ_FILENAMES[] = { - "A2110100", nullptr, "A2300100", nullptr, "B1220100", nullptr, "C1220100", nullptr, - "C1290100", nullptr, "D1220100", nullptr, "D1270100", nullptr, "E1210100", nullptr, + "A2110100", nullptr, "A2300100", nullptr, "B1220100", nullptr, "C1220100", nullptr, + "C1290100", nullptr, "D1220100", nullptr, "D1270100", nullptr, "E1210100", nullptr, "E1260100", nullptr, "E1280100", nullptr, "E1325100", nullptr, "F1200100", nullptr, - "G1250100", nullptr, "G1260100", nullptr, "H1200100", nullptr, "H1230100", nullptr, - "H1310100", nullptr, "I1300100", nullptr, "J1220100", nullptr, "J1230100", nullptr, + "G1250100", nullptr, "G1260100", nullptr, "H1200100", nullptr, "H1230100", nullptr, + "H1310100", nullptr, "I1300100", nullptr, "J1220100", nullptr, "J1230100", nullptr, "J1320100", nullptr, "K1260100", nullptr, "K1280100", nullptr, "K1325100", nullptr, - "L1210100", nullptr, "L1280100", nullptr, "L1290100", nullptr, "L1300100", nullptr, - "L1310100", nullptr, "M1260100", nullptr, "M1310100", nullptr, "N1210100", nullptr, + "L1210100", nullptr, "L1280100", nullptr, "L1290100", nullptr, "L1300100", nullptr, + "L1310100", nullptr, "M1260100", nullptr, "M1310100", nullptr, "N1210100", nullptr, "N1225100", nullptr, "N1275510", nullptr, "N1280510", nullptr, "N1325100", nullptr, - "O1230100", nullptr, "O1260100", nullptr, "O1260520", nullptr, "O1280100", nullptr, - "O1325540", nullptr, "P1276710", nullptr, "P1280540", nullptr, "P1280740", nullptr, + "O1230100", nullptr, "O1260100", nullptr, "O1260520", nullptr, "O1280100", nullptr, + "O1325540", nullptr, "P1276710", nullptr, "P1280540", nullptr, "P1280740", nullptr, "P1290510", nullptr, "P1325100", nullptr, "P1325300", nullptr, "P1325520", nullptr, - "Q1230100", nullptr, "Q1240530", nullptr, "Q1240730", nullptr, "Q1260100", nullptr, - "Q1260520", nullptr, "Q1260720", nullptr, "Q1325100", nullptr, "R1280540", nullptr, + "Q1230100", nullptr, "Q1240530", nullptr, "Q1240730", nullptr, "Q1260100", nullptr, + "Q1260520", nullptr, "Q1260720", nullptr, "Q1325100", nullptr, "R1280540", nullptr, "Z1110510", nullptr, "Z1110520", nullptr, "Z1110530", nullptr, "Z1110540", nullptr, - "Z1110545", nullptr, "Z2320100", nullptr, "Z2905300", nullptr, "Z3110100", nullptr, - "Z3115510", nullptr, "Z3115520", nullptr, "Z3115530", nullptr, "Z3115540", nullptr, + "Z1110545", nullptr, "Z2320100", nullptr, "Z2905300", nullptr, "Z3110100", nullptr, + "Z3115510", nullptr, "Z3115520", nullptr, "Z3115530", nullptr, "Z3115540", nullptr, "Z4915100", nullptr, "Z4915200", nullptr, "Z4915300", nullptr, nullptr, nullptr, nullptr, nullptr, "MMARG", "MZACK", "MREED", "MJESSI", "MCHLOE", "MCAMERA", "MENDCRED", diff --git a/engines/voyeur/voyeur.cpp b/engines/voyeur/voyeur.cpp index 9843930bd3..8edacc5883 100644 --- a/engines/voyeur/voyeur.cpp +++ b/engines/voyeur/voyeur.cpp @@ -37,7 +37,7 @@ VoyeurEngine *g_vm; VoyeurEngine::VoyeurEngine(OSystem *syst, const VoyeurGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc), _randomSource("Voyeur"), - _defaultFontInfo(3, 0xff, 0xff, 0, 0, ALIGN_LEFT, 0, Common::Point(), 1, 1, + _defaultFontInfo(3, 0xff, 0xff, 0, 0, ALIGN_LEFT, 0, Common::Point(), 1, 1, Common::Point(1, 1), 1, 0, 0) { _debugger = nullptr; _eventsManager = nullptr; @@ -158,7 +158,7 @@ void VoyeurEngine::initInput() { bool VoyeurEngine::doHeadTitle() { // char dest[144]; - + _eventsManager->startMainClockInt(); if (_loadGameSlot == -1) { @@ -205,7 +205,7 @@ bool VoyeurEngine::doHeadTitle() { _voy->addEvent(18, 7, EVTYPE_VIDEO, 40, 0, 998, -1); _voy->addEvent(18, 8, EVTYPE_VIDEO, 43, 0, 998, -1); _voy->addEvent(19, 1, EVTYPE_AUDIO, 20, 0, 998, -1); - } + } } _voy->_aptLoadMode = 140; @@ -271,7 +271,7 @@ bool VoyeurEngine::doLock() { _graphicsManager->setColor(2, 96, 96, 96); _graphicsManager->setColor(3, 160, 160, 160); _graphicsManager->setColor(4, 224, 224, 224); - + // Set up the cursor _eventsManager->setCursor(cursorPic); _eventsManager->showCursor(); @@ -464,11 +464,11 @@ void VoyeurEngine::doOpening() { _eventsManager->_intPtr._hasPalette = true; _graphicsManager->_vPort->setupViewPort(); flipPageAndWait(); - + RL2Decoder decoder; decoder.loadRL2File("a2300100.rl2", false); decoder.start(); - + while (!shouldQuit() && !decoder.endOfVideo() && !_eventsManager->_mouseClicked) { if (decoder.hasDirtyPalette()) { const byte *palette = decoder.getPalette(); @@ -487,7 +487,7 @@ void VoyeurEngine::doOpening() { textPic = _bVoy->boltEntry(frameIndex / 2 + 0x202)._picResource; textPos = Common::Point(READ_LE_UINT16(xyTable + frameIndex * 2), READ_LE_UINT16(xyTable + (frameIndex + 1) * 2)); - + creditShow = false; } else { textPic = nullptr; @@ -500,8 +500,9 @@ void VoyeurEngine::doOpening() { if (textPic) { _graphicsManager->sDrawPic(textPic, _graphicsManager->_vPort, textPos); - flipPageAndWait(); } + + flipPageAndWait(); } _eventsManager->getMouseInfo(); @@ -560,9 +561,9 @@ void VoyeurEngine::playAVideoDuration(int videoId, int duration) { RL2Decoder decoder; decoder.loadVideo(videoId); - decoder.seek(Audio::Timestamp(_voy->_vocSecondsOffset * 1000)); + decoder.seek(Audio::Timestamp(_voy->_vocSecondsOffset * 1000)); decoder.start(); - int endFrame = decoder.getCurFrame() + totalFrames; + int endFrame = decoder.getCurFrame() + totalFrames; _eventsManager->getMouseInfo(); _eventsManager->startCursorBlink(); @@ -603,9 +604,9 @@ void VoyeurEngine::playAVideoDuration(int videoId, int duration) { void VoyeurEngine::playAudio(int audioId) { _bVoy->getBoltGroup(0x7F00); - _graphicsManager->_backgroundPage = _bVoy->boltEntry(0x7F00 + + _graphicsManager->_backgroundPage = _bVoy->boltEntry(0x7F00 + BLIND_TABLE[audioId] * 2)._picResource; - _graphicsManager->_backColors = _bVoy->boltEntry(0x7F01 + + _graphicsManager->_backColors = _bVoy->boltEntry(0x7F01 + BLIND_TABLE[audioId] * 2)._cMapResource; _graphicsManager->_vPort->setupViewPort(); @@ -620,7 +621,7 @@ void VoyeurEngine::playAudio(int audioId) { _voy->_eventFlags |= EVTFLAG_RECORDING; _eventsManager->startCursorBlink(); - while (!shouldQuit() && !_eventsManager->_mouseClicked && + while (!shouldQuit() && !_eventsManager->_mouseClicked && _soundManager->getVOCStatus()) _eventsManager->delayClick(1); @@ -657,7 +658,7 @@ void VoyeurEngine::doTransitionCard(const Common::String &time, const Common::St fi._justifyHeight = 120; _graphicsManager->_vPort->drawText(time); - + if (!location.empty()) { fi._pos = Common::Point(0, 138); fi._justify = ALIGN_CENTER; @@ -723,7 +724,7 @@ void VoyeurEngine::showEndingNews() { _soundManager->startVOCPlay(fname); _eventsManager->getMouseInfo(); - while (!shouldQuit() && !_eventsManager->_mouseClicked && + while (!shouldQuit() && !_eventsManager->_mouseClicked && _soundManager->getVOCStatus()) { _eventsManager->delay(1); _eventsManager->getMouseInfo(); @@ -901,7 +902,7 @@ void VoyeurSavegameHeader::write(Common::OutSaveFile *f, VoyeurEngine *vm, const // Create a thumbnail and save it Graphics::Surface *thumb = new Graphics::Surface(); - ::createThumbnail(thumb, (byte *)vm->_graphicsManager->_screenSurface.getPixels(), + ::createThumbnail(thumb, (byte *)vm->_graphicsManager->_screenSurface.getPixels(), SCREEN_WIDTH, SCREEN_HEIGHT, vm->_graphicsManager->_VGAColors); Graphics::saveThumbnail(*f, *thumb); thumb->free(); diff --git a/engines/voyeur/voyeur_game.cpp b/engines/voyeur/voyeur_game.cpp index a6564c32ba..34ad62a88d 100644 --- a/engines/voyeur/voyeur_game.cpp +++ b/engines/voyeur/voyeur_game.cpp @@ -33,7 +33,7 @@ void VoyeurEngine::playStamp() { _stampLibPtr->getBoltGroup(0); _controlPtr->_state = _stampLibPtr->boltEntry(_controlPtr->_stateId >> 16)._stateResource; assert(_controlPtr->_state); - + _resolvePtr = &RESOLVE_TABLE[0]; initStamp(); @@ -57,11 +57,11 @@ void VoyeurEngine::playStamp() { _mainThread->parsePlayCommands(); bool flag = breakFlag = (_voy->_eventFlags & EVTFLAG_2) != 0; - + switch (_voy->_playStampMode) { case 5: buttonId = _mainThread->doInterface(); - + if (buttonId == -2) { switch (_mainThread->doApt()) { case 0: @@ -110,7 +110,7 @@ void VoyeurEngine::playStamp() { case 16: _voy->_transitionId = 17; buttonId = _mainThread->doApt(); - + switch (buttonId) { case 1: _mainThread->chooseSTAMPButton(22); @@ -234,19 +234,19 @@ void VoyeurEngine::closeStamp() { void VoyeurEngine::doTailTitle() { _graphicsManager->_vPort->setupViewPort(NULL); _graphicsManager->screenReset(); - + if (_bVoy->getBoltGroup(0x600)) { RL2Decoder decoder; decoder.loadRL2File("a1100200.rl2", false); decoder.start(); decoder.play(this); - + if (!shouldQuit() && !_eventsManager->_mouseClicked) { doClosingCredits(); if (!shouldQuit() && !_eventsManager->_mouseClicked) { _graphicsManager->screenReset(); - + PictureResource *pic = _bVoy->boltEntry(0x602)._picResource; CMapResource *pal = _bVoy->boltEntry(0x603)._cMapResource; @@ -315,7 +315,7 @@ void VoyeurEngine::doClosingCredits() { _graphicsManager->_vPort->drawText(msg); msg += strlen(msg) + 1; } - + if (flags & 0x40) { fi._foreColor = 2; fi._curFont = _bVoy->boltEntry(0x400)._fontResource; @@ -345,7 +345,7 @@ void VoyeurEngine::doClosingCredits() { fi._justifyHeight = 240; fi._pos = Common::Point(198, READ_LE_UINT16(entry)); - _graphicsManager->_vPort->drawText(msg); + _graphicsManager->_vPort->drawText(msg); msg += strlen(msg) + 1; } @@ -500,7 +500,7 @@ void VoyeurEngine::reviewTape() { Common::String msg = _eventsManager->getEvidString(eventNum); _graphicsManager->_backgroundPage->drawText(msg); - + yp += 15; } @@ -527,7 +527,7 @@ void VoyeurEngine::reviewTape() { break; } } - + pt = _eventsManager->getMousePos(); if (tempPos.x >= 68 && tempPos.x <= 277 && tempPos.y >= 31 && tempPos.y <= 154) { tempPos.y -= 2; @@ -545,7 +545,7 @@ void VoyeurEngine::reviewTape() { flipPageAndWait(); _graphicsManager->_drawPtr->_penColor = 0; - _graphicsManager->_drawPtr->_pos = Common::Point(tempRect.left, tempRect.top); + _graphicsManager->_drawPtr->_pos = Common::Point(tempRect.left, tempRect.top); _graphicsManager->_backgroundPage->sFillBox(tempRect.width(), tempRect.height()); int yp = 45; @@ -642,7 +642,7 @@ void VoyeurEngine::reviewTape() { foundIndex = -1; _eventsManager->_rightClick = 0; } - + if (_eventsManager->_rightClick) foundIndex = 0; @@ -652,7 +652,7 @@ void VoyeurEngine::reviewTape() { _voy->_fadingType = 0; _voy->_viewBounds = nullptr; _graphicsManager->_vPort->setupViewPort(NULL); - + if (_currentVocId != -1) { _voy->_vocSecondsOffset = _voy->_RTVNum - _voy->_musicStartTime; _soundManager->stopVOCPlay(); @@ -693,7 +693,7 @@ void VoyeurEngine::reviewTape() { uint32 secondsDuration = e._computerOff; _eventsManager->getMouseInfo(); - while (!_eventsManager->_mouseClicked && _soundManager->getVOCStatus() && + while (!_eventsManager->_mouseClicked && _soundManager->getVOCStatus() && _soundManager->getVOCFrame() < secondsDuration) { _eventsManager->getMouseInfo(); _eventsManager->delay(10); @@ -707,7 +707,7 @@ void VoyeurEngine::reviewTape() { case EVTYPE_EVID: _voy->reviewAnEvidEvent(eventIndex); - + _voy->_vocSecondsOffset = _voy->_RTVNum - _voy->_musicStartTime; _soundManager->stopVOCPlay(); _bVoy->getBoltGroup(0x900); @@ -715,7 +715,7 @@ void VoyeurEngine::reviewTape() { case EVTYPE_COMPUTER: _voy->reviewComputerEvent(eventIndex); - + _voy->_vocSecondsOffset = _voy->_RTVNum - _voy->_musicStartTime; _soundManager->stopVOCPlay(); _bVoy->getBoltGroup(0x900); @@ -863,7 +863,7 @@ bool VoyeurEngine::checkForIncriminate() { for (int idx = 0; idx < _voy->_eventCount; ++idx) { VoyeurEvent &evt = _voy->_events[idx]; - + if (evt._type == EVTYPE_VIDEO) { if (evt._audioVideoId == 44 && evt._computerOn <= 40 && (evt._computerOff + evt._computerOn) >= 70) { @@ -908,7 +908,7 @@ void VoyeurEngine::playAVideoEvent(int eventIndex) { _voy->_vocSecondsOffset = evt._computerOn; _eventsManager->_videoDead = evt._dead; _voy->_eventFlags &= ~EVTFLAG_TIME_DISABLED; - + playAVideoDuration(_audioVideoId, evt._computerOff); _voy->_eventFlags |= EVTFLAG_TIME_DISABLED; @@ -929,7 +929,7 @@ void VoyeurEngine::playAVideoEvent(int eventIndex) { int VoyeurEngine::getChooseButton() { int prevIndex = -2; - Common::Array<RectEntry> &hotspots = _bVoy->boltEntry(_playStampGroupId + Common::Array<RectEntry> &hotspots = _bVoy->boltEntry(_playStampGroupId + 6)._rectResource->_entries; int selectedIndex = -1; @@ -949,7 +949,7 @@ int VoyeurEngine::getChooseButton() { _eventsManager->getMouseInfo(); selectedIndex = -1; Common::Point pt = _eventsManager->getMousePos(); - + for (uint idx = 0; idx < hotspots.size(); ++idx) { if (hotspots[idx].contains(pt)) { if (!_voy->_victimMurdered || ((int)idx + 1) != _controlPtr->_state->_victimIndex) { @@ -984,7 +984,7 @@ int VoyeurEngine::getChooseButton() { void VoyeurEngine::makeViewFinder() { _graphicsManager->_backgroundPage = _bVoy->boltEntry(0x103)._picResource; - _graphicsManager->sDrawPic(_graphicsManager->_backgroundPage, + _graphicsManager->sDrawPic(_graphicsManager->_backgroundPage, _graphicsManager->_vPort, Common::Point(0, 0)); CMapResource *pal = _bVoy->boltEntry(0x104)._cMapResource; @@ -1067,7 +1067,7 @@ void VoyeurEngine::initIFace() { _mansionViewPos = Common::Point((MANSION_MAX_X - MANSION_VIEW_WIDTH) / 2, (MANSION_MAX_Y - MANSION_VIEW_HEIGHT) / 2); doScroll(_mansionViewPos); - + _voy->_viewBounds = _bVoy->boltEntry(_playStampGroupId)._rectResource; // Show the cursor using ScummVM functionality @@ -1150,7 +1150,7 @@ Common::String VoyeurEngine::getDayName() { case 3: case 4: return SATURDAY; - case 17: + case 17: return MONDAY; default: return SUNDAY; @@ -1277,7 +1277,7 @@ void VoyeurEngine::doTimeBar() { if (_voy->_RTVLimit > 0) { if (_voy->_RTVNum > _voy->_RTVLimit || _voy->_RTVNum < 0) _voy->_RTVNum = _voy->_RTVLimit - 1; - + _timeBarVal = _voy->_RTVNum; int height = ((_voy->_RTVLimit - _voy->_RTVNum) * 59) / _voy->_RTVLimit; int fullHeight = MAX(151 - height, 93); @@ -1308,14 +1308,14 @@ void VoyeurEngine::flashTimeBar() { _graphicsManager->setColor(240, 220, 20, 20); else _graphicsManager->setColor(240, 220, 220, 220); - + _eventsManager->_intPtr._hasPalette = true; _flashTimeFlag = !_flashTimeFlag; } } void VoyeurEngine::checkPhoneCall() { - if ((_voy->_RTVLimit - _voy->_RTVNum) >= 36 && _voy->_totalPhoneCalls < 5 && + if ((_voy->_RTVLimit - _voy->_RTVNum) >= 36 && _voy->_totalPhoneCalls < 5 && _currentVocId <= 151 && _currentVocId > 146) { if ((_voy->_switchBGNum < _checkPhoneVal || _checkPhoneVal > 180) && !_soundManager->getVOCStatus()) { @@ -1361,9 +1361,9 @@ void VoyeurEngine::doEvidDisplay(int evidId, int eventId) { if (count > 0) { for (int idx = 1; idx <= count; ++idx) { - _voy->_evPicPtrs[idx - 1] = _bVoy->boltEntry(_voy->_boltGroupId2 + + _voy->_evPicPtrs[idx - 1] = _bVoy->boltEntry(_voy->_boltGroupId2 + (evidId + idx) * 2)._picResource; - _voy->_evCmPtrs[idx - 1] = _bVoy->boltEntry(_voy->_boltGroupId2 + + _voy->_evCmPtrs[idx - 1] = _bVoy->boltEntry(_voy->_boltGroupId2 + (evidId + idx) * 2 + 1)._cMapResource; } } @@ -1394,7 +1394,7 @@ void VoyeurEngine::doEvidDisplay(int evidId, int eventId) { break; if (count == 0 || evidIdx >= eventId) continue; - + pic = _voy->_evPicPtrs[arrIndex]; _graphicsManager->sDrawPic(pic, _graphicsManager->_vPort, Common::Point((384 - pic->_bounds.width()) / 2, diff --git a/engines/wintermute/debugger.cpp b/engines/wintermute/debugger.cpp index 51fd74e300..a313314a8b 100644 --- a/engines/wintermute/debugger.cpp +++ b/engines/wintermute/debugger.cpp @@ -29,8 +29,8 @@ namespace Wintermute { Console::Console(WintermuteEngine *vm) : GUI::Debugger(), _engineRef(vm) { - DCmd_Register("show_fps", WRAP_METHOD(Console, Cmd_ShowFps)); - DCmd_Register("dump_file", WRAP_METHOD(Console, Cmd_DumpFile)); + registerCmd("show_fps", WRAP_METHOD(Console, Cmd_ShowFps)); + registerCmd("dump_file", WRAP_METHOD(Console, Cmd_DumpFile)); } Console::~Console(void) { @@ -50,7 +50,7 @@ bool Console::Cmd_ShowFps(int argc, const char **argv) { bool Console::Cmd_DumpFile(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Usage: %s <file path> <output file name>\n", argv[0]); + debugPrintf("Usage: %s <file path> <output file name>\n", argv[0]); return true; } @@ -60,7 +60,7 @@ bool Console::Cmd_DumpFile(int argc, const char **argv) { BaseFileManager *fileManager = BaseEngine::instance().getFileManager(); Common::SeekableReadStream *inFile = fileManager->openFile(filePath); if (!inFile) { - DebugPrintf("File '%s' not found\n", argv[1]); + debugPrintf("File '%s' not found\n", argv[1]); return true; } @@ -77,7 +77,7 @@ bool Console::Cmd_DumpFile(int argc, const char **argv) { delete outFile; delete inFile; - DebugPrintf("Resource file '%s' dumped to file '%s'\n", argv[1], argv[2]); + debugPrintf("Resource file '%s' dumped to file '%s'\n", argv[1], argv[2]); return true; } diff --git a/engines/zvision/core/console.cpp b/engines/zvision/core/console.cpp index 22382bc264..e610f34474 100644 --- a/engines/zvision/core/console.cpp +++ b/engines/zvision/core/console.cpp @@ -45,25 +45,25 @@ namespace ZVision { Console::Console(ZVision *engine) : GUI::Debugger(), _engine(engine) { - DCmd_Register("loadimage", WRAP_METHOD(Console, cmdLoadImage)); - DCmd_Register("loadvideo", WRAP_METHOD(Console, cmdLoadVideo)); - DCmd_Register("loadsound", WRAP_METHOD(Console, cmdLoadSound)); - DCmd_Register("raw2wav", WRAP_METHOD(Console, cmdRawToWav)); - DCmd_Register("setrenderstate", WRAP_METHOD(Console, cmdSetRenderState)); - DCmd_Register("generaterendertable", WRAP_METHOD(Console, cmdGenerateRenderTable)); - DCmd_Register("setpanoramafov", WRAP_METHOD(Console, cmdSetPanoramaFoV)); - DCmd_Register("setpanoramascale", WRAP_METHOD(Console, cmdSetPanoramaScale)); - DCmd_Register("changelocation", WRAP_METHOD(Console, cmdChangeLocation)); - DCmd_Register("dumpfile", WRAP_METHOD(Console, cmdDumpFile)); - DCmd_Register("parseallscrfiles", WRAP_METHOD(Console, cmdParseAllScrFiles)); - DCmd_Register("rendertext", WRAP_METHOD(Console, cmdRenderText)); + registerCmd("loadimage", WRAP_METHOD(Console, cmdLoadImage)); + registerCmd("loadvideo", WRAP_METHOD(Console, cmdLoadVideo)); + registerCmd("loadsound", WRAP_METHOD(Console, cmdLoadSound)); + registerCmd("raw2wav", WRAP_METHOD(Console, cmdRawToWav)); + registerCmd("setrenderstate", WRAP_METHOD(Console, cmdSetRenderState)); + registerCmd("generaterendertable", WRAP_METHOD(Console, cmdGenerateRenderTable)); + registerCmd("setpanoramafov", WRAP_METHOD(Console, cmdSetPanoramaFoV)); + registerCmd("setpanoramascale", WRAP_METHOD(Console, cmdSetPanoramaScale)); + registerCmd("changelocation", WRAP_METHOD(Console, cmdChangeLocation)); + registerCmd("dumpfile", WRAP_METHOD(Console, cmdDumpFile)); + registerCmd("parseallscrfiles", WRAP_METHOD(Console, cmdParseAllScrFiles)); + registerCmd("rendertext", WRAP_METHOD(Console, cmdRenderText)); } bool Console::cmdLoadImage(int argc, const char **argv) { if (argc == 4) _engine->getRenderManager()->renderImageToScreen(argv[1], atoi(argv[2]), atoi(argv[3])); else { - DebugPrintf("Use loadimage <fileName> <destinationX> <destinationY> to load an image to the screen\n"); + debugPrintf("Use loadimage <fileName> <destinationX> <destinationY> to load an image to the screen\n"); return true; } @@ -72,7 +72,7 @@ bool Console::cmdLoadImage(int argc, const char **argv) { bool Console::cmdLoadVideo(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Use loadvideo <fileName> to load a video to the screen\n"); + debugPrintf("Use loadvideo <fileName> to load a video to the screen\n"); return true; } @@ -86,7 +86,7 @@ bool Console::cmdLoadVideo(int argc, const char **argv) { bool Console::cmdLoadSound(int argc, const char **argv) { if (!Common::File::exists(argv[1])) { - DebugPrintf("File does not exist\n"); + debugPrintf("File does not exist\n"); return true; } @@ -105,7 +105,7 @@ bool Console::cmdLoadSound(int argc, const char **argv) { Audio::SoundHandle handle; _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &handle, soundStream, -1, 100, 0, DisposeAfterUse::YES, false, false); } else { - DebugPrintf("Use loadsound <fileName> [<rate> <isStereo: 1 or 0>] to load a sound\n"); + debugPrintf("Use loadsound <fileName> [<rate> <isStereo: 1 or 0>] to load a sound\n"); return true; } @@ -114,7 +114,7 @@ bool Console::cmdLoadSound(int argc, const char **argv) { bool Console::cmdRawToWav(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Use raw2wav <rawFilePath> <wavFileName> to dump a .RAW file to .WAV\n"); + debugPrintf("Use raw2wav <rawFilePath> <wavFileName> to dump a .RAW file to .WAV\n"); return true; } @@ -124,7 +124,7 @@ bool Console::cmdRawToWav(int argc, const char **argv) { bool Console::cmdSetRenderState(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Use setrenderstate <RenderState: panorama, tilt, flat> to change the current render state\n"); + debugPrintf("Use setrenderstate <RenderState: panorama, tilt, flat> to change the current render state\n"); return true; } @@ -137,7 +137,7 @@ bool Console::cmdSetRenderState(int argc, const char **argv) { else if (renderState.matchString("flat", true)) _engine->getRenderManager()->getRenderTable()->setRenderState(RenderTable::FLAT); else - DebugPrintf("Use setrenderstate <RenderState: panorama, tilt, flat> to change the current render state\n"); + debugPrintf("Use setrenderstate <RenderState: panorama, tilt, flat> to change the current render state\n"); return true; } @@ -150,7 +150,7 @@ bool Console::cmdGenerateRenderTable(int argc, const char **argv) { bool Console::cmdSetPanoramaFoV(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Use setpanoramafov <fieldOfView> to change the current panorama field of view\n"); + debugPrintf("Use setpanoramafov <fieldOfView> to change the current panorama field of view\n"); return true; } @@ -161,7 +161,7 @@ bool Console::cmdSetPanoramaFoV(int argc, const char **argv) { bool Console::cmdSetPanoramaScale(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Use setpanoramascale <scale> to change the current panorama scale\n"); + debugPrintf("Use setpanoramascale <scale> to change the current panorama scale\n"); return true; } @@ -172,7 +172,7 @@ bool Console::cmdSetPanoramaScale(int argc, const char **argv) { bool Console::cmdChangeLocation(int argc, const char **argv) { if (argc != 6) { - DebugPrintf("Use changelocation <char: world> <char: room> <char:node> <char:view> <int: x position> to change your location\n"); + debugPrintf("Use changelocation <char: world> <char: room> <char:node> <char:view> <int: x position> to change your location\n"); return true; } @@ -183,7 +183,7 @@ bool Console::cmdChangeLocation(int argc, const char **argv) { bool Console::cmdDumpFile(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Use dumpfile <fileName> to dump a file\n"); + debugPrintf("Use dumpfile <fileName> to dump a file\n"); return true; } @@ -205,7 +205,7 @@ bool Console::cmdParseAllScrFiles(int argc, const char **argv) { bool Console::cmdRenderText(int argc, const char **argv) { if (argc != 7) { - DebugPrintf("Use rendertext <text> <fontNumber> <destX> <destY> <maxWidth> <1 or 0: wrap> to render text\n"); + debugPrintf("Use rendertext <text> <fontNumber> <destX> <destY> <maxWidth> <1 or 0: wrap> to render text\n"); return true; } diff --git a/engines/zvision/sound/zork_raw.cpp b/engines/zvision/sound/zork_raw.cpp index 55353acbb9..edee1fd16e 100644 --- a/engines/zvision/sound/zork_raw.cpp +++ b/engines/zvision/sound/zork_raw.cpp @@ -185,14 +185,14 @@ Audio::RewindableAudioStream *makeRawZorkStream(const Common::String &filePath, char fileIdentifier = (engine->getGameId() == GID_NEMESIS) ? fileName[6] : fileName[7]; if (engine->getGameId() == GID_NEMESIS) { - for (int i = 0; i < 6; ++i) { + for (uint i = 0; i < ARRAYSIZE(RawZorkStream::_zNemSoundParamLookupTable); ++i) { if (RawZorkStream::_zNemSoundParamLookupTable[i].identifier == fileIdentifier) { soundParams = RawZorkStream::_zNemSoundParamLookupTable[i]; foundParams = true; } } } else if (engine->getGameId() == GID_GRANDINQUISITOR) { - for (int i = 0; i < 6; ++i) { + for (uint i = 0; i < ARRAYSIZE(RawZorkStream::_zgiSoundParamLookupTable); ++i) { if (RawZorkStream::_zgiSoundParamLookupTable[i].identifier == fileIdentifier) { soundParams = RawZorkStream::_zgiSoundParamLookupTable[i]; foundParams = true; diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index a3ec66a29d..a9594f7dd2 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -701,7 +701,7 @@ darkenFill(PixelType *ptr, PixelType *end) { PixelType addA = (PixelType)(3 << (_format.aShift + 6 - _format.aLoss)); while (ptr != end) { - // Darken the colour, and increase the alpha + // Darken the color, and increase the alpha // (0% -> 75%, 100% -> 100%) *ptr = (PixelType)(((*ptr & ~mask) >> 2) + addA); ++ptr; diff --git a/gui/credits.h b/gui/credits.h index bcace12d13..d5c12515d3 100644 --- a/gui/credits.h +++ b/gui/credits.h @@ -168,6 +168,12 @@ static const char *credits[] = { "C0""Benjamin Haisch", "C0""Filippos Karapetis", "", +"C1""MADS", +"A0""Arnaud Boutonne", +"C0""Arnaud Boutonn\351", +"C0""Paul Gilbert", +"C0""Filippos Karapetis", +"", "C1""Mohawk", "C0""Bastien Bouclet", "C0""Matthew Hoops", @@ -299,6 +305,11 @@ static const char *credits[] = { "C0""Gregory Montoir", "C2""(retired)", "", +"C1""Voyeur", +"A0""Arnaud Boutonne", +"C0""Arnaud Boutonn\351", +"C0""Paul Gilbert", +"", "C1""Wintermute", "A0""Einar Johan T. Somaaen", "C0""Einar Johan T. S\370m\345en", diff --git a/gui/debugger.cpp b/gui/debugger.cpp index 2ec9937fdb..4d97338b9c 100644 --- a/gui/debugger.cpp +++ b/gui/debugger.cpp @@ -23,6 +23,7 @@ // NB: This is really only necessary if USE_READLINE is defined #define FORBIDDEN_SYMBOL_ALLOW_ALL +#include "common/debug.h" #include "common/debug-channels.h" #include "common/system.h" @@ -51,19 +52,20 @@ Debugger::Debugger() { #endif // Register variables - DVar_Register("debug_countdown", &_frameCountdown, DVAR_INT, 0); + registerVar("debug_countdown", &_frameCountdown, DVAR_INT, 0); // Register commands - //DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("exit", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("quit", WRAP_METHOD(Debugger, Cmd_Exit)); + //registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("exit", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("quit", WRAP_METHOD(Debugger, cmdExit)); - DCmd_Register("help", WRAP_METHOD(Debugger, Cmd_Help)); - DCmd_Register("openlog", WRAP_METHOD(Debugger, Cmd_OpenLog)); + registerCmd("help", WRAP_METHOD(Debugger, cmdHelp)); + registerCmd("openlog", WRAP_METHOD(Debugger, cmdOpenLog)); - DCmd_Register("debugflag_list", WRAP_METHOD(Debugger, Cmd_DebugFlagsList)); - DCmd_Register("debugflag_enable", WRAP_METHOD(Debugger, Cmd_DebugFlagEnable)); - DCmd_Register("debugflag_disable", WRAP_METHOD(Debugger, Cmd_DebugFlagDisable)); + registerCmd("debuglevel", WRAP_METHOD(Debugger, cmdDebugLevel)); + registerCmd("debugflag_list", WRAP_METHOD(Debugger, cmdDebugFlagsList)); + registerCmd("debugflag_enable", WRAP_METHOD(Debugger, cmdDebugFlagEnable)); + registerCmd("debugflag_disable", WRAP_METHOD(Debugger, cmdDebugFlagDisable)); } Debugger::~Debugger() { @@ -74,7 +76,7 @@ Debugger::~Debugger() { // Initialisation Functions -int Debugger::DebugPrintf(const char *format, ...) { +int Debugger::debugPrintf(const char *format, ...) { va_list argptr; va_start(argptr, format); @@ -151,13 +153,13 @@ void Debugger::enter() { #ifndef USE_TEXT_CONSOLE_FOR_DEBUGGER if (_firstTime) { - DebugPrintf("Debugger started, type 'exit' to return to the game.\n"); - DebugPrintf("Type 'help' to see a little list of commands and variables.\n"); + debugPrintf("Debugger started, type 'exit' to return to the game.\n"); + debugPrintf("Type 'help' to see a little list of commands and variables.\n"); _firstTime = false; } if (_errStr) { - DebugPrintf("ERROR: %s\n\n", _errStr); + debugPrintf("ERROR: %s\n\n", _errStr); free(_errStr); _errStr = NULL; } @@ -240,82 +242,82 @@ bool Debugger::parseCommand(const char *inputOrig) { } // It's not a command, so things get a little tricky for variables. Do fuzzy matching to ignore things like subscripts. - for (uint i = 0; i < _dvars.size(); i++) { - if (!strncmp(_dvars[i].name.c_str(), param[0], _dvars[i].name.size())) { + for (uint i = 0; i < _vars.size(); i++) { + if (!strncmp(_vars[i].name.c_str(), param[0], _vars[i].name.size())) { if (num_params > 1) { // Alright, we need to check the TYPE of the variable to deref and stuff... the array stuff is a bit ugly :) - switch (_dvars[i].type) { + switch (_vars[i].type) { // Integer case DVAR_BYTE: - *(byte *)_dvars[i].variable = atoi(param[1]); - DebugPrintf("byte%s = %d\n", param[0], *(byte *)_dvars[i].variable); + *(byte *)_vars[i].variable = atoi(param[1]); + debugPrintf("byte%s = %d\n", param[0], *(byte *)_vars[i].variable); break; case DVAR_INT: - *(int32 *)_dvars[i].variable = atoi(param[1]); - DebugPrintf("(int)%s = %d\n", param[0], *(int32 *)_dvars[i].variable); + *(int32 *)_vars[i].variable = atoi(param[1]); + debugPrintf("(int)%s = %d\n", param[0], *(int32 *)_vars[i].variable); break; case DVAR_BOOL: - if (Common::parseBool(param[1], *(bool *)_dvars[i].variable)) - DebugPrintf("(bool)%s = %s\n", param[0], *(bool *)_dvars[i].variable ? "true" : "false"); + if (Common::parseBool(param[1], *(bool *)_vars[i].variable)) + debugPrintf("(bool)%s = %s\n", param[0], *(bool *)_vars[i].variable ? "true" : "false"); else - DebugPrintf("Invalid value for boolean variable. Valid values are \"true\", \"false\", \"1\", \"0\", \"yes\", \"no\"\n"); + debugPrintf("Invalid value for boolean variable. Valid values are \"true\", \"false\", \"1\", \"0\", \"yes\", \"no\"\n"); break; // Integer Array case DVAR_INTARRAY: { const char *chr = strchr(param[0], '['); if (!chr) { - DebugPrintf("You must access this array as %s[element]\n", param[0]); + debugPrintf("You must access this array as %s[element]\n", param[0]); } else { int element = atoi(chr+1); - int32 *var = *(int32 **)_dvars[i].variable; - if (element >= _dvars[i].arraySize) { - DebugPrintf("%s is out of range (array is %d elements big)\n", param[0], _dvars[i].arraySize); + int32 *var = *(int32 **)_vars[i].variable; + if (element >= _vars[i].arraySize) { + debugPrintf("%s is out of range (array is %d elements big)\n", param[0], _vars[i].arraySize); } else { var[element] = atoi(param[1]); - DebugPrintf("(int)%s = %d\n", param[0], var[element]); + debugPrintf("(int)%s = %d\n", param[0], var[element]); } } } break; default: - DebugPrintf("Failed to set variable %s to %s - unknown type\n", _dvars[i].name.c_str(), param[1]); + debugPrintf("Failed to set variable %s to %s - unknown type\n", _vars[i].name.c_str(), param[1]); break; } } else { // And again, type-dependent prints/defrefs. The array one is still ugly. - switch (_dvars[i].type) { + switch (_vars[i].type) { // Integer case DVAR_BYTE: - DebugPrintf("(byte)%s = %d\n", param[0], *(const byte *)_dvars[i].variable); + debugPrintf("(byte)%s = %d\n", param[0], *(const byte *)_vars[i].variable); break; case DVAR_INT: - DebugPrintf("(int)%s = %d\n", param[0], *(const int32 *)_dvars[i].variable); + debugPrintf("(int)%s = %d\n", param[0], *(const int32 *)_vars[i].variable); break; case DVAR_BOOL: - DebugPrintf("(bool)%s = %s\n", param[0], *(const bool *)_dvars[i].variable ? "true" : "false"); + debugPrintf("(bool)%s = %s\n", param[0], *(const bool *)_vars[i].variable ? "true" : "false"); break; // Integer array case DVAR_INTARRAY: { const char *chr = strchr(param[0], '['); if (!chr) { - DebugPrintf("You must access this array as %s[element]\n", param[0]); + debugPrintf("You must access this array as %s[element]\n", param[0]); } else { int element = atoi(chr+1); - const int32 *var = *(const int32 **)_dvars[i].variable; - if (element >= _dvars[i].arraySize) { - DebugPrintf("%s is out of range (array is %d elements big)\n", param[0], _dvars[i].arraySize); + const int32 *var = *(const int32 **)_vars[i].variable; + if (element >= _vars[i].arraySize) { + debugPrintf("%s is out of range (array is %d elements big)\n", param[0], _vars[i].arraySize); } else { - DebugPrintf("(int)%s = %d\n", param[0], var[element]); + debugPrintf("(int)%s = %d\n", param[0], var[element]); } } } break; // String case DVAR_STRING: - DebugPrintf("(string)%s = %s\n", param[0], ((Common::String *)_dvars[i].variable)->c_str()); + debugPrintf("(string)%s = %s\n", param[0], ((Common::String *)_vars[i].variable)->c_str()); break; default: - DebugPrintf("%s = (unknown type)\n", param[0]); + debugPrintf("%s = (unknown type)\n", param[0]); break; } } @@ -325,7 +327,7 @@ bool Debugger::parseCommand(const char *inputOrig) { } } - DebugPrintf("Unknown command or variable\n"); + debugPrintf("Unknown command or variable\n"); free(input); return true; } @@ -404,36 +406,36 @@ char *Debugger::readlineComplete(const char *input, int state) { #endif // Variable registration function -void Debugger::DVar_Register(const Common::String &varname, void *pointer, VarType type, int arraySize) { +void Debugger::registerVar(const Common::String &varname, void *pointer, VarType type, int arraySize) { // TODO: Filter out duplicates // TODO: Sort this list? Then we can do binary search later on when doing lookups. assert(pointer); - DVar tmp; + Var tmp; tmp.name = varname; tmp.type = type; tmp.variable = pointer; tmp.arraySize = arraySize; - _dvars.push_back(tmp); + _vars.push_back(tmp); } // Command registration function -void Debugger::DCmd_Register(const Common::String &cmdname, Debuglet *debuglet) { +void Debugger::registerCmd(const Common::String &cmdname, Debuglet *debuglet) { assert(debuglet && debuglet->isValid()); _cmds[cmdname] = Common::SharedPtr<Debuglet>(debuglet); } // Detach ("exit") the debugger -bool Debugger::Cmd_Exit(int argc, const char **argv) { +bool Debugger::cmdExit(int argc, const char **argv) { detach(); return false; } // Print a list of all registered commands (and variables, if any), // nicely word-wrapped. -bool Debugger::Cmd_Help(int argc, const char **argv) { +bool Debugger::cmdHelp(int argc, const char **argv) { #ifndef USE_TEXT_CONSOLE_FOR_DEBUGGER const int charsPerLine = _debuggerDialog->getCharsPerLine(); #elif defined(USE_READLINE) @@ -446,7 +448,7 @@ bool Debugger::Cmd_Help(int argc, const char **argv) { int width, size; uint i; - DebugPrintf("Commands are:\n"); + debugPrintf("Commands are:\n"); // Obtain a list of sorted command names Common::Array<Common::String> cmds; @@ -462,84 +464,103 @@ bool Debugger::Cmd_Help(int argc, const char **argv) { size = cmds[i].size() + 1; if ((width + size) >= charsPerLine) { - DebugPrintf("\n"); + debugPrintf("\n"); width = size; } else width += size; - DebugPrintf("%s ", cmds[i].c_str()); + debugPrintf("%s ", cmds[i].c_str()); } - DebugPrintf("\n"); + debugPrintf("\n"); - if (!_dvars.empty()) { - DebugPrintf("\n"); - DebugPrintf("Variables are:\n"); + if (!_vars.empty()) { + debugPrintf("\n"); + debugPrintf("Variables are:\n"); width = 0; - for (i = 0; i < _dvars.size(); i++) { - size = _dvars[i].name.size() + 1; + for (i = 0; i < _vars.size(); i++) { + size = _vars[i].name.size() + 1; if ((width + size) >= charsPerLine) { - DebugPrintf("\n"); + debugPrintf("\n"); width = size; } else width += size; - DebugPrintf("%s ", _dvars[i].name.c_str()); + debugPrintf("%s ", _vars[i].name.c_str()); } - DebugPrintf("\n"); + debugPrintf("\n"); } return true; } -bool Debugger::Cmd_OpenLog(int argc, const char **argv) { +bool Debugger::cmdOpenLog(int argc, const char **argv) { if (g_system->hasFeature(OSystem::kFeatureDisplayLogFile)) g_system->displayLogFile(); else - DebugPrintf("Opening the log file not supported on this system\n"); + debugPrintf("Opening the log file not supported on this system\n"); return true; } -bool Debugger::Cmd_DebugFlagsList(int argc, const char **argv) { +bool Debugger::cmdDebugLevel(int argc, const char **argv) { + if (argc == 1) { // print level + debugPrintf("Debugging is currently %s (set at level %d)\n", (gDebugLevel >= 0) ? "enabled" : "disabled", gDebugLevel); + debugPrintf("Usage: %s <n> where n is 0 to 10 or -1 to disable debugging\n", argv[0]); + } else { // set level + gDebugLevel = atoi(argv[1]); + if (gDebugLevel >= 0 && gDebugLevel < 11) { + debugPrintf("Debug level set to level %d\n", gDebugLevel); + } else if (gDebugLevel < 0) { + debugPrintf("Debugging is now disabled\n"); + } else { + debugPrintf("Invalid debug level value\n"); + debugPrintf("Usage: %s <n> where n is 0 to 10 or -1 to disable debugging\n", argv[0]); + } + } + + return true; +} + +bool Debugger::cmdDebugFlagsList(int argc, const char **argv) { const Common::DebugManager::DebugChannelList &debugLevels = DebugMan.listDebugChannels(); - DebugPrintf("Engine debug levels:\n"); - DebugPrintf("--------------------\n"); + debugPrintf("Engine debug levels:\n"); + debugPrintf("--------------------\n"); if (debugLevels.empty()) { - DebugPrintf("No engine debug levels\n"); + debugPrintf("No engine debug levels\n"); return true; } for (Common::DebugManager::DebugChannelList::const_iterator i = debugLevels.begin(); i != debugLevels.end(); ++i) { - DebugPrintf("%c%s - %s (%s)\n", i->enabled ? '+' : ' ', + debugPrintf("%c%s - %s (%s)\n", i->enabled ? '+' : ' ', i->name.c_str(), i->description.c_str(), i->enabled ? "enabled" : "disabled"); } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } -bool Debugger::Cmd_DebugFlagEnable(int argc, const char **argv) { +bool Debugger::cmdDebugFlagEnable(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("debugflag_enable <flag>\n"); + debugPrintf("debugflag_enable <flag>\n"); } else { if (DebugMan.enableDebugChannel(argv[1])) { - DebugPrintf("Enabled debug flag '%s'\n", argv[1]); + debugPrintf("Enabled debug flag '%s'\n", argv[1]); } else { - DebugPrintf("Failed to enable debug flag '%s'\n", argv[1]); + debugPrintf("Failed to enable debug flag '%s'\n", argv[1]); } } return true; } -bool Debugger::Cmd_DebugFlagDisable(int argc, const char **argv) { +bool Debugger::cmdDebugFlagDisable(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("debugflag_disable <flag>\n"); + debugPrintf("debugflag_disable <flag>\n"); } else { if (DebugMan.disableDebugChannel(argv[1])) { - DebugPrintf("Disabled debug flag '%s'\n", argv[1]); + debugPrintf("Disabled debug flag '%s'\n", argv[1]); } else { - DebugPrintf("Failed to disable debug flag '%s'\n", argv[1]); + debugPrintf("Failed to disable debug flag '%s'\n", argv[1]); } } return true; diff --git a/gui/debugger.h b/gui/debugger.h index 4ce5481fbb..8c7481b61f 100644 --- a/gui/debugger.h +++ b/gui/debugger.h @@ -40,7 +40,7 @@ public: Debugger(); virtual ~Debugger(); - int DebugPrintf(const char *format, ...) GCC_PRINTF(2, 3); + int debugPrintf(const char *format, ...) GCC_PRINTF(2, 3); /** * The onFrame() method should be invoked by the engine at regular @@ -74,8 +74,8 @@ protected: * Convenience macro that makes it easier to register a method * of a debugger subclass as a command. * Usage example: - * DCmd_Register("COMMAND", WRAP_METHOD(MyDebugger, MyCmd)); - * would register the method MyDebugger::MyCmd(int, const char **) + * registerCmd("COMMAND", WRAP_METHOD(MyDebugger, myCmd)); + * would register the method MyDebugger::myCmd(int, const char **) * under the command name "COMMAND". */ #define WRAP_METHOD(cls, method) \ @@ -89,14 +89,14 @@ protected: DVAR_STRING }; - struct DVar { + struct Var { Common::String name; void *variable; VarType type; int arraySize; }; - +private: /** * Register a variable with the debugger. This allows the user to read and modify * this variable. @@ -104,11 +104,31 @@ protected: * @param variable pointer to the actual storage of the variable * @param type the type of the variable (byte, int, bool, ...) * @paral arraySize for type DVAR_INTARRAY this specifies the size of the array - * - * @todo replace this single method by type safe variants. */ - void DVar_Register(const Common::String &varname, void *variable, VarType type, int arraySize); - void DCmd_Register(const Common::String &cmdname, Debuglet *debuglet); + void registerVar(const Common::String &varname, void *variable, VarType type, int arraySize); + +protected: + void registerVar(const Common::String &varname, byte *variable) { + registerVar(varname, variable, DVAR_BYTE, 0); + } + + void registerVar(const Common::String &varname, int *variable) { + registerVar(varname, variable, DVAR_INT, 0); + } + + void registerVar(const Common::String &varname, bool *variable) { + registerVar(varname, variable, DVAR_BOOL, 0); + } + + void registerVar(const Common::String &varname, int32 **variable, int arraySize) { + registerVar(varname, variable, DVAR_INTARRAY, arraySize); + } + + void registerVar(const Common::String &varname, Common::String *variable) { + registerVar(varname, variable, DVAR_STRING, 0); + } + + void registerCmd(const Common::String &cmdname, Debuglet *debuglet); private: @@ -125,7 +145,7 @@ private: */ uint _frameCountdown; - Common::Array<DVar> _dvars; + Common::Array<Var> _vars; typedef Common::HashMap<Common::String, Common::SharedPtr<Debuglet>, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> CommandsMap; CommandsMap _cmds; @@ -168,7 +188,7 @@ protected: virtual void postEnter(); /** - * Subclasses should invoke the detach() method in their Cmd_FOO methods + * Subclasses should invoke the detach() method in their cmdFOO methods * if that command will resume execution of the program (as opposed to * executing, say, a "single step through code" command). * @@ -190,12 +210,13 @@ private: virtual bool handleCommand(int argc, const char **argv, bool &keepRunning); protected: - bool Cmd_Exit(int argc, const char **argv); - bool Cmd_Help(int argc, const char **argv); - bool Cmd_OpenLog(int argc, const char **argv); - bool Cmd_DebugFlagsList(int argc, const char **argv); - bool Cmd_DebugFlagEnable(int argc, const char **argv); - bool Cmd_DebugFlagDisable(int argc, const char **argv); + bool cmdExit(int argc, const char **argv); + bool cmdHelp(int argc, const char **argv); + bool cmdOpenLog(int argc, const char **argv); + bool cmdDebugLevel(int argc, const char **argv); + bool cmdDebugFlagsList(int argc, const char **argv); + bool cmdDebugFlagEnable(int argc, const char **argv); + bool cmdDebugFlagDisable(int argc, const char **argv); #ifndef USE_TEXT_CONSOLE_FOR_DEBUGGER private: diff --git a/image/codecs/codec.cpp b/image/codecs/codec.cpp index 530fb3b836..6b0c7ebcfb 100644 --- a/image/codecs/codec.cpp +++ b/image/codecs/codec.cpp @@ -58,10 +58,10 @@ Codec *createBitmapCodec(uint32 tag, int width, int height, int bitsPerPixel) { return new CinepakDecoder(bitsPerPixel); case MKTAG('I','V','3','2'): return new Indeo3Decoder(width, height); -#ifdef VIDEO_CODECS_TRUEMOTION1_H +#ifdef IMAGE_CODECS_TRUEMOTION1_H case MKTAG('D','U','C','K'): case MKTAG('d','u','c','k'): - return new TrueMotion1Decoder(width, height); + return new TrueMotion1Decoder(); #endif #ifdef USE_MPEG2 case MKTAG('m','p','g','2'): diff --git a/image/codecs/truemotion1.cpp b/image/codecs/truemotion1.cpp index 1302d72e2f..e60ec6c72e 100644 --- a/image/codecs/truemotion1.cpp +++ b/image/codecs/truemotion1.cpp @@ -30,6 +30,7 @@ #include "image/codecs/truemotion1data.h" #include "common/stream.h" #include "common/textconsole.h" +#include "common/rect.h" #include "common/util.h" namespace Image { @@ -88,24 +89,20 @@ static const CompressionType compressionTypes[17] = { { ALGO_RGB24H, 2, 2, BLOCK_2x2 } }; -TrueMotion1Decoder::TrueMotion1Decoder(uint16 width, uint16 height) { - _surface = new Graphics::Surface(); - _width = width; - _height = height; - - _surface->create(width, height, getPixelFormat()); - - // there is a vertical predictor for each pixel in a line; each vertical - // predictor is 0 to start with - _vertPred = new uint32[_width]; +TrueMotion1Decoder::TrueMotion1Decoder() { + _surface = 0; + _vertPred = 0; _buf = _mbChangeBits = _indexStream = 0; _lastDeltaset = _lastVectable = -1; } TrueMotion1Decoder::~TrueMotion1Decoder() { - _surface->free(); - delete _surface; + if (_surface) { + _surface->free(); + delete _surface; + } + delete[] _vertPred; } @@ -170,11 +167,6 @@ void TrueMotion1Decoder::decodeHeader(Common::SeekableReadStream &stream) { byte headerBuffer[128]; // logical maximum size of the header const byte *selVectorTable; - // There is 1 change bit per 4 pixels, so each change byte represents - // 32 pixels; divide width by 4 to obtain the number of change bits and - // then round up to the nearest byte. - _mbChangeBitsRowSize = ((_width >> 2) + 7) >> 3; - _header.headerSize = ((_buf[0] >> 5) | (_buf[0] << 3)) & 0x7f; if (_buf[0] < 0x10) @@ -196,6 +188,22 @@ void TrueMotion1Decoder::decodeHeader(Common::SeekableReadStream &stream) { _header.flags = headerBuffer[11]; _header.control = headerBuffer[12]; + if (!_vertPred) { + // there is a vertical predictor for each pixel in a line; each vertical + // predictor is 0 to start with + _vertPred = new uint32[_header.xsize]; + } + + if (!_surface) { + _surface = new Graphics::Surface(); + _surface->create(_header.xsize, _header.ysize, getPixelFormat()); + } + + // There is 1 change bit per 4 pixels, so each change byte represents + // 32 pixels; divide width by 4 to obtain the number of change bits and + // then round up to the nearest byte. + _mbChangeBitsRowSize = ((_header.xsize >> 2) + 7) >> 3; + // Version 2 if (_header.version >= 2) { if (_header.headerType > 3) { @@ -240,7 +248,7 @@ void TrueMotion1Decoder::decodeHeader(Common::SeekableReadStream &stream) { _indexStream = _mbChangeBits; } else { // one change bit per 4x4 block - _indexStream = _mbChangeBits + _mbChangeBitsRowSize * (_height >> 2); + _indexStream = _mbChangeBits + _mbChangeBitsRowSize * (_header.ysize >> 2); } _indexStreamSize = stream.size() - (_indexStream - _buf); @@ -306,11 +314,11 @@ void TrueMotion1Decoder::decode16() { int index; // clean out the line buffer - memset(_vertPred, 0, _width * 4); + memset(_vertPred, 0, _header.xsize * 4); GET_NEXT_INDEX(); - for (int y = 0; y < _height; y++) { + for (int y = 0; y < _header.ysize; y++) { // re-init variables for the next line iteration uint32 horizPred = 0; uint32 *currentPixelPair = (uint32 *)_surface->getBasePtr(0, y); @@ -319,7 +327,7 @@ void TrueMotion1Decoder::decode16() { byte mbChangeByte = _mbChangeBits[mbChangeIndex++]; byte mbChangeByteMask = 1; - for (int pixelsLeft = _width; pixelsLeft > 0; pixelsLeft -= 4) { + for (int pixelsLeft = _header.xsize; pixelsLeft > 0; pixelsLeft -= 4) { if (keyframe || (mbChangeByte & mbChangeByteMask) == 0) { switch (y & 3) { case 0: diff --git a/image/codecs/truemotion1.h b/image/codecs/truemotion1.h index 12570f066c..51daf607d2 100644 --- a/image/codecs/truemotion1.h +++ b/image/codecs/truemotion1.h @@ -39,7 +39,7 @@ namespace Image { */ class TrueMotion1Decoder : public Codec { public: - TrueMotion1Decoder(uint16 width, uint16 height); + TrueMotion1Decoder(); ~TrueMotion1Decoder(); const Graphics::Surface *decodeFrame(Common::SeekableReadStream &stream); @@ -54,7 +54,6 @@ private: byte *_buf, *_mbChangeBits, *_indexStream; int _indexStreamSize; - uint16 _width, _height; int _flags; struct PredictorTableEntry { diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index 9b196fefc9..68d6cb6cec 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -183,7 +183,7 @@ void AVIDecoder::handleList(uint32 listSize) { _decodedHeader = true; break; case ID_INFO: // Metadata - case ID_PRMI: // Unknown metadata, should be safe to ignore + case ID_PRMI: // Adobe Premiere metadata, safe to ignore // Ignore metadata _fileStream->skip(listSize); return; @@ -322,6 +322,9 @@ bool AVIDecoder::loadStream(Common::SeekableReadStream *stream) { // Seek back to the start of the MOVI list _fileStream->seek(_movieListStart); + // Check if this is a special Duck Truemotion video + checkTruemotion1(); + return true; } @@ -658,6 +661,48 @@ void AVIDecoder::forceVideoEnd() { ((AVIVideoTrack *)*it)->forceTrackEnd(); } +void AVIDecoder::checkTruemotion1() { + AVIVideoTrack *track = 0; + + for (TrackListIterator it = getTrackListBegin(); it != getTrackListEnd(); it++) { + if ((*it)->getTrackType() == Track::kTrackTypeVideo) { + if (track) { + // Multiple tracks; isn't going to be truemotion 1 + return; + } + + track = (AVIVideoTrack *)*it; + } + } + + // No track found? + if (!track) + return; + + // Ignore non-truemotion tracks + if (!track->isTruemotion1()) + return; + + // Search for a non-empty frame + const Graphics::Surface *frame = 0; + for (int i = 0; i < 10 && !frame; i++) + frame = decodeNextFrame(); + + if (!frame) { + // Probably shouldn't happen + rewind(); + return; + } + + // Fill in the width/height based on the frame's width/height + _header.width = frame->w; + _header.height = frame->h; + track->forceDimensions(frame->w, frame->h); + + // Rewind us back to the beginning + rewind(); +} + VideoDecoder::AudioTrack *AVIDecoder::getAudioTrack(int index) { // AVI audio track indexes are relative to the first track Track *track = getTrack(index); @@ -732,6 +777,15 @@ void AVIDecoder::AVIVideoTrack::useInitialPalette() { } } +bool AVIDecoder::AVIVideoTrack::isTruemotion1() const { + return _bmInfo.compression == MKTAG('D', 'U', 'C', 'K') || _bmInfo.compression == MKTAG('d', 'u', 'c', 'k'); +} + +void AVIDecoder::AVIVideoTrack::forceDimensions(uint16 width, uint16 height) { + _bmInfo.width = width; + _bmInfo.height = height; +} + bool AVIDecoder::AVIVideoTrack::rewind() { _curFrame = -1; diff --git a/video/avi_decoder.h b/video/avi_decoder.h index 2f7b267d36..28d87bc3b7 100644 --- a/video/avi_decoder.h +++ b/video/avi_decoder.h @@ -185,6 +185,9 @@ protected: void loadPaletteFromChunk(Common::SeekableReadStream *chunk); void useInitialPalette(); + bool isTruemotion1() const; + void forceDimensions(uint16 width, uint16 height); + bool isRewindable() const { return true; } bool rewind(); @@ -257,6 +260,7 @@ protected: uint16 getStreamType(uint32 tag) const { return tag & 0xFFFF; } byte getStreamIndex(uint32 tag) const; void forceVideoEnd(); + void checkTruemotion1(); public: virtual AVIAudioTrack *createAudioTrack(AVIStreamHeader sHeader, PCMWaveFormat wvInfo); |