2009-02-17 15:02:16 +00:00
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers , whose names
* are too numerous to list here . Please refer to the COPYRIGHT
* file distributed with this source distribution .
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*
* $ URL $
* $ Id $
*
*/
2009-02-15 06:10:59 +00:00
2009-02-20 22:21:33 +00:00
# include "sci/sci.h"
2009-02-24 05:51:55 +00:00
# include "sci/engine/kernel.h"
2009-12-04 17:38:24 +00:00
# include "sci/event.h"
2009-05-15 14:07:45 +00:00
# include "sci/resource.h"
2009-02-27 02:23:40 +00:00
# include "sci/engine/state.h"
2009-02-15 06:10:59 +00:00
2010-02-17 23:37:32 +00:00
# include "common/system.h"
2009-02-21 10:23:36 +00:00
namespace Sci {
2010-06-10 15:25:36 +00:00
// Uncompiled kernel signatures are formed from a string of letters.
// each corresponding to a type of a parameter (see below).
// Use small letters to indicate end of sum type.
// Use capital letters for sum types, e.g.
// "LNoLr" for a function which takes two arguments:
// (1) list, node or object
// (2) list or ref
# define KSIG_SPEC_LIST 'l'
# define KSIG_SPEC_NODE 'n'
# define KSIG_SPEC_OBJECT 'o'
# define KSIG_SPEC_REF 'r' // Said Specs and strings
# define KSIG_SPEC_ARITHMETIC 'i'
# define KSIG_SPEC_NULL 'z'
# define KSIG_SPEC_ANY '.'
# define KSIG_SPEC_ELLIPSIS '*' // Arbitrarily more TYPED arguments
# define KSIG_SPEC_SUM_DONE ('a' - 'A')
2010-06-10 15:25:54 +00:00
/** Default kernel name table. */
static const char * s_defaultKernelNames [ ] = {
2009-05-31 12:05:49 +00:00
/*0x00*/ " Load " ,
/*0x01*/ " UnLoad " ,
/*0x02*/ " ScriptID " ,
/*0x03*/ " DisposeScript " ,
/*0x04*/ " Clone " ,
/*0x05*/ " DisposeClone " ,
/*0x06*/ " IsObject " ,
/*0x07*/ " RespondsTo " ,
/*0x08*/ " DrawPic " ,
2009-10-21 19:19:03 +00:00
/*0x09*/ " Dummy " , // Show
2009-05-31 12:05:49 +00:00
/*0x0a*/ " PicNotValid " ,
/*0x0b*/ " Animate " ,
/*0x0c*/ " SetNowSeen " ,
/*0x0d*/ " NumLoops " ,
/*0x0e*/ " NumCels " ,
/*0x0f*/ " CelWide " ,
/*0x10*/ " CelHigh " ,
/*0x11*/ " DrawCel " ,
/*0x12*/ " AddToPic " ,
/*0x13*/ " NewWindow " ,
/*0x14*/ " GetPort " ,
/*0x15*/ " SetPort " ,
/*0x16*/ " DisposeWindow " ,
/*0x17*/ " DrawControl " ,
/*0x18*/ " HiliteControl " ,
/*0x19*/ " EditControl " ,
/*0x1a*/ " TextSize " ,
/*0x1b*/ " Display " ,
/*0x1c*/ " GetEvent " ,
/*0x1d*/ " GlobalToLocal " ,
/*0x1e*/ " LocalToGlobal " ,
/*0x1f*/ " MapKeyToDir " ,
/*0x20*/ " DrawMenuBar " ,
/*0x21*/ " MenuSelect " ,
/*0x22*/ " AddMenu " ,
/*0x23*/ " DrawStatus " ,
/*0x24*/ " Parse " ,
/*0x25*/ " Said " ,
2010-02-21 01:25:10 +00:00
/*0x26*/ " SetSynonyms " , // Portrait (KQ6 hires)
2009-05-31 12:05:49 +00:00
/*0x27*/ " HaveMouse " ,
/*0x28*/ " SetCursor " ,
2010-02-21 01:25:10 +00:00
// FOpen (SCI0)
// FPuts (SCI0)
// FGets (SCI0)
// FClose (SCI0)
2009-05-31 12:05:49 +00:00
/*0x29*/ " SaveGame " ,
/*0x2a*/ " RestoreGame " ,
/*0x2b*/ " RestartGame " ,
/*0x2c*/ " GameIsRestarting " ,
/*0x2d*/ " DoSound " ,
/*0x2e*/ " NewList " ,
/*0x2f*/ " DisposeList " ,
/*0x30*/ " NewNode " ,
/*0x31*/ " FirstNode " ,
/*0x32*/ " LastNode " ,
/*0x33*/ " EmptyList " ,
/*0x34*/ " NextNode " ,
/*0x35*/ " PrevNode " ,
/*0x36*/ " NodeValue " ,
/*0x37*/ " AddAfter " ,
/*0x38*/ " AddToFront " ,
/*0x39*/ " AddToEnd " ,
/*0x3a*/ " FindKey " ,
/*0x3b*/ " DeleteKey " ,
/*0x3c*/ " Random " ,
/*0x3d*/ " Abs " ,
/*0x3e*/ " Sqrt " ,
/*0x3f*/ " GetAngle " ,
/*0x40*/ " GetDistance " ,
/*0x41*/ " Wait " ,
/*0x42*/ " GetTime " ,
/*0x43*/ " StrEnd " ,
/*0x44*/ " StrCat " ,
/*0x45*/ " StrCmp " ,
/*0x46*/ " StrLen " ,
/*0x47*/ " StrCpy " ,
/*0x48*/ " Format " ,
/*0x49*/ " GetFarText " ,
/*0x4a*/ " ReadNumber " ,
/*0x4b*/ " BaseSetter " ,
/*0x4c*/ " DirLoop " ,
2010-02-21 01:25:10 +00:00
/*0x4d*/ " CanBeHere " , // CantBeHere in newer SCI versions
2009-05-31 12:05:49 +00:00
/*0x4e*/ " OnControl " ,
/*0x4f*/ " InitBresen " ,
/*0x50*/ " DoBresen " ,
2010-02-21 01:25:10 +00:00
/*0x51*/ " Platform " , // DoAvoider (SCI0)
2009-05-31 12:05:49 +00:00
/*0x52*/ " SetJump " ,
/*0x53*/ " SetDebug " ,
- Changed the unimplemented debug SCI kernel functions (InspectObj, ShowSends, ShowObjs, ShowFree, StackUsage and Profiler) to be dummy functions - we have our own debugger, and don't use these functions for debugging
- Removed the function number parameter from all kernel functions, as it's no longer needed, and removed the FAKE_FUNCT_NR hack
- Removed kUnknown() and kStub()
- Dummy/unknown kernel functions are no longer invoked, and a warning is shown instead, with the paremeters passed to them
Note: there is an evil hack used for debugging scripts in invoke_selector(), which probably no longer works now
svn-id: r44461
2009-09-29 14:24:07 +00:00
/*0x54*/ " Dummy " , // InspectObj
/*0x55*/ " Dummy " , // ShowSends
/*0x56*/ " Dummy " , // ShowObjs
/*0x57*/ " Dummy " , // ShowFree
2009-05-31 12:05:49 +00:00
/*0x58*/ " MemoryInfo " ,
- Changed the unimplemented debug SCI kernel functions (InspectObj, ShowSends, ShowObjs, ShowFree, StackUsage and Profiler) to be dummy functions - we have our own debugger, and don't use these functions for debugging
- Removed the function number parameter from all kernel functions, as it's no longer needed, and removed the FAKE_FUNCT_NR hack
- Removed kUnknown() and kStub()
- Dummy/unknown kernel functions are no longer invoked, and a warning is shown instead, with the paremeters passed to them
Note: there is an evil hack used for debugging scripts in invoke_selector(), which probably no longer works now
svn-id: r44461
2009-09-29 14:24:07 +00:00
/*0x59*/ " Dummy " , // StackUsage
/*0x5a*/ " Dummy " , // Profiler
2009-05-31 12:05:49 +00:00
/*0x5b*/ " GetMenu " ,
/*0x5c*/ " SetMenu " ,
/*0x5d*/ " GetSaveFiles " ,
/*0x5e*/ " GetCWD " ,
/*0x5f*/ " CheckFreeSpace " ,
/*0x60*/ " ValidPath " ,
/*0x61*/ " CoordPri " ,
/*0x62*/ " StrAt " ,
/*0x63*/ " DeviceInfo " ,
/*0x64*/ " GetSaveDir " ,
/*0x65*/ " CheckSaveGame " ,
/*0x66*/ " ShakeScreen " ,
/*0x67*/ " FlushResources " ,
/*0x68*/ " SinMult " ,
/*0x69*/ " CosMult " ,
/*0x6a*/ " SinDiv " ,
/*0x6b*/ " CosDiv " ,
/*0x6c*/ " Graph " ,
/*0x6d*/ " Joystick " ,
2010-02-21 01:25:10 +00:00
// End of kernel function table for SCI0
2010-07-01 20:16:42 +00:00
/*0x6e*/ " Dummy " , // ShiftScreen
2009-05-31 12:05:49 +00:00
/*0x6f*/ " Palette " ,
/*0x70*/ " MemorySegment " ,
2010-02-21 01:25:10 +00:00
/*0x71*/ " Intersections " , // MoveCursor (SCI1 late), PalVary (SCI1.1)
2009-05-31 12:05:49 +00:00
/*0x72*/ " Memory " ,
2010-07-01 20:16:42 +00:00
/*0x73*/ " Dummy " , // ListOps
2009-05-31 12:05:49 +00:00
/*0x74*/ " FileIO " ,
/*0x75*/ " DoAudio " ,
/*0x76*/ " DoSync " ,
/*0x77*/ " AvoidPath " ,
2010-02-21 01:25:10 +00:00
/*0x78*/ " Sort " , // StrSplit (SCI01)
2010-07-01 20:16:42 +00:00
/*0x79*/ " Dummy " , // ATan
2009-05-31 12:05:49 +00:00
/*0x7a*/ " Lock " ,
/*0x7b*/ " StrSplit " ,
2010-02-21 01:25:10 +00:00
/*0x7c*/ " GetMessage " , // Message (SCI1.1)
2009-05-31 12:05:49 +00:00
/*0x7d*/ " IsItSkip " ,
/*0x7e*/ " MergePoly " ,
/*0x7f*/ " ResCheck " ,
/*0x80*/ " AssertPalette " ,
/*0x81*/ " TextColors " ,
/*0x82*/ " TextFonts " ,
2009-12-27 02:57:03 +00:00
/*0x83*/ " Dummy " , // Record
/*0x84*/ " Dummy " , // PlayBack
2009-05-31 12:05:49 +00:00
/*0x85*/ " ShowMovie " ,
/*0x86*/ " SetVideoMode " ,
/*0x87*/ " SetQuitStr " ,
2009-12-27 02:57:03 +00:00
/*0x88*/ " Dummy " // DbugStr
2009-05-31 12:05:49 +00:00
} ;
2009-02-15 06:10:59 +00:00
2010-07-10 18:21:09 +00:00
reg_t kStub ( EngineState * s , int argc , reg_t * argv ) {
Kernel * kernel = g_sci - > getKernel ( ) ;
int kernelCallNr = - 1 ;
Common : : List < ExecStack > : : iterator callIterator = s - > _executionStack . end ( ) ;
if ( callIterator ! = s - > _executionStack . begin ( ) ) {
callIterator - - ;
ExecStack lastCall = * callIterator ;
kernelCallNr = lastCall . debugSelector ;
}
Common : : String warningMsg = " Dummy function k " + kernel - > getKernelName ( kernelCallNr ) +
Common : : String : : printf ( " [%x] " , kernelCallNr ) +
" invoked. Params: " +
Common : : String : : printf ( " %d " , argc ) + " ( " ;
for ( int i = 0 ; i < argc ; i + + ) {
warningMsg + = Common : : String : : printf ( " %04x:%04x " , PRINT_REG ( argv [ i ] ) ) ;
warningMsg + = ( i = = argc - 1 ? " ) " : " , " ) ;
}
warning ( " %s " , warningMsg . c_str ( ) ) ;
return s - > r_acc ;
}
reg_t kStubNull ( EngineState * s , int argc , reg_t * argv ) {
kStub ( s , argc , argv ) ;
return NULL_REG ;
}
reg_t kDummy ( EngineState * s , int argc , reg_t * argv ) {
kStub ( s , argc , argv ) ;
error ( " Kernel function was called, which was considered to be unused - see log for details " ) ;
}
2010-06-29 20:44:19 +00:00
// [io] -> either integer or object
// (io) -> optionally integer AND an object
// (i) -> optional integer
// . -> any type
// i* -> optional multiple integers
// .* -> any parameters afterwards (or none)
2010-07-10 19:58:25 +00:00
// gameID, scriptNr,lvl, object-name, method-name, call, index, replace
static const SciWorkaroundEntry kAbs_workarounds [ ] = {
2010-07-11 19:11:48 +00:00
{ GID_HOYLE1 , 1 , 0 , " room1 " , " doit " , - 1 , 0 , { 2 , 0x3e9 } } , // crazy eights - called with objects instead of integers
{ GID_HOYLE1 , 2 , 0 , " room2 " , " doit " , - 1 , 0 , { 2 , 0x3e9 } } , // old maid - called with objects instead of integers
{ GID_HOYLE1 , 3 , 0 , " room3 " , " doit " , - 1 , 0 , { 2 , 0x3e9 } } , // hearts - called with objects instead of integers
SCI_WORKAROUNDENTRY_TERMINATOR
2010-07-10 19:58:25 +00:00
} ;
2010-07-05 14:36:31 +00:00
// gameID, scriptNr,lvl, object-name, method-name, call, index, replace
2010-06-30 09:47:04 +00:00
static const SciWorkaroundEntry kDisposeScript_workarounds [ ] = {
2010-07-11 19:11:48 +00:00
{ GID_QFG1 , 64 , 0 , " rm64 " , " dispose " , - 1 , 0 , { 1 , 0 } } , // when leaving graveyard, parameter 0 is an object
SCI_WORKAROUNDENTRY_TERMINATOR
2010-06-30 09:47:04 +00:00
} ;
2010-07-11 11:12:03 +00:00
// gameID, scriptNr,lvl, object-name, method-name, call, index, replace
static const SciWorkaroundEntry kDoSoundFade_workarounds [ ] = {
2010-07-11 19:11:48 +00:00
{ GID_KQ6 , 989 , 0 , " globalSound " , " fade " , - 1 , 0 , { 0 , 0 } } , // during intro, parameter 4 is an object
SCI_WORKAROUNDENTRY_TERMINATOR
2010-07-11 11:12:03 +00:00
} ;
2010-07-12 09:24:18 +00:00
// gameID, scriptNr,lvl, object-name, method-name, call, index, replace
static const SciWorkaroundEntry kGraphRestoreBox_workarounds [ ] = {
{ GID_LSL6 , 86 , 0 , " LL6Inv " , " show " , - 1 , 0 , { 1 , 0 } } , // happens when restoring, is called with hunk segment, but hunk is not allocated at that time
// ^^ TODO: check, if this is really a script error or an issue with our restore code
SCI_WORKAROUNDENTRY_TERMINATOR
} ;
2010-07-10 20:45:59 +00:00
// gameID, scriptNr,lvl, object-name, method-name, call, index, replace
static const SciWorkaroundEntry kGraphFillBoxAny_workarounds [ ] = {
2010-07-11 19:11:48 +00:00
{ GID_SQ4 , 818 , 0 , " iconTextSwitch " , " show " , - 1 , 0 , { 0 , 0 } } , // game menu "text/speech" display - parameter 5 is missing, but the right color number is on the stack
SCI_WORKAROUNDENTRY_TERMINATOR
2010-07-10 20:45:59 +00:00
} ;
2010-07-10 18:31:11 +00:00
// gameID, scriptNr,lvl, object-name, method-name, call, index, replace
static const SciWorkaroundEntry kUnLoad_workarounds [ ] = {
2010-07-11 19:11:48 +00:00
{ GID_LSL6 , 130 , 0 , " recruitLarryScr " , " changeState " , - 1 , 0 , { 1 , 0 } } , // during intro, a 3rd parameter is passed by accident
{ GID_SQ1 , 303 , 0 , " slotGuy " , " dispose " , - 1 , 0 , { 1 , 0 } } , // when leaving ulence flats bar, parameter 1 is not passed - script error
SCI_WORKAROUNDENTRY_TERMINATOR
2010-07-10 18:31:11 +00:00
} ;
2010-07-08 18:26:05 +00:00
struct SciKernelMapSubEntry {
2010-06-29 20:44:19 +00:00
SciVersion fromVersion ;
SciVersion toVersion ;
2010-07-08 18:26:05 +00:00
2010-07-08 21:22:59 +00:00
uint16 id ;
2010-07-08 18:26:05 +00:00
const char * name ;
2010-07-08 21:22:59 +00:00
KernelFunctionCall * function ;
2010-06-29 20:44:19 +00:00
const char * signature ;
2010-06-30 09:47:04 +00:00
const SciWorkaroundEntry * workarounds ;
2009-05-20 17:52:12 +00:00
} ;
2010-07-08 18:26:05 +00:00
# define SCI_SUBOPENTRY_TERMINATOR { SCI_VERSION_NONE, SCI_VERSION_NONE, 0, NULL, NULL, NULL, NULL }
# define SIG_SCIALL SCI_VERSION_NONE, SCI_VERSION_NONE
# define SIG_SCI0 SCI_VERSION_NONE, SCI_VERSION_01
# define SIG_SCI1 SCI_VERSION_1_EGA, SCI_VERSION_1_LATE
# define SIG_SCI11 SCI_VERSION_1_1, SCI_VERSION_1_1
# define SIG_SCI16 SCI_VERSION_NONE, SCI_VERSION_1_1
# define SIG_SCI32 SCI_VERSION_2, SCI_VERSION_NONE
// SCI-Sound-Version
2010-07-08 21:22:59 +00:00
# define SIG_SOUNDSCI0 SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE
2010-07-08 18:26:05 +00:00
# define SIG_SOUNDSCI1EARLY SCI_VERSION_1_EARLY, SCI_VERSION_1_EARLY
# define SIG_SOUNDSCI1LATE SCI_VERSION_1_LATE, SCI_VERSION_1_LATE
2010-06-29 20:44:19 +00:00
2010-07-03 12:33:49 +00:00
# define SIGFOR_ALL 0x3f
2010-06-29 21:41:36 +00:00
# define SIGFOR_DOS 1 << 0
2010-06-29 20:44:19 +00:00
# define SIGFOR_PC98 1 << 1
# define SIGFOR_WIN 1 << 2
# define SIGFOR_MAC 1 << 3
# define SIGFOR_AMIGA 1 << 4
# define SIGFOR_ATARI 1 << 5
2010-06-29 21:41:36 +00:00
# define SIGFOR_PC SIGFOR_DOS|SIGFOR_WIN
2010-06-29 20:44:19 +00:00
2010-06-29 21:41:36 +00:00
# define SIG_EVERYWHERE SIG_SCIALL, SIGFOR_ALL
2010-06-29 20:44:19 +00:00
# define MAP_CALL(_name_) #_name_, k##_name_
2010-07-10 18:34:38 +00:00
// version, subId, function-mapping, signature, workarounds
2010-07-08 18:26:05 +00:00
static const SciKernelMapSubEntry kDoSound_subops [ ] = {
2010-07-09 12:06:41 +00:00
{ SIG_SOUNDSCI0 , 0 , MAP_CALL ( DoSoundInit ) , " o " , NULL } ,
{ SIG_SOUNDSCI0 , 1 , MAP_CALL ( DoSoundPlay ) , " o " , NULL } ,
{ SIG_SOUNDSCI0 , 2 , MAP_CALL ( DoSoundDummy ) , " o " , NULL } ,
{ SIG_SOUNDSCI0 , 3 , MAP_CALL ( DoSoundDispose ) , " o " , NULL } ,
{ SIG_SOUNDSCI0 , 4 , MAP_CALL ( DoSoundMute ) , " (i) " , NULL } ,
{ SIG_SOUNDSCI0 , 5 , MAP_CALL ( DoSoundStop ) , " o " , NULL } ,
2010-07-09 16:05:47 +00:00
{ SIG_SOUNDSCI0 , 6 , MAP_CALL ( DoSoundPause ) , " i " , NULL } ,
2010-07-11 11:52:17 +00:00
{ SIG_SOUNDSCI0 , 7 , MAP_CALL ( DoSoundResume ) , " " , NULL } ,
2010-07-09 12:06:41 +00:00
{ SIG_SOUNDSCI0 , 8 , MAP_CALL ( DoSoundMasterVolume ) , " (i) " , NULL } ,
{ SIG_SOUNDSCI0 , 9 , MAP_CALL ( DoSoundUpdate ) , " o " , NULL } ,
{ SIG_SOUNDSCI0 , 10 , MAP_CALL ( DoSoundFade ) , " o " , NULL } ,
{ SIG_SOUNDSCI0 , 11 , MAP_CALL ( DoSoundGetPolyphony ) , " " , NULL } ,
{ SIG_SOUNDSCI0 , 12 , MAP_CALL ( DoSoundStopAll ) , " " , NULL } ,
2010-07-08 18:26:05 +00:00
{ SIG_SOUNDSCI1EARLY , 0 , MAP_CALL ( DoSoundMasterVolume ) , NULL , NULL } ,
{ SIG_SOUNDSCI1EARLY , 1 , MAP_CALL ( DoSoundMute ) , NULL , NULL } ,
{ SIG_SOUNDSCI1EARLY , 2 , MAP_CALL ( DoSoundDummy ) , NULL , NULL } ,
{ SIG_SOUNDSCI1EARLY , 3 , MAP_CALL ( DoSoundGetPolyphony ) , NULL , NULL } ,
{ SIG_SOUNDSCI1EARLY , 4 , MAP_CALL ( DoSoundUpdate ) , NULL , NULL } ,
{ SIG_SOUNDSCI1EARLY , 5 , MAP_CALL ( DoSoundInit ) , NULL , NULL } ,
{ SIG_SOUNDSCI1EARLY , 6 , MAP_CALL ( DoSoundDispose ) , NULL , NULL } ,
2010-07-09 12:06:41 +00:00
{ SIG_SOUNDSCI1EARLY , 7 , MAP_CALL ( DoSoundPlay ) , " oi " , NULL } ,
2010-07-08 18:26:05 +00:00
{ SIG_SOUNDSCI1EARLY , 8 , MAP_CALL ( DoSoundStop ) , NULL , NULL } ,
2010-07-09 12:06:41 +00:00
{ SIG_SOUNDSCI1EARLY , 9 , MAP_CALL ( DoSoundPause ) , " [o0]i " , NULL } ,
{ SIG_SOUNDSCI1EARLY , 10 , MAP_CALL ( DoSoundFade ) , " oiiii " , NULL } ,
2010-07-09 09:26:57 +00:00
{ SIG_SOUNDSCI1EARLY , 11 , MAP_CALL ( DoSoundUpdateCues ) , " o " , NULL } ,
{ SIG_SOUNDSCI1EARLY , 12 , MAP_CALL ( DoSoundSendMidi ) , " oiiii " , NULL } ,
2010-07-09 12:06:41 +00:00
{ SIG_SOUNDSCI1EARLY , 13 , MAP_CALL ( DoSoundReverb ) , " oi " , NULL } ,
2010-07-09 09:26:57 +00:00
{ SIG_SOUNDSCI1EARLY , 14 , MAP_CALL ( DoSoundSetHold ) , " oi " , NULL } ,
{ SIG_SOUNDSCI1EARLY , 15 , MAP_CALL ( DoSoundDummy ) , " " , NULL } ,
2010-07-08 18:26:05 +00:00
// ^^ Longbow demo
{ SIG_SOUNDSCI1LATE , 0 , MAP_CALL ( DoSoundMasterVolume ) , NULL , NULL } ,
{ SIG_SOUNDSCI1LATE , 1 , MAP_CALL ( DoSoundMute ) , NULL , NULL } ,
2010-07-09 12:06:41 +00:00
{ SIG_SOUNDSCI1LATE , 2 , MAP_CALL ( DoSoundDummy ) , " " , NULL } ,
2010-07-08 18:26:05 +00:00
{ SIG_SOUNDSCI1LATE , 3 , MAP_CALL ( DoSoundGetPolyphony ) , NULL , NULL } ,
2010-07-09 09:26:57 +00:00
{ SIG_SOUNDSCI1LATE , 4 , MAP_CALL ( DoSoundGetAudioCapability ) , " " , NULL } ,
2010-07-09 12:26:54 +00:00
{ SIG_SOUNDSCI1LATE , 5 , MAP_CALL ( DoSoundSuspend ) , " i " , NULL } ,
2010-07-08 18:26:05 +00:00
{ SIG_SOUNDSCI1LATE , 6 , MAP_CALL ( DoSoundInit ) , NULL , NULL } ,
{ SIG_SOUNDSCI1LATE , 7 , MAP_CALL ( DoSoundDispose ) , NULL , NULL } ,
{ SIG_SOUNDSCI1LATE , 8 , MAP_CALL ( DoSoundPlay ) , NULL , NULL } ,
{ SIG_SOUNDSCI1LATE , 9 , MAP_CALL ( DoSoundStop ) , NULL , NULL } ,
{ SIG_SOUNDSCI1LATE , 10 , MAP_CALL ( DoSoundPause ) , NULL , NULL } ,
2010-07-11 11:12:03 +00:00
{ SIG_SOUNDSCI1LATE , 11 , MAP_CALL ( DoSoundFade ) , " oiiii(i) " , kDoSoundFade_workarounds } ,
2010-07-08 18:26:05 +00:00
{ SIG_SOUNDSCI1LATE , 12 , MAP_CALL ( DoSoundSetHold ) , NULL , NULL } ,
{ SIG_SOUNDSCI1LATE , 13 , MAP_CALL ( DoSoundDummy ) , NULL , NULL } ,
2010-07-09 09:26:57 +00:00
{ SIG_SOUNDSCI1LATE , 14 , MAP_CALL ( DoSoundSetVolume ) , " oi " , NULL } ,
{ SIG_SOUNDSCI1LATE , 15 , MAP_CALL ( DoSoundSetPriority ) , " oi " , NULL } ,
{ SIG_SOUNDSCI1LATE , 16 , MAP_CALL ( DoSoundSetLoop ) , " oi " , NULL } ,
2010-07-08 18:26:05 +00:00
{ SIG_SOUNDSCI1LATE , 17 , MAP_CALL ( DoSoundUpdateCues ) , NULL , NULL } ,
{ SIG_SOUNDSCI1LATE , 18 , MAP_CALL ( DoSoundSendMidi ) , NULL , NULL } ,
{ SIG_SOUNDSCI1LATE , 19 , MAP_CALL ( DoSoundReverb ) , NULL , NULL } ,
{ SIG_SOUNDSCI1LATE , 20 , MAP_CALL ( DoSoundUpdate ) , NULL , NULL } ,
SCI_SUBOPENTRY_TERMINATOR
} ;
2010-07-10 18:34:38 +00:00
// version, subId, function-mapping, signature, workarounds
2010-07-10 18:21:09 +00:00
static const SciKernelMapSubEntry kGraph_subops [ ] = {
{ SIG_SCI32 , 1 , MAP_CALL ( StubNull ) , " " , NULL } , // called by gk1 sci32 right at the start
{ SIG_SCIALL , 2 , MAP_CALL ( GraphGetColorCount ) , " " , NULL } ,
// 3 - set palette via resource
{ SIG_SCIALL , 4 , MAP_CALL ( GraphDrawLine ) , " iiiii(i)(i) " , NULL } ,
// 5 - nop
// 6 - draw pattern
{ SIG_SCIALL , 7 , MAP_CALL ( GraphSaveBox ) , " iiiii " , NULL } ,
2010-07-12 09:24:18 +00:00
{ SIG_SCIALL , 8 , MAP_CALL ( GraphRestoreBox ) , " [r0!] " , kGraphRestoreBox_workarounds } ,
2010-07-10 18:21:09 +00:00
// ^ this may get called with invalid references, we check them within restoreBits() and sierra sci behaves the same
{ SIG_SCIALL , 9 , MAP_CALL ( GraphFillBoxBackground ) , " iiii " , NULL } ,
{ SIG_SCIALL , 10 , MAP_CALL ( GraphFillBoxForeground ) , " iiii " , NULL } ,
2010-07-10 20:45:59 +00:00
{ SIG_SCIALL , 11 , MAP_CALL ( GraphFillBoxAny ) , " iiiiii(i)(i) " , kGraphFillBoxAny_workarounds } ,
2010-07-10 21:47:37 +00:00
{ SIG_SCI11 , 12 , MAP_CALL ( GraphUpdateBox ) , " iiii(i)(r0) " , NULL } , // kq6 hires
{ SIG_SCIALL , 12 , MAP_CALL ( GraphUpdateBox ) , " iiii(i) " , NULL } ,
2010-07-10 18:21:09 +00:00
{ SIG_SCIALL , 13 , MAP_CALL ( GraphRedrawBox ) , " iiii " , NULL } ,
{ SIG_SCIALL , 14 , MAP_CALL ( GraphAdjustPriority ) , " ii " , NULL } ,
{ SIG_SCI11 , 15 , MAP_CALL ( GraphSaveUpscaledHiresBox ) , " iiii " , NULL } , // kq6 hires
SCI_SUBOPENTRY_TERMINATOR
} ;
2010-07-10 18:34:38 +00:00
// version, subId, function-mapping, signature, workarounds
2010-07-10 10:20:23 +00:00
static const SciKernelMapSubEntry kPalVary_subops [ ] = {
{ SIG_SCIALL , 0 , MAP_CALL ( PalVaryInit ) , " ii(i)(i) " , NULL } ,
{ SIG_SCIALL , 1 , MAP_CALL ( PalVaryReverse ) , " (i)(i)(i) " , NULL } ,
{ SIG_SCIALL , 2 , MAP_CALL ( PalVaryGetCurrentStep ) , " " , NULL } ,
{ SIG_SCIALL , 3 , MAP_CALL ( PalVaryDeinit ) , " " , NULL } ,
{ SIG_SCIALL , 4 , MAP_CALL ( PalVaryChangeTarget ) , " i " , NULL } ,
{ SIG_SCIALL , 5 , MAP_CALL ( PalVaryChangeTicks ) , " i " , NULL } ,
{ SIG_SCIALL , 6 , MAP_CALL ( PalVaryPauseResume ) , " i " , NULL } ,
{ SIG_SCI32 , 8 , MAP_CALL ( PalVaryUnknown ) , " " , NULL } ,
SCI_SUBOPENTRY_TERMINATOR
} ;
2010-07-10 18:34:38 +00:00
// version, subId, function-mapping, signature, workarounds
2010-07-10 12:19:32 +00:00
static const SciKernelMapSubEntry kPalette_subops [ ] = {
{ SIG_SCIALL , 1 , MAP_CALL ( PaletteSetFromResource ) , " i(i) " , NULL } ,
{ SIG_SCIALL , 2 , MAP_CALL ( PaletteSetFlag ) , " iii " , NULL } ,
{ SIG_SCIALL , 3 , MAP_CALL ( PaletteUnsetFlag ) , " iii " , NULL } ,
{ SIG_SCIALL , 4 , MAP_CALL ( PaletteSetIntensity ) , " iii(i) " , NULL } ,
{ SIG_SCIALL , 5 , MAP_CALL ( PaletteFindColor ) , " iii " , NULL } ,
{ SIG_SCIALL , 6 , MAP_CALL ( PaletteAnimate ) , " i* " , NULL } ,
{ SIG_SCIALL , 7 , MAP_CALL ( PaletteSave ) , " " , NULL } ,
{ SIG_SCIALL , 8 , MAP_CALL ( PaletteRestore ) , " i " , NULL } ,
SCI_SUBOPENTRY_TERMINATOR
} ;
2010-07-08 18:26:05 +00:00
struct SciKernelMapEntry {
const char * name ;
2010-07-08 21:22:59 +00:00
KernelFunctionCall * function ;
2010-07-08 18:26:05 +00:00
SciVersion fromVersion ;
SciVersion toVersion ;
byte forPlatform ;
const char * signature ;
2010-07-08 21:22:59 +00:00
const SciKernelMapSubEntry * subFunctions ;
2010-07-08 18:26:05 +00:00
const SciWorkaroundEntry * workarounds ;
} ;
2010-06-29 21:13:19 +00:00
// name, version/platform, signature, sub-signatures, workarounds
2010-06-29 20:44:19 +00:00
static SciKernelMapEntry s_kernelMap [ ] = {
2010-07-10 19:58:25 +00:00
{ MAP_CALL ( Abs ) , SIG_EVERYWHERE , " i " , NULL , kAbs_workarounds } ,
2010-07-08 18:26:05 +00:00
{ MAP_CALL ( AddAfter ) , SIG_EVERYWHERE , " lnn " , NULL , NULL } ,
{ MAP_CALL ( AddMenu ) , SIG_EVERYWHERE , " rr " , NULL , NULL } ,
{ MAP_CALL ( AddToEnd ) , SIG_EVERYWHERE , " ln " , NULL , NULL } ,
{ MAP_CALL ( AddToFront ) , SIG_EVERYWHERE , " ln " , NULL , NULL } ,
{ MAP_CALL ( AddToPic ) , SIG_EVERYWHERE , " [il](iiiiii) " , NULL , NULL } ,
{ MAP_CALL ( Animate ) , SIG_EVERYWHERE , " (l0)(i) " , NULL , NULL } ,
{ MAP_CALL ( AssertPalette ) , SIG_EVERYWHERE , " i " , NULL , NULL } ,
{ MAP_CALL ( AvoidPath ) , SIG_EVERYWHERE , " ii(.*) " , NULL , NULL } ,
{ MAP_CALL ( BaseSetter ) , SIG_EVERYWHERE , " o " , NULL , NULL } ,
{ MAP_CALL ( CanBeHere ) , SIG_EVERYWHERE , " o(l) " , NULL , NULL } ,
{ MAP_CALL ( CantBeHere ) , SIG_EVERYWHERE , " o(l) " , NULL , NULL } ,
{ MAP_CALL ( CelHigh ) , SIG_EVERYWHERE , " ii(i) " , NULL , NULL } ,
{ MAP_CALL ( CelWide ) , SIG_EVERYWHERE , " ii(i) " , NULL , NULL } ,
{ MAP_CALL ( CheckFreeSpace ) , SIG_SCI32 , SIGFOR_ALL , " r.* " , NULL , NULL } ,
{ MAP_CALL ( CheckFreeSpace ) , SIG_EVERYWHERE , " r " , NULL , NULL } ,
{ MAP_CALL ( CheckSaveGame ) , SIG_EVERYWHERE , " .* " , NULL , NULL } ,
{ MAP_CALL ( Clone ) , SIG_EVERYWHERE , " o " , NULL , NULL } ,
{ MAP_CALL ( CoordPri ) , SIG_EVERYWHERE , " i(i) " , NULL , NULL } ,
{ MAP_CALL ( CosDiv ) , SIG_EVERYWHERE , " ii " , NULL , NULL } ,
{ MAP_CALL ( DeleteKey ) , SIG_EVERYWHERE , " l. " , NULL , NULL } ,
{ MAP_CALL ( DeviceInfo ) , SIG_EVERYWHERE , " i(r)(r)(i) " , NULL , NULL } , // subop
2010-07-10 17:08:42 +00:00
{ MAP_CALL ( Display ) , SIG_EVERYWHERE , " [ir]([ir!]*) " , NULL , NULL } ,
// ^ we allow invalid references here, because kDisplay gets called with those in e.g. pq3 during intro
2010-07-10 18:21:09 +00:00
// restoreBits() checks and skips invalid handles, so that's fine. Sierra SCI behaved the same
2010-07-08 18:26:05 +00:00
{ MAP_CALL ( DirLoop ) , SIG_EVERYWHERE , " oi " , NULL , NULL } ,
{ MAP_CALL ( DisposeClone ) , SIG_EVERYWHERE , " o " , NULL , NULL } ,
{ MAP_CALL ( DisposeList ) , SIG_EVERYWHERE , " l " , NULL , NULL } ,
{ MAP_CALL ( DisposeScript ) , SIG_EVERYWHERE , " i(i*) " , NULL , kDisposeScript_workarounds } ,
{ MAP_CALL ( DisposeWindow ) , SIG_EVERYWHERE , " i(i) " , NULL , NULL } ,
{ MAP_CALL ( DoAudio ) , SIG_EVERYWHERE , " i(.*) " , NULL , NULL } , // subop
{ MAP_CALL ( DoAvoider ) , SIG_EVERYWHERE , " o " , NULL , NULL } ,
{ MAP_CALL ( DoBresen ) , SIG_EVERYWHERE , " o " , NULL , NULL } ,
2010-07-10 10:20:23 +00:00
{ MAP_CALL ( DoSound ) , SIG_EVERYWHERE , " i([io])(i)(ii[io])(i) " , kDoSound_subops , NULL } ,
2010-07-08 18:26:05 +00:00
{ MAP_CALL ( DoSync ) , SIG_EVERYWHERE , " i(.*) " , NULL , NULL } , // subop
{ MAP_CALL ( DrawCel ) , SIG_SCI11 , SIGFOR_PC , " iiiii(i)(i)(r0) " , NULL , NULL } , // for kq6 hires
{ MAP_CALL ( DrawCel ) , SIG_EVERYWHERE , " iiiii(i)(i) " , NULL , NULL } ,
{ MAP_CALL ( DrawControl ) , SIG_EVERYWHERE , " o " , NULL , NULL } ,
{ MAP_CALL ( DrawMenuBar ) , SIG_EVERYWHERE , " i " , NULL , NULL } ,
{ MAP_CALL ( DrawPic ) , SIG_EVERYWHERE , " i(i)(i)(i) " , NULL , NULL } ,
{ MAP_CALL ( DrawStatus ) , SIG_EVERYWHERE , " [r0](i)(i) " , NULL , NULL } ,
{ MAP_CALL ( EditControl ) , SIG_EVERYWHERE , " [o0][o0] " , NULL , NULL } ,
{ MAP_CALL ( Empty ) , SIG_EVERYWHERE , " (.*) " , NULL , NULL } ,
{ MAP_CALL ( EmptyList ) , SIG_EVERYWHERE , " l " , NULL , NULL } ,
{ MAP_CALL ( FClose ) , SIG_EVERYWHERE , " i " , NULL , NULL } ,
{ MAP_CALL ( FGets ) , SIG_EVERYWHERE , " rii " , NULL , NULL } ,
{ MAP_CALL ( FOpen ) , SIG_EVERYWHERE , " ri " , NULL , NULL } ,
{ MAP_CALL ( FPuts ) , SIG_EVERYWHERE , " ir " , NULL , NULL } ,
{ MAP_CALL ( FileIO ) , SIG_EVERYWHERE , " i(.*) " , NULL , NULL } , // subop
{ MAP_CALL ( FindKey ) , SIG_EVERYWHERE , " l. " , NULL , NULL } ,
{ MAP_CALL ( FirstNode ) , SIG_EVERYWHERE , " [l0] " , NULL , NULL } ,
{ MAP_CALL ( FlushResources ) , SIG_EVERYWHERE , " i " , NULL , NULL } ,
{ MAP_CALL ( Format ) , SIG_EVERYWHERE , " r(.*) " , NULL , NULL } ,
{ MAP_CALL ( GameIsRestarting ) , SIG_EVERYWHERE , " (i) " , NULL , NULL } ,
{ MAP_CALL ( GetAngle ) , SIG_EVERYWHERE , " iiii " , NULL , NULL } ,
2010-06-29 20:44:19 +00:00
// ^^ FIXME - occasionally KQ6 passes a 5th argument by mistake
2010-07-08 18:26:05 +00:00
{ MAP_CALL ( GetCWD ) , SIG_EVERYWHERE , " r " , NULL , NULL } ,
{ MAP_CALL ( GetDistance ) , SIG_EVERYWHERE , " ii(i)(i)(i)(i) " , NULL , NULL } ,
{ MAP_CALL ( GetEvent ) , SIG_SCIALL , SIGFOR_MAC , " io(i*) " , NULL , NULL } ,
{ MAP_CALL ( GetEvent ) , SIG_EVERYWHERE , " io " , NULL , NULL } ,
{ MAP_CALL ( GetFarText ) , SIG_EVERYWHERE , " ii[r0] " , NULL , NULL } ,
{ MAP_CALL ( GetMenu ) , SIG_EVERYWHERE , " i. " , NULL , NULL } ,
{ MAP_CALL ( GetMessage ) , SIG_EVERYWHERE , " iiir " , NULL , NULL } ,
{ MAP_CALL ( GetPort ) , SIG_EVERYWHERE , " " , NULL , NULL } ,
{ MAP_CALL ( GetSaveDir ) , SIG_SCI32 , SIGFOR_ALL , " (r*) " , NULL , NULL } ,
{ MAP_CALL ( GetSaveDir ) , SIG_EVERYWHERE , " " , NULL , NULL } ,
{ MAP_CALL ( GetSaveFiles ) , SIG_EVERYWHERE , " rrr " , NULL , NULL } ,
{ MAP_CALL ( GetTime ) , SIG_EVERYWHERE , " (i) " , NULL , NULL } ,
{ MAP_CALL ( GlobalToLocal ) , SIG_SCI32 , SIGFOR_ALL , " oo " , NULL , NULL } ,
{ MAP_CALL ( GlobalToLocal ) , SIG_EVERYWHERE , " o " , NULL , NULL } ,
2010-07-12 09:24:18 +00:00
{ MAP_CALL ( Graph ) , SIG_EVERYWHERE , NULL , kGraph_subops , NULL } ,
2010-07-08 18:26:05 +00:00
{ MAP_CALL ( HaveMouse ) , SIG_EVERYWHERE , " " , NULL , NULL } ,
{ MAP_CALL ( HiliteControl ) , SIG_EVERYWHERE , " o " , NULL , NULL } ,
{ MAP_CALL ( InitBresen ) , SIG_EVERYWHERE , " o(i) " , NULL , NULL } ,
{ MAP_CALL ( Intersections ) , SIG_EVERYWHERE , " iiiiriiiri " , NULL , NULL } ,
{ MAP_CALL ( IsItSkip ) , SIG_EVERYWHERE , " iiiii " , NULL , NULL } ,
{ MAP_CALL ( IsObject ) , SIG_EVERYWHERE , " . " , NULL , NULL } ,
{ MAP_CALL ( Joystick ) , SIG_EVERYWHERE , " i(.*) " , NULL , NULL } , // subop
{ MAP_CALL ( LastNode ) , SIG_EVERYWHERE , " l " , NULL , NULL } ,
{ MAP_CALL ( Load ) , SIG_EVERYWHERE , " ii(i*) " , NULL , NULL } ,
{ MAP_CALL ( LocalToGlobal ) , SIG_SCI32 , SIGFOR_ALL , " oo " , NULL , NULL } ,
{ MAP_CALL ( LocalToGlobal ) , SIG_EVERYWHERE , " o " , NULL , NULL } ,
{ MAP_CALL ( Lock ) , SIG_EVERYWHERE , " ii(i) " , NULL , NULL } ,
{ MAP_CALL ( MapKeyToDir ) , SIG_EVERYWHERE , " o " , NULL , NULL } ,
{ MAP_CALL ( Memory ) , SIG_EVERYWHERE , " i(.*) " , NULL , NULL } , // subop
{ MAP_CALL ( MemoryInfo ) , SIG_EVERYWHERE , " i " , NULL , NULL } ,
{ MAP_CALL ( MemorySegment ) , SIG_EVERYWHERE , " ir(i) " , NULL , NULL } , // subop
{ MAP_CALL ( MenuSelect ) , SIG_EVERYWHERE , " o(i) " , NULL , NULL } ,
{ MAP_CALL ( MergePoly ) , SIG_EVERYWHERE , " rli " , NULL , NULL } ,
{ MAP_CALL ( Message ) , SIG_EVERYWHERE , " i(.*) " , NULL , NULL } , // subop
{ MAP_CALL ( MoveCursor ) , SIG_EVERYWHERE , " ii " , NULL , NULL } ,
{ MAP_CALL ( NewList ) , SIG_EVERYWHERE , " " , NULL , NULL } ,
{ MAP_CALL ( NewNode ) , SIG_EVERYWHERE , " .. " , NULL , NULL } ,
{ MAP_CALL ( NewWindow ) , SIG_SCIALL , SIGFOR_MAC , " .* " , NULL , NULL } ,
{ MAP_CALL ( NewWindow ) , SIG_SCI0 , SIGFOR_ALL , " iiii[r0]i(i)(i)(i) " , NULL , NULL } ,
{ MAP_CALL ( NewWindow ) , SIG_SCI1 , SIGFOR_ALL , " iiii[ir]i(i)(i)([ir])(i)(i)(i)(i) " , NULL , NULL } ,
{ MAP_CALL ( NewWindow ) , SIG_SCI11 , SIGFOR_ALL , " iiiiiiii[r0]i(i)(i)(i) " , NULL , NULL } ,
{ MAP_CALL ( NextNode ) , SIG_EVERYWHERE , " n " , NULL , NULL } ,
{ MAP_CALL ( NodeValue ) , SIG_EVERYWHERE , " [n0] " , NULL , NULL } ,
{ MAP_CALL ( NumCels ) , SIG_EVERYWHERE , " o " , NULL , NULL } ,
{ MAP_CALL ( NumLoops ) , SIG_EVERYWHERE , " o " , NULL , NULL } ,
{ MAP_CALL ( OnControl ) , SIG_EVERYWHERE , " ii(i)(i)(i) " , NULL , NULL } ,
2010-07-10 10:20:23 +00:00
{ MAP_CALL ( PalVary ) , SIG_EVERYWHERE , " i(i*) " , kPalVary_subops , NULL } ,
2010-07-10 12:19:32 +00:00
{ MAP_CALL ( Palette ) , SIG_EVERYWHERE , " i(.*) " , kPalette_subops , NULL } ,
2010-07-08 18:26:05 +00:00
{ MAP_CALL ( Parse ) , SIG_EVERYWHERE , " ro " , NULL , NULL } ,
{ MAP_CALL ( PicNotValid ) , SIG_EVERYWHERE , " (i) " , NULL , NULL } ,
{ MAP_CALL ( Platform ) , SIG_EVERYWHERE , " (.*) " , NULL , NULL } ,
{ MAP_CALL ( Portrait ) , SIG_EVERYWHERE , " i(.*) " , NULL , NULL } , // subop
{ MAP_CALL ( PrevNode ) , SIG_EVERYWHERE , " n " , NULL , NULL } ,
{ MAP_CALL ( PriCoord ) , SIG_EVERYWHERE , " i " , NULL , NULL } ,
{ MAP_CALL ( Random ) , SIG_EVERYWHERE , " ii " , NULL , NULL } ,
{ MAP_CALL ( ReadNumber ) , SIG_EVERYWHERE , " r " , NULL , NULL } ,
{ MAP_CALL ( ResCheck ) , SIG_EVERYWHERE , " ii(iiii) " , NULL , NULL } ,
{ MAP_CALL ( RespondsTo ) , SIG_EVERYWHERE , " .i " , NULL , NULL } ,
{ MAP_CALL ( RestartGame ) , SIG_EVERYWHERE , " " , NULL , NULL } ,
{ MAP_CALL ( RestoreGame ) , SIG_EVERYWHERE , " rir " , NULL , NULL } ,
{ MAP_CALL ( Said ) , SIG_EVERYWHERE , " [r0] " , NULL , NULL } ,
{ MAP_CALL ( SaveGame ) , SIG_EVERYWHERE , " rir(r) " , NULL , NULL } ,
{ MAP_CALL ( ScriptID ) , SIG_EVERYWHERE , " [io](i) " , NULL , NULL } ,
{ MAP_CALL ( SetCursor ) , SIG_EVERYWHERE , " i(i*) " , NULL , NULL } ,
{ MAP_CALL ( SetDebug ) , SIG_EVERYWHERE , " (i*) " , NULL , NULL } ,
{ MAP_CALL ( SetJump ) , SIG_EVERYWHERE , " oiii " , NULL , NULL } ,
{ MAP_CALL ( SetMenu ) , SIG_EVERYWHERE , " i(.*) " , NULL , NULL } ,
{ MAP_CALL ( SetNowSeen ) , SIG_EVERYWHERE , " o(i) " , NULL , NULL } ,
{ MAP_CALL ( SetPort ) , SIG_EVERYWHERE , " i(iii)(i)(i)(i) " , NULL , NULL } ,
{ MAP_CALL ( SetQuitStr ) , SIG_EVERYWHERE , " r " , NULL , NULL } ,
{ MAP_CALL ( SetSynonyms ) , SIG_EVERYWHERE , " o " , NULL , NULL } ,
{ MAP_CALL ( SetVideoMode ) , SIG_EVERYWHERE , " i " , NULL , NULL } ,
{ MAP_CALL ( ShakeScreen ) , SIG_EVERYWHERE , " (i)(i) " , NULL , NULL } ,
{ MAP_CALL ( ShowMovie ) , SIG_EVERYWHERE , " (.*) " , NULL , NULL } ,
{ MAP_CALL ( SinDiv ) , SIG_EVERYWHERE , " ii " , NULL , NULL } ,
{ MAP_CALL ( Sort ) , SIG_EVERYWHERE , " ooo " , NULL , NULL } ,
{ MAP_CALL ( Sqrt ) , SIG_EVERYWHERE , " i " , NULL , NULL } ,
{ MAP_CALL ( StrAt ) , SIG_EVERYWHERE , " ri(i) " , NULL , NULL } ,
{ MAP_CALL ( StrCat ) , SIG_EVERYWHERE , " rr " , NULL , NULL } ,
{ MAP_CALL ( StrCmp ) , SIG_EVERYWHERE , " rr(i) " , NULL , NULL } ,
{ MAP_CALL ( StrCpy ) , SIG_EVERYWHERE , " [r0]r(i) " , NULL , NULL } ,
{ MAP_CALL ( StrEnd ) , SIG_EVERYWHERE , " r " , NULL , NULL } ,
{ MAP_CALL ( StrLen ) , SIG_EVERYWHERE , " [r0] " , NULL , NULL } ,
{ MAP_CALL ( StrSplit ) , SIG_EVERYWHERE , " rr[r0] " , NULL , NULL } ,
{ MAP_CALL ( TextColors ) , SIG_EVERYWHERE , " (i*) " , NULL , NULL } ,
{ MAP_CALL ( TextFonts ) , SIG_EVERYWHERE , " (i*) " , NULL , NULL } ,
{ MAP_CALL ( TextSize ) , SIG_EVERYWHERE , " r[r0]i(i)(r0) " , NULL , NULL } ,
{ MAP_CALL ( TimesCos ) , SIG_EVERYWHERE , " ii " , NULL , NULL } ,
{ " CosMult " , kTimesCos , SIG_EVERYWHERE , " ii " , NULL , NULL } ,
{ MAP_CALL ( TimesCot ) , SIG_EVERYWHERE , " ii " , NULL , NULL } ,
{ MAP_CALL ( TimesSin ) , SIG_EVERYWHERE , " ii " , NULL , NULL } ,
{ " SinMult " , kTimesSin , SIG_EVERYWHERE , " ii " , NULL , NULL } ,
{ MAP_CALL ( TimesTan ) , SIG_EVERYWHERE , " ii " , NULL , NULL } ,
2010-07-10 18:31:11 +00:00
{ MAP_CALL ( UnLoad ) , SIG_EVERYWHERE , " i[ri] " , NULL , kUnLoad_workarounds } ,
2010-07-08 18:26:05 +00:00
{ MAP_CALL ( ValidPath ) , SIG_EVERYWHERE , " r " , NULL , NULL } ,
{ MAP_CALL ( Wait ) , SIG_EVERYWHERE , " i " , NULL , NULL } ,
2010-01-25 01:39:44 +00:00
2009-12-21 14:32:54 +00:00
# ifdef ENABLE_SCI32
2010-06-29 20:44:19 +00:00
// SCI2 Kernel Functions
2010-07-08 18:26:05 +00:00
{ MAP_CALL ( AddPlane ) , SIG_EVERYWHERE , " o " , NULL , NULL } ,
{ MAP_CALL ( AddScreenItem ) , SIG_EVERYWHERE , " o " , NULL , NULL } ,
{ MAP_CALL ( Array ) , SIG_EVERYWHERE , " (.*) " , NULL , NULL } ,
{ MAP_CALL ( CreateTextBitmap ) , SIG_EVERYWHERE , " i(.*) " , NULL , NULL } ,
{ MAP_CALL ( DeletePlane ) , SIG_EVERYWHERE , " o " , NULL , NULL } ,
{ MAP_CALL ( DeleteScreenItem ) , SIG_EVERYWHERE , " o " , NULL , NULL } ,
{ MAP_CALL ( FrameOut ) , SIG_EVERYWHERE , " " , NULL , NULL } ,
{ MAP_CALL ( GetHighPlanePri ) , SIG_EVERYWHERE , " " , NULL , NULL } ,
{ MAP_CALL ( InPolygon ) , SIG_EVERYWHERE , " iio " , NULL , NULL } ,
{ MAP_CALL ( IsHiRes ) , SIG_EVERYWHERE , " " , NULL , NULL } ,
{ MAP_CALL ( ListAllTrue ) , SIG_EVERYWHERE , " li(.*) " , NULL , NULL } ,
{ MAP_CALL ( ListAt ) , SIG_EVERYWHERE , " li " , NULL , NULL } ,
{ MAP_CALL ( ListEachElementDo ) , SIG_EVERYWHERE , " li(.*) " , NULL , NULL } ,
{ MAP_CALL ( ListFirstTrue ) , SIG_EVERYWHERE , " li(.*) " , NULL , NULL } ,
{ MAP_CALL ( ListIndexOf ) , SIG_EVERYWHERE , " l[o0] " , NULL , NULL } ,
{ MAP_CALL ( OnMe ) , SIG_EVERYWHERE , " iio(.*) " , NULL , NULL } ,
{ MAP_CALL ( RepaintPlane ) , SIG_EVERYWHERE , " o " , NULL , NULL } ,
{ MAP_CALL ( String ) , SIG_EVERYWHERE , " (.*) " , NULL , NULL } ,
{ MAP_CALL ( UpdatePlane ) , SIG_EVERYWHERE , " o " , NULL , NULL } ,
{ MAP_CALL ( UpdateScreenItem ) , SIG_EVERYWHERE , " o " , NULL , NULL } ,
2010-06-29 20:44:19 +00:00
// SCI2.1 Kernel Functions
2010-07-08 18:26:05 +00:00
{ MAP_CALL ( CD ) , SIG_EVERYWHERE , " (.*) " , NULL , NULL } ,
{ MAP_CALL ( IsOnMe ) , SIG_EVERYWHERE , " iio(.*) " , NULL , NULL } ,
{ MAP_CALL ( List ) , SIG_EVERYWHERE , " (.*) " , NULL , NULL } ,
{ MAP_CALL ( MulDiv ) , SIG_EVERYWHERE , " iii " , NULL , NULL } ,
{ MAP_CALL ( PlayVMD ) , SIG_EVERYWHERE , " (.*) " , NULL , NULL } ,
{ MAP_CALL ( Robot ) , SIG_EVERYWHERE , " (.*) " , NULL , NULL } ,
{ MAP_CALL ( Save ) , SIG_EVERYWHERE , " (.*) " , NULL , NULL } ,
{ MAP_CALL ( Text ) , SIG_EVERYWHERE , " (.*) " , NULL , NULL } ,
{ NULL , NULL , SIG_EVERYWHERE , NULL , NULL , NULL }
2009-12-21 14:32:54 +00:00
# endif
2010-06-29 20:44:19 +00:00
} ;
2009-02-15 06:10:59 +00:00
2010-06-17 23:13:30 +00:00
Kernel : : Kernel ( ResourceManager * resMan , SegManager * segMan )
: _resMan ( resMan ) , _segMan ( segMan ) , _invalid ( " <invalid> " ) {
2009-07-07 10:28:05 +00:00
loadSelectorNames ( ) ;
2009-07-07 11:14:18 +00:00
mapSelectors ( ) ; // Map a few special selectors for later use
2009-06-01 14:12:43 +00:00
}
Kernel : : ~ Kernel ( ) {
2010-07-08 21:22:59 +00:00
for ( KernelFunctionArray : : iterator i = _kernelFuncs . begin ( ) ; i ! = _kernelFuncs . end ( ) ; + + i )
2010-06-17 23:13:54 +00:00
free ( i - > signature ) ;
2009-06-01 14:12:43 +00:00
}
2009-09-21 21:38:07 +00:00
uint Kernel : : getSelectorNamesSize ( ) const {
return _selectorNames . size ( ) ;
}
2010-01-12 20:19:45 +00:00
2009-09-21 21:38:07 +00:00
const Common : : String & Kernel : : getSelectorName ( uint selector ) const {
2010-06-17 23:13:30 +00:00
if ( selector > = _selectorNames . size ( ) )
return _invalid ;
2009-09-21 21:38:07 +00:00
return _selectorNames [ selector ] ;
}
uint Kernel : : getKernelNamesSize ( ) const {
return _kernelNames . size ( ) ;
}
2010-01-12 20:19:45 +00:00
2009-09-21 21:38:07 +00:00
const Common : : String & Kernel : : getKernelName ( uint number ) const {
2010-06-18 09:37:06 +00:00
// FIXME: The following check is a temporary workaround for an issue
// leading to crashes when using the debugger's backtrace command.
2009-09-21 21:38:07 +00:00
if ( number > = _kernelNames . size ( ) )
2010-06-17 23:13:30 +00:00
return _invalid ;
2009-09-21 21:38:07 +00:00
return _kernelNames [ number ] ;
}
2009-09-17 14:54:11 +00:00
int Kernel : : findSelector ( const char * selectorName ) const {
for ( uint pos = 0 ; pos < _selectorNames . size ( ) ; + + pos ) {
if ( _selectorNames [ pos ] = = selectorName )
return pos ;
}
2010-01-30 11:59:05 +00:00
debugC ( 2 , kDebugLevelVM , " Could not map '%s' to any selector " , selectorName ) ;
2009-09-17 14:54:11 +00:00
return - 1 ;
}
2009-07-07 10:28:05 +00:00
void Kernel : : loadSelectorNames ( ) {
2009-09-02 12:02:37 +00:00
Resource * r = _resMan - > findResource ( ResourceId ( kResourceTypeVocab , VOCAB_RESOURCE_SELECTORS ) , 0 ) ;
2009-09-23 10:55:35 +00:00
bool oldScriptHeader = ( getSciVersion ( ) = = SCI_VERSION_0_EARLY ) ;
2009-06-01 14:12:43 +00:00
2009-07-11 06:33:19 +00:00
if ( ! r ) { // No such resource?
// Check if we have a table for this game
// Some demos do not have a selector table
2010-03-18 15:54:40 +00:00
Common : : StringArray staticSelectorTable = checkStaticSelectorNames ( ) ;
2010-01-25 01:39:44 +00:00
2009-07-11 06:33:19 +00:00
if ( staticSelectorTable . empty ( ) )
error ( " Kernel: Could not retrieve selector names " ) ;
2009-10-11 21:28:52 +00:00
else
warning ( " No selector vocabulary found, using a static one " ) ;
2009-07-11 06:33:19 +00:00
for ( uint32 i = 0 ; i < staticSelectorTable . size ( ) ; i + + ) {
_selectorNames . push_back ( staticSelectorTable [ i ] ) ;
2009-08-25 15:14:29 +00:00
if ( oldScriptHeader )
2009-07-11 06:33:19 +00:00
_selectorNames . push_back ( staticSelectorTable [ i ] ) ;
}
2010-01-25 01:39:44 +00:00
2009-07-11 06:33:19 +00:00
return ;
}
2009-06-01 14:12:43 +00:00
2009-07-07 10:28:05 +00:00
int count = READ_LE_UINT16 ( r - > data ) + 1 ; // Counter is slightly off
2009-06-01 14:12:43 +00:00
for ( int i = 0 ; i < count ; i + + ) {
int offset = READ_LE_UINT16 ( r - > data + 2 + i * 2 ) ;
int len = READ_LE_UINT16 ( r - > data + offset ) ;
Common : : String tmp ( ( const char * ) r - > data + offset + 2 , len ) ;
_selectorNames . push_back ( tmp ) ;
2009-07-04 16:30:20 +00:00
//printf("%s\n", tmp.c_str()); // debug
2009-06-01 14:12:43 +00:00
// Early SCI versions used the LSB in the selector ID as a read/write
// toggle. To compensate for that, we add every selector name twice.
2009-08-25 15:14:29 +00:00
if ( oldScriptHeader )
2009-06-01 14:12:43 +00:00
_selectorNames . push_back ( tmp ) ;
}
}
2010-07-05 14:36:31 +00:00
// this parses a written kernel signature into an internal memory format
// [io] -> either integer or object
// (io) -> optionally integer AND an object
// (i) -> optional integer
// . -> any type
// i* -> optional multiple integers
// .* -> any parameters afterwards (or none)
static uint16 * parseKernelSignature ( const char * kernelName , const char * writtenSig ) {
const char * curPos ;
char curChar ;
uint16 * result = NULL ;
uint16 * writePos = NULL ;
int size = 0 ;
bool validType = false ;
bool optionalType = false ;
bool eitherOr = false ;
bool optional = false ;
bool hadOptional = false ;
2010-07-12 09:24:18 +00:00
// No signature given? no signature out
if ( ! writtenSig )
return NULL ;
2010-07-05 14:36:31 +00:00
// First, we check how many bytes the result will be
// we also check, if the written signature makes any sense
curPos = writtenSig ;
while ( * curPos ) {
2010-07-07 18:35:07 +00:00
curChar = * curPos ;
switch ( curChar ) {
2010-07-05 14:36:31 +00:00
case ' [ ' : // either or
if ( eitherOr )
error ( " signature for k%s: '[' used within '[]' " , kernelName ) ;
eitherOr = true ;
validType = false ;
break ;
case ' ] ' : // either or end
if ( ! eitherOr )
error ( " signature for k%s: ']' used without leading '[' " , kernelName ) ;
if ( ! validType )
error ( " signature for k%s: '[]' does not surround valid type(s) " , kernelName ) ;
eitherOr = false ;
validType = false ;
size + + ;
break ;
case ' ( ' : // optional
if ( optional )
error ( " signature for k%s: '(' used within '()' brackets " , kernelName ) ;
if ( eitherOr )
error ( " signature for k%s: '(' used within '[]' brackets " , kernelName ) ;
optional = true ;
validType = false ;
optionalType = false ;
break ;
case ' ) ' : // optional end
if ( ! optional )
error ( " signature for k%s: ')' used without leading '(' " , kernelName ) ;
if ( ! optionalType )
error ( " signature for k%s: '()' does not to surround valid type(s) " , kernelName ) ;
optional = false ;
validType = false ;
hadOptional = true ;
break ;
case ' 0 ' : // allowed types
case ' i ' :
case ' o ' :
case ' r ' :
case ' l ' :
case ' n ' :
case ' . ' :
2010-07-07 18:35:07 +00:00
case ' ! ' :
2010-07-05 14:36:31 +00:00
if ( ( hadOptional ) & ( ! optional ) )
error ( " signature for k%s: non-optional type may not follow optional type " , kernelName ) ;
validType = true ;
if ( optional )
optionalType = true ;
if ( ! eitherOr )
size + + ;
break ;
case ' * ' : // accepts more of the same parameter (must be last char)
if ( ! validType ) {
if ( ( writtenSig = = curPos ) | | ( * ( curPos - 1 ) ! = ' ] ' ) )
error ( " signature for k%s: a valid type must be in front of '*' " , kernelName ) ;
}
if ( eitherOr )
error ( " signature for k%s: '*' may not be inside '[]' " , kernelName ) ;
if ( optional ) {
if ( ( * ( curPos + 1 ) ! = ' ) ' ) | | ( * ( curPos + 2 ) ! = 0 ) )
error ( " signature for k%s: '*' may only be used for last type " , kernelName ) ;
} else {
if ( * ( curPos + 1 ) ! = 0 )
error ( " signature for k%s: '*' may only be used for last type " , kernelName ) ;
}
break ;
default :
error ( " signature for k%s: '%c' unknown " , kernelName , * curPos ) ;
}
curPos + + ;
}
2009-02-15 06:10:59 +00:00
2010-07-05 14:36:31 +00:00
uint16 signature = 0 ;
// Now we allocate buffer with required size and fill it
result = new uint16 [ size + 1 ] ;
writePos = result ;
curPos = writtenSig ;
do {
curChar = * curPos ;
if ( ! eitherOr ) {
// not within either-or, check if next character forces output
switch ( curChar ) {
case 0 :
case ' [ ' :
case ' ( ' :
case ' ) ' :
case ' i ' :
case ' o ' :
case ' r ' :
case ' l ' :
case ' n ' :
case ' . ' :
2010-07-07 18:35:07 +00:00
case ' ! ' :
2010-07-05 14:36:31 +00:00
// and we also got some signature pending?
if ( signature ) {
2010-07-07 18:35:07 +00:00
if ( ! ( signature & SIG_MAYBE_ANY ) )
error ( " signature for k%s: invalid ('!') may only get used in combination with a real type " , kernelName ) ;
if ( ( signature & SIG_IS_INVALID ) & & ( ( signature & SIG_MAYBE_ANY ) = = ( SIG_TYPE_NULL | SIG_TYPE_INTEGER ) ) )
error ( " signature for k%s: invalid ('!') should not be used on exclusive null/integer type " , kernelName ) ;
2010-07-05 14:36:31 +00:00
if ( optional ) {
signature | = SIG_IS_OPTIONAL ;
if ( curChar ! = ' ) ' )
signature | = SIG_NEEDS_MORE ;
}
* writePos = signature ;
writePos + + ;
signature = 0 ;
}
}
}
switch ( curChar ) {
case ' [ ' : // either or
eitherOr = true ;
break ;
case ' ] ' : // either or end
eitherOr = false ;
break ;
case ' ( ' : // optional
optional = true ;
break ;
case ' ) ' : // optional end
optional = false ;
break ;
case ' 0 ' :
if ( signature & SIG_TYPE_NULL )
2010-07-07 18:35:07 +00:00
error ( " signature for k%s: NULL ('0') specified more than once " , kernelName ) ;
2010-07-05 14:36:31 +00:00
signature | = SIG_TYPE_NULL ;
break ;
case ' i ' :
if ( signature & SIG_TYPE_INTEGER )
2010-07-07 18:35:07 +00:00
error ( " signature for k%s: integer ('i') specified more than once " , kernelName ) ;
2010-07-05 14:36:31 +00:00
signature | = SIG_TYPE_INTEGER | SIG_TYPE_NULL ;
break ;
case ' o ' :
if ( signature & SIG_TYPE_OBJECT )
2010-07-07 18:35:07 +00:00
error ( " signature for k%s: object ('o') specified more than once " , kernelName ) ;
2010-07-05 14:36:31 +00:00
signature | = SIG_TYPE_OBJECT ;
break ;
case ' r ' :
if ( signature & SIG_TYPE_REFERENCE )
2010-07-07 18:35:07 +00:00
error ( " signature for k%s: reference ('r') specified more than once " , kernelName ) ;
2010-07-05 14:36:31 +00:00
signature | = SIG_TYPE_REFERENCE ;
break ;
case ' l ' :
if ( signature & SIG_TYPE_LIST )
2010-07-07 18:35:07 +00:00
error ( " signature for k%s: list ('l') specified more than once " , kernelName ) ;
2010-07-05 14:36:31 +00:00
signature | = SIG_TYPE_LIST ;
break ;
case ' n ' :
if ( signature & SIG_TYPE_NODE )
2010-07-07 18:35:07 +00:00
error ( " signature for k%s: node ('n') specified more than once " , kernelName ) ;
2010-07-05 14:36:31 +00:00
signature | = SIG_TYPE_NODE ;
break ;
case ' . ' :
2010-07-07 18:35:07 +00:00
if ( signature & SIG_MAYBE_ANY )
error ( " signature for k%s: maybe-any ('.') shouldn't get specified with other types in front of it " , kernelName ) ;
2010-07-05 14:36:31 +00:00
signature | = SIG_MAYBE_ANY ;
break ;
2010-07-07 18:35:07 +00:00
case ' ! ' :
if ( signature & SIG_IS_INVALID )
error ( " signature for k%s: invalid ('!') specified more than once " , kernelName ) ;
signature | = SIG_IS_INVALID ;
break ;
2010-07-05 14:36:31 +00:00
case ' * ' : // accepts more of the same parameter
signature | = SIG_MORE_MAY_FOLLOW ;
break ;
default :
break ;
}
curPos + + ;
} while ( curChar ) ;
2009-02-15 06:10:59 +00:00
2010-07-05 14:36:31 +00:00
// Write terminator
* writePos = 0 ;
2009-02-15 06:10:59 +00:00
2010-07-05 14:36:31 +00:00
return result ;
}
2009-02-15 06:10:59 +00:00
2010-07-07 18:35:07 +00:00
uint16 Kernel : : findRegType ( reg_t reg ) {
2010-07-05 14:36:31 +00:00
// No segment? Must be integer
if ( ! reg . segment )
return SIG_TYPE_INTEGER | ( reg . offset ? 0 : SIG_TYPE_NULL ) ;
2009-02-15 06:10:59 +00:00
2010-07-05 14:36:31 +00:00
if ( reg . segment = = 0xFFFF )
return SIG_TYPE_UNINITIALIZED ;
2009-02-15 06:10:59 +00:00
2010-07-05 14:36:31 +00:00
// Otherwise it's an object
SegmentObj * mobj = _segMan - > getSegmentObj ( reg . segment ) ;
if ( ! mobj )
2010-07-07 18:35:07 +00:00
return SIG_TYPE_ERROR ;
2009-02-15 06:10:59 +00:00
2010-07-07 18:35:07 +00:00
uint16 result = 0 ;
2010-07-05 14:36:31 +00:00
if ( ! mobj - > isValidOffset ( reg . offset ) )
2010-07-07 18:35:07 +00:00
result | = SIG_IS_INVALID ;
2009-02-15 06:10:59 +00:00
2010-07-05 14:36:31 +00:00
switch ( mobj - > getType ( ) ) {
case SEG_TYPE_SCRIPT :
if ( reg . offset < = ( * ( Script * ) mobj ) . getBufSize ( ) & &
reg . offset > = - SCRIPT_OBJECT_MAGIC_OFFSET & &
RAW_IS_OBJECT ( ( * ( Script * ) mobj ) . getBuf ( reg . offset ) ) ) {
2010-07-07 18:35:07 +00:00
result | = ( ( Script * ) mobj ) - > getObject ( reg . offset ) ? SIG_TYPE_OBJECT : SIG_TYPE_REFERENCE ;
2010-07-05 14:36:31 +00:00
} else
2010-07-07 18:35:07 +00:00
result | = SIG_TYPE_REFERENCE ;
break ;
2010-07-05 14:36:31 +00:00
case SEG_TYPE_CLONES :
2010-07-07 18:35:07 +00:00
result | = SIG_TYPE_OBJECT ;
break ;
2010-07-05 14:36:31 +00:00
case SEG_TYPE_LOCALS :
case SEG_TYPE_STACK :
case SEG_TYPE_SYS_STRINGS :
case SEG_TYPE_DYNMEM :
case SEG_TYPE_HUNK :
# ifdef ENABLE_SCI32
case SEG_TYPE_ARRAY :
case SEG_TYPE_STRING :
# endif
2010-07-07 18:35:07 +00:00
result | = SIG_TYPE_REFERENCE ;
break ;
2010-07-05 14:36:31 +00:00
case SEG_TYPE_LISTS :
2010-07-07 18:35:07 +00:00
result | = SIG_TYPE_LIST ;
break ;
2010-07-05 14:36:31 +00:00
case SEG_TYPE_NODES :
2010-07-07 18:35:07 +00:00
result | = SIG_TYPE_NODE ;
break ;
2010-07-05 14:36:31 +00:00
default :
2010-07-07 18:35:07 +00:00
return SIG_TYPE_ERROR ;
2010-07-05 14:36:31 +00:00
}
2010-07-07 18:35:07 +00:00
return result ;
2010-07-05 14:36:31 +00:00
}
2009-02-15 06:10:59 +00:00
2010-07-05 14:36:31 +00:00
struct SignatureDebugType {
uint16 typeCheck ;
const char * text ;
} ;
2009-02-15 06:10:59 +00:00
2010-07-05 14:36:31 +00:00
static const SignatureDebugType signatureDebugTypeList [ ] = {
{ SIG_TYPE_NULL , " null " } ,
{ SIG_TYPE_INTEGER , " integer " } ,
{ SIG_TYPE_UNINITIALIZED , " uninitialized " } ,
{ SIG_TYPE_OBJECT , " object " } ,
{ SIG_TYPE_REFERENCE , " reference " } ,
{ SIG_TYPE_LIST , " list " } ,
{ SIG_TYPE_NODE , " node " } ,
2010-07-07 18:35:07 +00:00
{ SIG_TYPE_ERROR , " error " } ,
{ SIG_IS_INVALID , " invalid " } ,
2010-07-05 14:36:31 +00:00
{ 0 , NULL }
} ;
2009-02-15 06:10:59 +00:00
2010-07-05 14:36:31 +00:00
static void kernelSignatureDebugType ( const uint16 type ) {
bool firstPrint = true ;
2009-02-15 06:10:59 +00:00
2010-07-05 14:36:31 +00:00
const SignatureDebugType * list = signatureDebugTypeList ;
while ( list - > typeCheck ) {
if ( type & list - > typeCheck ) {
if ( ! firstPrint )
printf ( " , " ) ;
printf ( " %s " , list - > text ) ;
firstPrint = false ;
}
list + + ;
}
}
2009-02-15 06:10:59 +00:00
2010-07-05 14:36:31 +00:00
// Shows kernel call signature and current arguments for debugging purposes
void Kernel : : signatureDebug ( const uint16 * sig , int argc , const reg_t * argv ) {
int argnr = 0 ;
while ( * sig | | argc ) {
printf ( " parameter %d: " , argnr + + ) ;
if ( argc ) {
reg_t parameter = * argv ;
printf ( " %04x:%04x ( " , PRINT_REG ( parameter ) ) ;
int regType = findRegType ( parameter ) ;
if ( regType )
kernelSignatureDebugType ( regType ) ;
else
printf ( " unknown type of %04x:%04x " , PRINT_REG ( parameter ) ) ;
printf ( " ) " ) ;
argv + + ;
argc - - ;
} else {
printf ( " not passed " ) ;
}
if ( * sig ) {
const uint16 signature = * sig ;
if ( ( signature & SIG_MAYBE_ANY ) = = SIG_MAYBE_ANY ) {
printf ( " , may be any " ) ;
} else {
printf ( " , should be " ) ;
kernelSignatureDebugType ( signature ) ;
2009-02-15 06:10:59 +00:00
}
2010-07-05 14:36:31 +00:00
if ( signature & SIG_IS_OPTIONAL )
printf ( " (optional) " ) ;
if ( signature & SIG_NEEDS_MORE )
printf ( " (needs more) " ) ;
if ( signature & SIG_MORE_MAY_FOLLOW )
printf ( " (more may follow) " ) ;
sig + + ;
}
printf ( " \n " ) ;
2009-02-15 06:10:59 +00:00
}
2010-07-05 14:36:31 +00:00
}
2009-02-15 06:10:59 +00:00
2010-07-05 14:36:31 +00:00
bool Kernel : : signatureMatch ( const uint16 * sig , int argc , const reg_t * argv ) {
uint16 nextSig = * sig ;
uint16 curSig = nextSig ;
while ( nextSig & & argc ) {
curSig = nextSig ;
int type = findRegType ( * argv ) ;
2010-06-17 23:13:54 +00:00
2010-07-07 18:35:07 +00:00
if ( ( type & SIG_IS_INVALID ) & & ( ! ( curSig & SIG_IS_INVALID ) ) )
return false ; // pointer is invalid and signature doesn't allow that?
if ( ! ( ( type & ~ SIG_IS_INVALID ) & curSig ) )
2010-07-05 14:36:31 +00:00
return false ; // type mismatch
if ( ! ( curSig & SIG_MORE_MAY_FOLLOW ) ) {
sig + + ;
nextSig = * sig ;
} else {
nextSig | = SIG_IS_OPTIONAL ; // more may follow -> assumes followers are optional
}
argv + + ;
argc - - ;
}
// Too many arguments?
if ( argc )
return false ;
// Signature end reached?
if ( nextSig = = 0 )
return true ;
// current parameter is optional?
if ( curSig & SIG_IS_OPTIONAL ) {
// yes, check if nothing more is required
if ( ! ( curSig & SIG_NEEDS_MORE ) )
return true ;
} else {
// no, check if next parameter is optional
if ( nextSig & SIG_IS_OPTIONAL )
return true ;
}
// Too few arguments or more optional arguments required
return false ;
2009-02-15 06:10:59 +00:00
}
2009-06-02 14:16:59 +00:00
void Kernel : : mapFunctions ( ) {
2009-02-15 06:10:59 +00:00
int mapped = 0 ;
int ignored = 0 ;
2010-06-29 20:44:19 +00:00
uint functionCount = _kernelNames . size ( ) ;
byte platformMask = 0 ;
2010-06-29 21:41:36 +00:00
SciVersion myVersion = getSciVersion ( ) ;
2010-06-29 20:44:19 +00:00
switch ( g_sci - > getPlatform ( ) ) {
case Common : : kPlatformPC :
2010-06-29 21:41:36 +00:00
platformMask = SIGFOR_DOS ;
2010-06-29 20:44:19 +00:00
break ;
case Common : : kPlatformPC98 :
platformMask = SIGFOR_PC98 ;
break ;
case Common : : kPlatformWindows :
platformMask = SIGFOR_WIN ;
break ;
case Common : : kPlatformMacintosh :
platformMask = SIGFOR_MAC ;
break ;
case Common : : kPlatformAmiga :
platformMask = SIGFOR_AMIGA ;
break ;
case Common : : kPlatformAtariST :
platformMask = SIGFOR_ATARI ;
break ;
default :
break ;
}
2009-02-15 06:10:59 +00:00
2010-06-29 20:44:19 +00:00
_kernelFuncs . resize ( functionCount ) ;
2009-02-15 06:10:59 +00:00
2010-07-08 21:22:59 +00:00
for ( uint id = 0 ; id < functionCount ; id + + ) {
2009-06-04 21:42:24 +00:00
// First, get the name, if known, of the kernel function with number functnr
2010-07-08 21:22:59 +00:00
Common : : String kernelName = _kernelNames [ id ] ;
2009-02-15 06:10:59 +00:00
2009-06-04 21:42:24 +00:00
// Reset the table entry
2010-07-08 21:22:59 +00:00
_kernelFuncs [ id ] . function = NULL ;
_kernelFuncs [ id ] . signature = NULL ;
2010-07-09 21:10:14 +00:00
_kernelFuncs [ id ] . name = NULL ;
2010-07-08 21:22:59 +00:00
_kernelFuncs [ id ] . workarounds = NULL ;
_kernelFuncs [ id ] . subFunctions = NULL ;
_kernelFuncs [ id ] . subFunctionCount = 0 ;
2010-07-09 21:10:14 +00:00
_kernelFuncs [ id ] . debugCalls = false ;
2010-07-08 21:22:59 +00:00
if ( kernelName . empty ( ) ) {
2009-09-02 11:35:00 +00:00
// No name was given -> must be an unknown opcode
2010-07-08 21:22:59 +00:00
warning ( " Kernel function %x unknown " , id ) ;
- Changed the unimplemented debug SCI kernel functions (InspectObj, ShowSends, ShowObjs, ShowFree, StackUsage and Profiler) to be dummy functions - we have our own debugger, and don't use these functions for debugging
- Removed the function number parameter from all kernel functions, as it's no longer needed, and removed the FAKE_FUNCT_NR hack
- Removed kUnknown() and kStub()
- Dummy/unknown kernel functions are no longer invoked, and a warning is shown instead, with the paremeters passed to them
Note: there is an evil hack used for debugging scripts in invoke_selector(), which probably no longer works now
svn-id: r44461
2009-09-29 14:24:07 +00:00
continue ;
}
// Don't map dummy functions - they will never be called
2010-07-10 18:21:09 +00:00
if ( kernelName = = " Dummy " ) {
_kernelFuncs [ id ] . function = kDummy ;
2009-09-02 11:35:00 +00:00
continue ;
2010-07-10 18:21:09 +00:00
}
2009-09-02 11:35:00 +00:00
2010-06-29 20:44:19 +00:00
// If the name is known, look it up in s_kernelMap. This table
2009-09-02 11:35:00 +00:00
// maps kernel func names to actual function (pointers).
2010-06-29 20:44:19 +00:00
SciKernelMapEntry * kernelMap = s_kernelMap ;
bool nameMatch = false ;
while ( kernelMap - > name ) {
2010-07-08 21:22:59 +00:00
if ( kernelName = = kernelMap - > name ) {
2010-07-05 14:36:31 +00:00
if ( ( kernelMap - > fromVersion = = SCI_VERSION_NONE ) | | ( kernelMap - > fromVersion < = myVersion ) )
if ( ( kernelMap - > toVersion = = SCI_VERSION_NONE ) | | ( kernelMap - > toVersion > = myVersion ) )
2010-06-29 21:41:36 +00:00
if ( platformMask & kernelMap - > forPlatform )
break ;
2010-06-29 20:44:19 +00:00
nameMatch = true ;
}
kernelMap + + ;
}
2009-09-02 11:35:00 +00:00
2010-06-29 20:44:19 +00:00
if ( kernelMap - > name ) {
// A match was found
2010-07-09 21:10:14 +00:00
_kernelFuncs [ id ] . function = kernelMap - > function ;
_kernelFuncs [ id ] . name = kernelMap - > name ;
_kernelFuncs [ id ] . signature = parseKernelSignature ( kernelMap - > name , kernelMap - > signature ) ;
_kernelFuncs [ id ] . workarounds = kernelMap - > workarounds ;
if ( kernelMap - > subFunctions ) {
// Get version for subfunction identification
SciVersion mySubVersion = ( SciVersion ) kernelMap - > function ( NULL , 0 , NULL ) . offset ;
// Now check whats the highest subfunction-id for this version
const SciKernelMapSubEntry * kernelSubMap = kernelMap - > subFunctions ;
uint16 subFunctionCount = 0 ;
while ( kernelSubMap - > function ) {
if ( ( kernelSubMap - > fromVersion = = SCI_VERSION_NONE ) | | ( kernelSubMap - > fromVersion < = mySubVersion ) )
if ( ( kernelSubMap - > toVersion = = SCI_VERSION_NONE ) | | ( kernelSubMap - > toVersion > = mySubVersion ) )
if ( subFunctionCount < = kernelSubMap - > id )
subFunctionCount = kernelSubMap - > id + 1 ;
kernelSubMap + + ;
}
if ( ! subFunctionCount )
error ( " k%s[%x]: no subfunctions found for requested version " , kernelName . c_str ( ) , id ) ;
// Now allocate required memory and go through it again
_kernelFuncs [ id ] . subFunctionCount = subFunctionCount ;
KernelSubFunction * subFunctions = new KernelSubFunction [ subFunctionCount ] ;
_kernelFuncs [ id ] . subFunctions = subFunctions ;
memset ( subFunctions , 0 , sizeof ( KernelSubFunction ) * subFunctionCount ) ;
// And fill this info out
kernelSubMap = kernelMap - > subFunctions ;
uint kernelSubNr = 0 ;
while ( kernelSubMap - > function ) {
if ( ( kernelSubMap - > fromVersion = = SCI_VERSION_NONE ) | | ( kernelSubMap - > fromVersion < = mySubVersion ) )
if ( ( kernelSubMap - > toVersion = = SCI_VERSION_NONE ) | | ( kernelSubMap - > toVersion > = mySubVersion ) ) {
uint subId = kernelSubMap - > id ;
2010-07-11 21:03:23 +00:00
if ( ! subFunctions [ subId ] . function ) {
subFunctions [ subId ] . function = kernelSubMap - > function ;
subFunctions [ subId ] . name = kernelSubMap - > name ;
subFunctions [ subId ] . workarounds = kernelSubMap - > workarounds ;
if ( kernelSubMap - > signature ) {
subFunctions [ subId ] . signature = parseKernelSignature ( kernelSubMap - > name , kernelSubMap - > signature ) ;
} else {
// we go back the submap to find the previous signature for that kernel call
const SciKernelMapSubEntry * kernelSubMapBack = kernelSubMap ;
uint kernelSubLeft = kernelSubNr ;
while ( kernelSubLeft ) {
kernelSubLeft - - ;
kernelSubMapBack - - ;
if ( kernelSubMapBack - > name = = kernelSubMap - > name ) {
if ( kernelSubMapBack - > signature ) {
subFunctions [ subId ] . signature = parseKernelSignature ( kernelSubMap - > name , kernelSubMapBack - > signature ) ;
break ;
}
2010-07-09 09:26:57 +00:00
}
}
2010-07-11 21:03:23 +00:00
if ( ! subFunctions [ subId ] . signature )
error ( " k%s: no previous signatures " , kernelSubMap - > name ) ;
2010-07-09 09:26:57 +00:00
}
2010-07-08 21:22:59 +00:00
}
2010-07-09 21:10:14 +00:00
}
kernelSubMap + + ;
kernelSubNr + + ;
2010-07-08 21:22:59 +00:00
}
2009-07-06 10:39:22 +00:00
}
2010-07-09 21:10:14 +00:00
+ + mapped ;
2010-06-29 20:44:19 +00:00
} else {
if ( nameMatch )
2010-07-08 21:22:59 +00:00
error ( " k%s[%x]: not found for this version/platform " , kernelName . c_str ( ) , id ) ;
2010-06-29 20:44:19 +00:00
// No match but a name was given -> stub
2010-07-08 21:22:59 +00:00
warning ( " k%s[%x]: unmapped " , kernelName . c_str ( ) , id ) ;
2010-07-10 18:21:09 +00:00
_kernelFuncs [ id ] . function = kStub ;
2009-06-04 21:42:24 +00:00
}
2009-02-19 18:33:43 +00:00
} // for all functions requesting to be mapped
2009-02-15 06:10:59 +00:00
2010-01-30 11:59:05 +00:00
debugC ( 2 , kDebugLevelVM , " Handled %d/%d kernel functions, mapping %d and ignoring %d. " ,
2009-09-17 14:53:57 +00:00
mapped + ignored , _kernelNames . size ( ) , mapped , ignored ) ;
2009-02-19 18:33:43 +00:00
2009-06-02 14:16:59 +00:00
return ;
2009-02-15 06:10:59 +00:00
}
2010-06-09 10:45:54 +00:00
void Kernel : : setDefaultKernelNames ( ) {
2010-06-10 15:25:54 +00:00
_kernelNames = Common : : StringArray ( s_defaultKernelNames , ARRAYSIZE ( s_defaultKernelNames ) ) ;
2009-08-17 23:11:25 +00:00
2009-09-17 14:53:57 +00:00
// Some (later) SCI versions replaced CanBeHere by CantBeHere
if ( _selectorCache . cantBeHere ! = - 1 )
_kernelNames [ 0x4d ] = " CantBeHere " ;
2009-09-23 10:55:35 +00:00
switch ( getSciVersion ( ) ) {
2009-08-17 23:11:25 +00:00
case SCI_VERSION_0_EARLY :
case SCI_VERSION_0_LATE :
// Insert SCI0 file functions after SetCursor (0x28)
_kernelNames . insert_at ( 0x29 , " FOpen " ) ;
_kernelNames . insert_at ( 0x2A , " FPuts " ) ;
_kernelNames . insert_at ( 0x2B , " FGets " ) ;
_kernelNames . insert_at ( 0x2C , " FClose " ) ;
// Function 0x55 is DoAvoider
_kernelNames [ 0x55 ] = " DoAvoider " ;
// Cut off unused functions
_kernelNames . resize ( 0x72 ) ;
break ;
2009-05-31 12:05:49 +00:00
2009-08-17 23:11:25 +00:00
case SCI_VERSION_01 :
// Multilingual SCI01 games have StrSplit as function 0x78
_kernelNames [ 0x78 ] = " StrSplit " ;
2009-05-31 12:05:49 +00:00
2009-08-17 23:11:25 +00:00
// Cut off unused functions
_kernelNames . resize ( 0x79 ) ;
break ;
2009-07-06 15:30:07 +00:00
2010-01-31 22:38:07 +00:00
case SCI_VERSION_1_LATE :
_kernelNames [ 0x71 ] = " MoveCursor " ;
break ;
2009-08-17 23:11:25 +00:00
case SCI_VERSION_1_1 :
2010-06-11 07:47:57 +00:00
// In SCI1.1, kSetSynonyms is an empty function
_kernelNames [ 0x26 ] = " Empty " ;
2010-06-10 23:16:32 +00:00
2010-06-25 16:16:29 +00:00
if ( g_sci - > getGameId ( ) = = GID_KQ6 ) {
2010-06-17 18:30:11 +00:00
// In the Windows version of KQ6 CD, the empty kSetSynonyms
// function has been replaced with kPortrait. In KQ6 Mac,
// kPlayBack has been replaced by kShowMovie.
2010-06-09 17:04:03 +00:00
if ( g_sci - > getPlatform ( ) = = Common : : kPlatformWindows )
2010-05-18 04:17:58 +00:00
_kernelNames [ 0x26 ] = " Portrait " ;
2010-06-09 17:04:03 +00:00
else if ( g_sci - > getPlatform ( ) = = Common : : kPlatformMacintosh )
_kernelNames [ 0x84 ] = " ShowMovie " ;
2010-06-25 16:16:29 +00:00
} else if ( g_sci - > getGameId ( ) = = GID_QFG4 & & g_sci - > isDemo ( ) ) {
2010-06-17 18:30:11 +00:00
_kernelNames [ 0x7b ] = " RemapColors " ; // QFG4 Demo has this SCI2 function instead of StrSplit
2010-05-18 04:17:58 +00:00
}
2009-08-31 18:42:07 +00:00
_kernelNames [ 0x71 ] = " PalVary " ;
2009-10-10 02:16:23 +00:00
_kernelNames [ 0x7c ] = " Message " ;
2009-08-17 23:11:25 +00:00
break ;
default :
// Use default table for the other versions
break ;
2009-07-06 15:30:07 +00:00
}
2009-05-31 12:05:49 +00:00
}
2010-06-09 18:42:21 +00:00
void Kernel : : loadKernelNames ( GameFeatures * features ) {
2009-05-31 12:05:49 +00:00
_kernelNames . clear ( ) ;
2010-01-25 01:39:44 +00:00
2009-08-25 23:02:57 +00:00
# ifdef ENABLE_SCI32
2009-09-23 10:55:35 +00:00
if ( getSciVersion ( ) > = SCI_VERSION_2_1 )
2010-06-09 18:42:21 +00:00
setKernelNamesSci21 ( features ) ;
2009-09-23 10:55:35 +00:00
else if ( getSciVersion ( ) = = SCI_VERSION_2 )
2009-08-27 01:39:30 +00:00
setKernelNamesSci2 ( ) ;
2009-08-25 23:02:57 +00:00
else
# endif
2010-06-09 10:45:54 +00:00
setDefaultKernelNames ( ) ;
2010-01-28 18:57:31 +00:00
mapFunctions ( ) ;
2009-05-31 12:05:49 +00:00
}
2010-05-18 12:16:48 +00:00
Common : : String Kernel : : lookupText ( reg_t address , int index ) {
char * seeker ;
Resource * textres ;
if ( address . segment )
return _segMan - > getString ( address ) ;
2010-06-10 15:25:54 +00:00
int textlen ;
int _index = index ;
textres = _resMan - > findResource ( ResourceId ( kResourceTypeText , address . offset ) , 0 ) ;
2010-05-18 12:16:48 +00:00
2010-06-10 15:25:54 +00:00
if ( ! textres ) {
error ( " text.%03d not found " , address . offset ) ;
return NULL ; /* Will probably segfault */
}
2010-05-18 12:16:48 +00:00
2010-06-10 15:25:54 +00:00
textlen = textres - > size ;
seeker = ( char * ) textres - > data ;
2010-05-18 12:16:48 +00:00
2010-06-10 15:25:54 +00:00
while ( index - - )
while ( ( textlen - - ) & & ( * seeker + + ) )
;
if ( textlen )
return seeker ;
error ( " Index %d out of bounds in text.%03d " , _index , address . offset ) ;
return NULL ;
2010-05-18 12:16:48 +00:00
}
2009-02-21 10:23:36 +00:00
} // End of namespace Sci