2009-05-20 17:51:55 +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 .
2014-02-18 02:34:24 +01:00
*
2009-05-20 17:51:55 +00:00
* 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 .
2014-02-18 02:34:24 +01:00
*
2009-05-20 17:51:55 +00:00
* 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 .
*
*/
2016-07-27 21:00:37 -05:00
# include "common/config-manager.h"
2020-04-19 23:46:13 -07:00
# include "common/savefile.h"
2009-05-20 17:51:55 +00:00
# include "common/system.h"
# include "sci/sci.h"
2009-06-04 11:28:05 +00:00
# include "sci/debug.h"
2009-12-04 17:38:24 +00:00
# include "sci/event.h"
2009-05-20 17:51:55 +00:00
# include "sci/engine/state.h"
# include "sci/engine/kernel.h"
# include "sci/engine/gc.h"
2020-04-19 23:46:13 -07:00
# ifdef ENABLE_SCI32
# include "sci/engine/guest_additions.h"
# endif
# include "sci/engine/savegame.h"
2011-02-06 00:05:27 +00:00
# include "sci/graphics/cursor.h"
2019-06-23 00:46:53 +02:00
# include "sci/graphics/palette.h"
2016-08-22 19:56:06 +03:00
# ifdef ENABLE_SCI32
# include "sci/graphics/cursor32.h"
2020-04-19 23:46:13 -07:00
# include "sci/graphics/frameout.h"
2016-08-22 19:56:06 +03:00
# endif
2010-05-24 17:21:11 +00:00
# include "sci/graphics/maciconbar.h"
2011-01-21 18:53:35 +00:00
# include "sci/console.h"
2019-07-08 08:55:45 +02:00
# ifdef ENABLE_SCI32
2019-07-07 22:25:24 +03:00
# include "sci/engine/hoyle5poker.h"
2019-07-08 08:55:45 +02:00
# endif
2009-05-20 17:51:55 +00:00
namespace Sci {
2019-01-05 20:08:47 +01:00
reg_t kRestartGame16 ( EngineState * s , int argc , reg_t * argv ) {
2010-05-23 16:44:36 +00:00
s - > shrinkStackToBase ( ) ;
2009-05-28 22:42:18 +00:00
2010-06-08 21:05:46 +00:00
s - > abortScriptProcessing = kAbortRestartGame ; // Force vm to abort ASAP
2009-05-20 17:51:55 +00:00
return NULL_REG ;
}
/* kGameIsRestarting():
* * Returns the restarting_flag in acc
*/
- 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
reg_t kGameIsRestarting ( EngineState * s , int argc , reg_t * argv ) {
2010-07-31 14:09:42 +00:00
s - > r_acc = make_reg ( 0 , s - > gameIsRestarting ) ;
2009-05-20 17:51:55 +00:00
if ( argc ) { // Only happens during replay
2009-06-07 15:53:30 +00:00
if ( ! argv [ 0 ] . toUint16 ( ) ) // Set restarting flag
2010-07-31 14:09:42 +00:00
s - > gameIsRestarting = GAMEISRESTARTING_NONE ;
2009-05-20 17:51:55 +00:00
}
2010-05-17 09:32:16 +00:00
uint32 neededSleep = 30 ;
2011-09-24 01:31:18 +03:00
// WORKAROUNDS for scripts that are polling too quickly in scenes that
// are not animating much
2010-07-30 21:29:45 +00:00
switch ( g_sci - > getGameId ( ) ) {
2011-09-24 01:31:18 +03:00
case GID_CASTLEBRAIN :
// In Castle of Dr. Brain, memory color matching puzzle in the first
// room (room 100), the game scripts constantly poll the state of each
// stone when the user clicks on one. Since the scene is not animating
// much, this results in activating and deactivating each stone very
// quickly (together with its associated tone sound), depending on how
// low it is in the animate list. This worked somewhat in older PCs, but
// not in modern computers. We throttle the scene in order to allow the
// stones to display, otherwise the game scripts reset them too soon.
// Fixes bug #3127824.
if ( s - > currentRoomNumber ( ) = = 100 ) {
s - > _throttleTrigger = true ;
neededSleep = 60 ;
}
break ;
case GID_ICEMAN :
// In ICEMAN the submarine control room is not animating much, so it
// runs way too fast. We calm it down even more, otherwise fighting
// against other submarines is almost impossible.
if ( s - > currentRoomNumber ( ) = = 27 ) {
s - > _throttleTrigger = true ;
neededSleep = 60 ;
}
break ;
2010-07-30 21:29:45 +00:00
case GID_LSL3 :
// LSL3 calculates a machinespeed variable during game startup
// (right after the filthy questions). This one would go through w/o
// throttling resulting in having to do 1000 pushups or something. Another
// way of handling this would be delaying incrementing of "machineSpeed"
// selector.
if ( s - > currentRoomNumber ( ) = = 290 )
s - > _throttleTrigger = true ;
break ;
2010-11-20 00:52:05 +00:00
case GID_SQ4 :
2011-06-20 00:59:48 +02:00
// In SQ4 (floppy and CD) the sequel police appear way too quickly in
2010-11-20 00:52:05 +00:00
// the Skate-o-rama rooms, resulting in all sorts of timer issues, like
// #3109139 (which occurs because a police officer instantly teleports
// just before Roger exits and shoots him). We throttle these scenes a
2011-09-24 01:31:18 +03:00
// bit more, in order to prevent timer bugs related to the sequel police.
2010-11-20 00:52:05 +00:00
if ( s - > currentRoomNumber ( ) = = 405 | | s - > currentRoomNumber ( ) = = 406 | |
s - > currentRoomNumber ( ) = = 410 | | s - > currentRoomNumber ( ) = = 411 ) {
s - > _throttleTrigger = true ;
neededSleep = 60 ;
}
2010-07-30 21:29:45 +00:00
default :
break ;
2010-05-17 09:32:16 +00:00
}
2010-01-17 20:17:00 +00:00
2010-07-10 22:27:28 +00:00
s - > speedThrottler ( neededSleep ) ;
2009-05-20 17:51:55 +00:00
return s - > r_acc ;
}
- 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
reg_t kHaveMouse ( EngineState * s , int argc , reg_t * argv ) {
2009-09-30 23:00:03 +00:00
return SIGNAL_REG ;
2009-05-20 17:51:55 +00:00
}
2009-08-20 21:18:52 +00:00
enum kMemoryInfoFunc {
K_MEMORYINFO_LARGEST_HEAP_BLOCK = 0 , // Largest heap block available
K_MEMORYINFO_FREE_HEAP = 1 , // Total free heap memory
K_MEMORYINFO_LARGEST_HUNK_BLOCK = 2 , // Largest available hunk memory block
K_MEMORYINFO_FREE_HUNK = 3 , // Amount of free DOS paragraphs
K_MEMORYINFO_TOTAL_HUNK = 4 // Total amount of hunk memory (SCI01)
} ;
- 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
reg_t kMemoryInfo ( EngineState * s , int argc , reg_t * argv ) {
2010-06-23 17:30:18 +00:00
// The free heap size returned must not be 0xffff, or some memory
// calculations will overflow. Crazy Nick's games handle up to 32746
// bytes (0x7fea), otherwise they throw a warning that the memory is
// fragmented
const uint16 size = 0x7fea ;
2009-08-20 21:18:52 +00:00
2012-06-18 05:21:59 +03:00
switch ( argv [ 0 ] . getOffset ( ) ) {
2009-08-20 21:18:52 +00:00
case K_MEMORYINFO_LARGEST_HEAP_BLOCK :
// In order to prevent "Memory fragmented" dialogs from
// popping up in some games, we must return FREE_HEAP - 2 here.
return make_reg ( 0 , size - 2 ) ;
case K_MEMORYINFO_FREE_HEAP :
case K_MEMORYINFO_LARGEST_HUNK_BLOCK :
case K_MEMORYINFO_FREE_HUNK :
case K_MEMORYINFO_TOTAL_HUNK :
return make_reg ( 0 , size ) ;
2009-05-20 17:51:55 +00:00
default :
2012-06-18 05:21:59 +03:00
error ( " Unknown MemoryInfo operation: %04x " , argv [ 0 ] . getOffset ( ) ) ;
2009-05-20 17:51:55 +00:00
}
return NULL_REG ;
}
2010-01-31 19:47:54 +00:00
enum kMemorySegmentFunc {
K_MEMORYSEGMENT_SAVE_DATA = 0 ,
K_MEMORYSEGMENT_RESTORE_DATA = 1
} ;
reg_t kMemorySegment ( EngineState * s , int argc , reg_t * argv ) {
// MemorySegment provides access to a 256-byte block of memory that remains
// intact across restarts and restores
switch ( argv [ 0 ] . toUint16 ( ) ) {
case K_MEMORYSEGMENT_SAVE_DATA : {
if ( argc < 3 )
error ( " Insufficient number of arguments passed to MemorySegment " ) ;
uint16 size = argv [ 2 ] . toUint16 ( ) ;
if ( ! size )
size = s - > _segMan - > strlen ( argv [ 1 ] ) + 1 ;
2011-03-27 18:11:26 +03:00
if ( size > EngineState : : kMemorySegmentMax ) {
// This was set to cut the block to 256 bytes. This should be an
// error, as we won't restore the full block that the game scripts
// request, thus error out instead.
//size = EngineState::kMemorySegmentMax;
error ( " kMemorySegment: Requested to save more than 256 bytes (%d) " , size ) ;
}
2010-01-31 19:47:54 +00:00
s - > _memorySegmentSize = size ;
// We assume that this won't be called on pointers
s - > _segMan - > memcpy ( s - > _memorySegment , argv [ 1 ] , size ) ;
break ;
}
case K_MEMORYSEGMENT_RESTORE_DATA :
s - > _segMan - > memcpy ( argv [ 1 ] , s - > _memorySegment , s - > _memorySegmentSize ) ;
break ;
default :
error ( " Unknown MemorySegment operation %04x " , argv [ 0 ] . toUint16 ( ) ) ;
}
return argv [ 1 ] ;
}
- 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
reg_t kFlushResources ( EngineState * s , int argc , reg_t * argv ) {
2010-02-06 19:41:55 +00:00
run_gc ( s ) ;
2011-01-01 12:48:12 +00:00
debugC ( kDebugLevelRoom , " Entering room number %d " , argv [ 0 ] . toUint16 ( ) ) ;
2009-05-20 17:51:55 +00:00
return s - > r_acc ;
}
- 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
reg_t kSetDebug ( EngineState * s , int argc , reg_t * argv ) {
2011-01-21 19:56:23 +00:00
// WORKAROUND: For some reason, GK1 calls this unconditionally when
// watching the intro. Older (SCI0) games call it on room change if
// a flag is set, in which case the debugger SHOULD get activated.
// Therefore, don't break into the debugger in GK1, but do so elsewhere.
2011-01-21 19:33:36 +00:00
if ( g_sci - > getGameId ( ) ! = GID_GK1 ) {
debug ( " Debug mode activated " ) ;
2011-06-20 00:59:48 +02:00
2011-01-21 19:33:36 +00:00
g_sci - > getDebugger ( ) - > attach ( ) ;
}
2009-05-20 17:51:55 +00:00
return s - > r_acc ;
}
2009-05-20 17:52:12 +00:00
enum {
2010-07-31 14:29:22 +00:00
KGETTIME_TICKS = 0 ,
KGETTIME_TIME_12HOUR = 1 ,
KGETTIME_TIME_24HOUR = 2 ,
KGETTIME_DATE = 3
2009-05-20 17:52:12 +00:00
} ;
2009-05-20 17:51:55 +00:00
- 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
reg_t kGetTime ( EngineState * s , int argc , reg_t * argv ) {
2009-10-08 19:41:38 +00:00
TimeDate loc_time ;
2009-05-20 17:51:55 +00:00
int retval = 0 ; // Avoid spurious warning
g_system - > getTimeAndDate ( loc_time ) ;
2009-06-07 16:50:34 +00:00
int mode = ( argc > 0 ) ? argv [ 0 ] . toUint16 ( ) : 0 ;
2009-05-20 17:51:55 +00:00
2010-10-08 18:33:54 +00:00
// Modes 2 and 3 are supported since 0.629.
// This condition doesn't check that exactly, but close enough.
if ( getSciVersion ( ) = = SCI_VERSION_0_EARLY & & mode > 1 )
2010-06-28 12:29:06 +00:00
error ( " kGetTime called in SCI0 with mode %d (expected 0 or 1) " , mode ) ;
2009-10-09 23:15:54 +00:00
2009-05-20 17:51:55 +00:00
switch ( mode ) {
2010-07-31 14:29:22 +00:00
case KGETTIME_TICKS :
2016-01-14 10:54:27 -06:00
retval = g_sci - > getTickCount ( ) ;
2011-01-01 12:48:12 +00:00
debugC ( kDebugLevelTime , " GetTime(elapsed) returns %d " , retval ) ;
2009-05-20 17:51:55 +00:00
break ;
2010-07-31 14:29:22 +00:00
case KGETTIME_TIME_12HOUR :
2009-05-21 10:34:13 +00:00
retval = ( ( loc_time . tm_hour % 12 ) < < 12 ) | ( loc_time . tm_min < < 6 ) | ( loc_time . tm_sec ) ;
2011-01-01 12:48:12 +00:00
debugC ( kDebugLevelTime , " GetTime(12h) returns %d " , retval ) ;
2009-05-20 17:51:55 +00:00
break ;
2010-07-31 14:29:22 +00:00
case KGETTIME_TIME_24HOUR :
2009-05-21 10:34:13 +00:00
retval = ( loc_time . tm_hour < < 11 ) | ( loc_time . tm_min < < 5 ) | ( loc_time . tm_sec > > 1 ) ;
2011-01-01 12:48:12 +00:00
debugC ( kDebugLevelTime , " GetTime(24h) returns %d " , retval ) ;
2009-05-20 17:51:55 +00:00
break ;
2010-07-31 14:29:22 +00:00
case KGETTIME_DATE :
2016-04-14 21:17:49 +03:00
{
// SCI0 late: Year since 1920 (0 = 1920, 1 = 1921, etc)
// SCI01 and newer: Year since 1980 (0 = 1980, 1 = 1981, etc)
// Atari ST SCI0 late versions use the newer base year.
int baseYear = 80 ;
if ( getSciVersion ( ) = = SCI_VERSION_0_LATE & & g_sci - > getPlatform ( ) = = Common : : kPlatformDOS ) {
baseYear = 20 ;
}
retval = loc_time . tm_mday | ( ( loc_time . tm_mon + 1 ) < < 5 ) | ( ( ( loc_time . tm_year - baseYear ) & 0x7f ) < < 9 ) ;
2011-01-01 12:48:12 +00:00
debugC ( kDebugLevelTime , " GetTime(date) returns %d " , retval ) ;
2009-05-20 17:51:55 +00:00
break ;
2016-04-14 21:17:49 +03:00
}
2009-05-20 17:51:55 +00:00
default :
2010-06-28 12:29:06 +00:00
error ( " Attempt to use unknown GetTime mode %d " , mode ) ;
2009-05-20 17:51:55 +00:00
break ;
}
return make_reg ( 0 , retval ) ;
}
2009-05-20 17:52:12 +00:00
enum {
K_MEMORY_ALLOCATE_CRITICAL = 1 ,
K_MEMORY_ALLOCATE_NONCRITICAL = 2 ,
K_MEMORY_FREE = 3 ,
K_MEMORY_MEMCPY = 4 ,
K_MEMORY_PEEK = 5 ,
K_MEMORY_POKE = 6
} ;
2009-05-20 17:51:55 +00:00
- 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
reg_t kMemory ( EngineState * s , int argc , reg_t * argv ) {
2009-06-07 15:53:30 +00:00
switch ( argv [ 0 ] . toUint16 ( ) ) {
2010-08-03 13:17:30 +00:00
case K_MEMORY_ALLOCATE_CRITICAL : {
int byteCount = argv [ 1 ] . toUint16 ( ) ;
2016-02-08 21:12:37 +01:00
// Sierra themselves allocated at least 2 bytes more than requested.
// Probably as a safety margin. And they also made size even.
//
// This behavior is required by at least these:
2010-10-23 20:22:24 +00:00
// - pq3 (multilingual) room 202
// when plotting crimes, allocates the returned bytes from kStrLen
// on "W" and "E" and wants to put a string in there, which doesn't
// fit of course.
// - lsl5 (multilingual) room 280
// allocates memory according to a previous kStrLen for the name of
// the airport ladies (bug #3093818), which isn't enough
2016-02-08 21:12:37 +01:00
byteCount + = 2 + ( byteCount & 1 ) ;
2010-10-23 20:22:24 +00:00
2010-08-03 13:17:30 +00:00
if ( ! s - > _segMan - > allocDynmem ( byteCount , " kMemory() critical " , & s - > r_acc ) ) {
2009-05-27 00:24:32 +00:00
error ( " Critical heap allocation failed " ) ;
2009-05-20 17:51:55 +00:00
}
break ;
2010-08-03 13:17:30 +00:00
}
2016-02-08 21:12:37 +01:00
case K_MEMORY_ALLOCATE_NONCRITICAL : {
int byteCount = argv [ 1 ] . toUint16 ( ) ;
// See above
byteCount + = 2 + ( byteCount & 1 ) ;
s - > _segMan - > allocDynmem ( byteCount , " kMemory() non-critical " , & s - > r_acc ) ;
2009-05-20 17:51:55 +00:00
break ;
2016-02-08 21:12:37 +01:00
}
2009-05-20 17:51:55 +00:00
case K_MEMORY_FREE :
2010-08-01 11:10:14 +00:00
if ( ! s - > _segMan - > freeDynmem ( argv [ 1 ] ) ) {
if ( g_sci - > getGameId ( ) = = GID_QFG1VGA ) {
// Ignore script bug in QFG1VGA, when closing any conversation dialog with esc
} else {
// Usually, the result of a script bug. Non-critical
warning ( " Attempt to kMemory::free() non-dynmem pointer %04x:%04x " , PRINT_REG ( argv [ 1 ] ) ) ;
}
2009-05-20 17:51:55 +00:00
}
break ;
case K_MEMORY_MEMCPY : {
2009-06-07 15:53:30 +00:00
int size = argv [ 3 ] . toUint16 ( ) ;
2009-10-04 18:38:18 +00:00
s - > _segMan - > memcpy ( argv [ 1 ] , argv [ 2 ] , size ) ;
2009-05-20 17:51:55 +00:00
break ;
}
case K_MEMORY_PEEK : {
2012-06-18 05:21:59 +03:00
if ( ! argv [ 1 ] . getSegment ( ) ) {
2010-05-28 16:47:30 +00:00
// This occurs in KQ5CD when interacting with certain objects
warning ( " Attempt to peek invalid memory at %04x:%04x " , PRINT_REG ( argv [ 1 ] ) ) ;
return s - > r_acc ;
}
2009-10-04 18:38:18 +00:00
SegmentRef ref = s - > _segMan - > dereference ( argv [ 1 ] ) ;
2009-05-20 17:51:55 +00:00
2009-09-27 01:50:26 +00:00
if ( ! ref . isValid ( ) | | ref . maxSize < 2 ) {
2010-06-28 12:29:06 +00:00
error ( " Attempt to peek invalid memory at %04x:%04x " , PRINT_REG ( argv [ 1 ] ) ) ;
2009-05-20 17:51:55 +00:00
return s - > r_acc ;
}
2011-03-04 21:51:55 +01:00
if ( ref . isRaw )
return make_reg ( 0 , ( int16 ) READ_SCIENDIAN_UINT16 ( ref . raw ) ) ;
else {
2010-01-26 19:51:08 +00:00
if ( ref . skipByte )
error ( " Attempt to peek memory at odd offset %04X:%04X " , PRINT_REG ( argv [ 1 ] ) ) ;
2009-09-27 01:50:26 +00:00
return * ( ref . reg ) ;
2010-01-26 19:51:08 +00:00
}
2009-05-20 17:51:55 +00:00
break ;
}
case K_MEMORY_POKE : {
2009-10-04 18:38:18 +00:00
SegmentRef ref = s - > _segMan - > dereference ( argv [ 1 ] ) ;
2009-05-20 17:51:55 +00:00
2009-09-27 01:50:26 +00:00
if ( ! ref . isValid ( ) | | ref . maxSize < 2 ) {
2010-06-28 12:29:06 +00:00
error ( " Attempt to poke invalid memory at %04x:%04x " , PRINT_REG ( argv [ 1 ] ) ) ;
2009-05-20 17:51:55 +00:00
return s - > r_acc ;
}
2009-09-27 01:50:26 +00:00
if ( ref . isRaw ) {
2012-06-18 05:21:59 +03:00
if ( argv [ 2 ] . getSegment ( ) ) {
2009-05-27 00:24:32 +00:00
error ( " Attempt to poke memory reference %04x:%04x to %04x:%04x " , PRINT_REG ( argv [ 2 ] ) , PRINT_REG ( argv [ 1 ] ) ) ;
2009-05-20 17:51:55 +00:00
return s - > r_acc ;
}
2012-06-18 05:21:59 +03:00
WRITE_SCIENDIAN_UINT16 ( ref . raw , argv [ 2 ] . getOffset ( ) ) ; // Amiga versions are BE
2010-01-26 19:51:08 +00:00
} else {
if ( ref . skipByte )
error ( " Attempt to poke memory at odd offset %04X:%04X " , PRINT_REG ( argv [ 1 ] ) ) ;
2009-09-27 01:50:26 +00:00
* ( ref . reg ) = argv [ 2 ] ;
2010-01-26 19:51:08 +00:00
}
2009-05-20 17:51:55 +00:00
break ;
}
2019-12-01 05:06:31 +00:00
default :
break ;
2009-05-20 17:51:55 +00:00
}
return s - > r_acc ;
}
2011-02-06 00:05:27 +00:00
# ifdef ENABLE_SCI32
reg_t kGetConfig ( EngineState * s , int argc , reg_t * argv ) {
Common : : String setting = s - > _segMan - > getString ( argv [ 0 ] ) ;
reg_t data = readSelector ( s - > _segMan , argv [ 1 ] , SELECTOR ( data ) ) ;
2012-05-26 16:41:11 +03:00
// This function is used to get the benchmarked results stored in the
// resource.cfg configuration file in Phantasmagoria 1. Normally,
// the configuration file contains values stored by the installer
// regarding audio and video settings, which are then used by the
// executable. In Phantasmagoria, two extra executable files are used
// to perform system benchmarks:
// - CPUID for the CPU benchmarks, sets the cpu and cpuspeed settings
// - HDDTEC for the graphics and CD-ROM benchmarks, sets the videospeed setting
//
// These settings are then used by the game scripts directly to modify
// the game speed and graphics output. The result of this call is stored
// in global 178. The scripts check these values against the value 425.
// Anything below that makes Phantasmagoria awfully sluggish, so we're
// setting everything to 500, which makes the game playable.
2012-05-30 18:43:39 +02:00
setting . toLowercase ( ) ;
2012-05-26 16:41:11 +03:00
if ( setting = = " videospeed " ) {
s - > _segMan - > strcpy ( data , " 500 " ) ;
} else if ( setting = = " cpu " ) {
// We always return the fastest CPU setting that CPUID can detect
// (i.e. 586).
s - > _segMan - > strcpy ( data , " 586 " ) ;
} else if ( setting = = " cpuspeed " ) {
s - > _segMan - > strcpy ( data , " 500 " ) ;
2012-06-02 18:50:46 +02:00
} else if ( setting = = " language " ) {
Common : : String languageId = Common : : String : : format ( " %d " , g_sci - > getSciLanguage ( ) ) ;
s - > _segMan - > strcpy ( data , languageId . c_str ( ) ) ;
2012-06-13 12:26:13 +03:00
} else if ( setting = = " torindebug " ) {
// Used to enable the debug mode in Torin's Passage (French).
// If true, the debug mode is enabled.
s - > _segMan - > strcpy ( data , " " ) ;
2012-06-14 12:10:39 +03:00
} else if ( setting = = " leakdump " ) {
// An unknown setting in LSL7. Likely used for debugging.
s - > _segMan - > strcpy ( data , " " ) ;
} else if ( setting = = " startroom " ) {
// Debug setting in LSL7, specifies the room to start from.
s - > _segMan - > strcpy ( data , " " ) ;
2016-07-11 13:02:05 -05:00
} else if ( setting = = " game " ) {
2016-07-23 11:17:06 +03:00
// Hoyle 5 startup, specifies the number of the game to start.
2018-10-23 01:32:26 +03:00
if ( g_sci - > getGameId ( ) = = GID_HOYLE5 & &
! g_sci - > getResMan ( ) - > testResource ( ResourceId ( kResourceTypeScript , 100 ) ) & &
g_sci - > getResMan ( ) - > testResource ( ResourceId ( kResourceTypeScript , 700 ) ) ) {
// Special case for Hoyle 5 Bridge: only one game is included (Bridge),
// so mimic the setting in 700.cfg and set the starting room number to 700.
s - > _segMan - > strcpy ( data , " 700 " ) ;
} else {
s - > _segMan - > strcpy ( data , " " ) ;
}
2016-07-23 11:17:06 +03:00
} else if ( setting = = " laptop " ) {
// Hoyle 5 startup.
s - > _segMan - > strcpy ( data , " " ) ;
} else if ( setting = = " jumpto " ) {
// Hoyle 5 startup.
2016-07-11 13:02:05 -05:00
s - > _segMan - > strcpy ( data , " " ) ;
2018-08-20 04:35:05 +03:00
} else if ( setting = = " klonchtsee " ) {
// Hoyle 5 - starting Solitaire.
s - > _segMan - > strcpy ( data , " " ) ;
} else if ( setting = = " klonchtarr " ) {
// Hoyle 5 - starting Solitaire.
s - > _segMan - > strcpy ( data , " " ) ;
2017-07-24 00:03:03 -05:00
} else if ( setting = = " deflang " ) {
// MGDX 4-language startup.
s - > _segMan - > strcpy ( data , " " ) ;
2012-05-26 16:41:11 +03:00
} else {
error ( " GetConfig: Unknown configuration setting %s " , setting . c_str ( ) ) ;
}
2011-02-06 00:05:27 +00:00
return argv [ 1 ] ;
}
2012-05-26 16:41:11 +03:00
2012-06-09 16:29:14 +03:00
// Likely modelled after the Windows 3.1 function GetPrivateProfileInt:
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms724345%28v=vs.85%29.aspx
2012-05-26 16:41:11 +03:00
reg_t kGetSierraProfileInt ( EngineState * s , int argc , reg_t * argv ) {
2017-08-04 00:42:02 -05:00
if ( g_sci - > getPlatform ( ) ! = Common : : kPlatformWindows ) {
return s - > r_acc ;
}
2012-05-26 16:41:11 +03:00
Common : : String category = s - > _segMan - > getString ( argv [ 0 ] ) ; // always "config"
2012-05-30 18:43:39 +02:00
category . toLowercase ( ) ;
2012-05-26 16:41:11 +03:00
Common : : String setting = s - > _segMan - > getString ( argv [ 1 ] ) ;
2012-05-30 18:43:39 +02:00
setting . toLowercase ( ) ;
2012-06-11 20:28:28 +03:00
// The third parameter is the default value returned if the configuration key is missing
2012-05-26 16:41:11 +03:00
2012-06-11 20:28:28 +03:00
if ( category = = " config " & & setting = = " videospeed " ) {
// We return the same fake value for videospeed as with kGetConfig
return make_reg ( 0 , 500 ) ;
}
2012-05-26 16:41:11 +03:00
2012-06-11 20:28:28 +03:00
warning ( " kGetSierraProfileInt: Returning default value %d for unknown setting %s.%s " , argv [ 2 ] . toSint16 ( ) , category . c_str ( ) , setting . c_str ( ) ) ;
return argv [ 2 ] ;
2012-05-26 16:41:11 +03:00
}
2012-07-03 18:11:41 +03:00
reg_t kGetWindowsOption ( EngineState * s , int argc , reg_t * argv ) {
uint16 windowsOption = argv [ 0 ] . toUint16 ( ) ;
switch ( windowsOption ) {
case 0 :
// Title bar on/off in Phantasmagoria, we return 0 (off)
return NULL_REG ;
default :
warning ( " GetWindowsOption: Unknown option %d " , windowsOption ) ;
return NULL_REG ;
}
}
2016-09-20 21:06:16 -05:00
extern Common : : String format ( const Common : : String & source , int argc , const reg_t * argv ) ;
reg_t kPrintDebug ( EngineState * s , int argc , reg_t * argv ) {
const Common : : String debugString = s - > _segMan - > getString ( argv [ 0 ] ) ;
debugC ( kDebugLevelGame , " %s " , format ( debugString , argc - 1 , argv + 1 ) . c_str ( ) ) ;
return s - > r_acc ;
}
2011-02-06 00:05:27 +00:00
# endif
// kIconBar is really a subop of kMacPlatform for SCI1.1 Mac
2010-05-18 04:17:58 +00:00
reg_t kIconBar ( EngineState * s , int argc , reg_t * argv ) {
2011-02-06 00:05:27 +00:00
// Mac versions use their own tertiary platform functions
// to handle the outside-of-the-screen icon bar.
2011-02-03 02:26:57 +00:00
// QFG1 Mac calls this function to load the Mac icon bar (of which
// the resources do exist), but the game completely ignores it and
// uses the standard icon bar for the game. We do the same.
if ( ! g_sci - > hasMacIconBar ( ) )
return NULL_REG ;
2011-02-06 00:05:27 +00:00
switch ( argv [ 0 ] . toUint16 ( ) ) {
2011-02-15 11:02:01 -05:00
case 0 : // InitIconBar
2019-03-25 01:28:13 -07:00
g_sci - > _gfxMacIconBar - > initIcons ( argv [ 1 ] . toUint16 ( ) , & argv [ 2 ] ) ;
2011-02-15 11:02:01 -05:00
break ;
case 1 : // DisposeIconBar
warning ( " kIconBar(Dispose) " ) ;
break ;
2011-03-09 20:50:11 +01:00
case 2 : // EnableIconBar (-1 = all)
debug ( 0 , " kIconBar(Enable, %i) " , argv [ 1 ] . toSint16 ( ) ) ;
g_sci - > _gfxMacIconBar - > setIconEnabled ( argv [ 1 ] . toSint16 ( ) , true ) ;
2011-02-15 11:02:01 -05:00
break ;
2011-03-09 20:50:11 +01:00
case 3 : // DisableIconBar (-1 = all)
debug ( 0 , " kIconBar(Disable, %i) " , argv [ 1 ] . toSint16 ( ) ) ;
g_sci - > _gfxMacIconBar - > setIconEnabled ( argv [ 1 ] . toSint16 ( ) , false ) ;
2011-02-06 00:05:27 +00:00
break ;
2011-02-15 11:02:01 -05:00
case 4 : // SetIconBarIcon
2011-03-09 20:50:11 +01:00
debug ( 0 , " kIconBar(SetIcon, %d, %d) " , argv [ 1 ] . toUint16 ( ) , argv [ 2 ] . toUint16 ( ) ) ;
if ( argv [ 2 ] . toSint16 ( ) = = - 1 )
g_sci - > _gfxMacIconBar - > setInventoryIcon ( argv [ 2 ] . toSint16 ( ) ) ;
2011-02-06 00:05:27 +00:00
break ;
default :
2011-02-15 11:02:01 -05:00
error ( " Unknown kIconBar(%d) " , argv [ 0 ] . toUint16 ( ) ) ;
2010-05-24 17:21:11 +00:00
}
2010-05-18 04:17:58 +00:00
2011-02-20 12:35:15 -05:00
g_sci - > _gfxMacIconBar - > drawIcons ( ) ;
2010-05-18 04:17:58 +00:00
return NULL_REG ;
}
2011-02-06 00:05:27 +00:00
// kMacPlatform is really a subop of kPlatform for SCI1.1+ Mac
reg_t kMacPlatform ( EngineState * s , int argc , reg_t * argv ) {
// Mac versions use their own secondary platform functions
// to do various things. Why didn't they just declare a new
// kernel function?
2010-11-19 12:46:36 +00:00
2011-02-06 00:05:27 +00:00
switch ( argv [ 0 ] . toUint16 ( ) ) {
case 0 :
2011-02-15 11:02:01 -05:00
// Subop 0 has changed a few times
// In SCI1, its usage is still unknown
// In SCI1.1, it's NOP
2016-08-23 01:42:51 +03:00
if ( getSciVersion ( ) ! = SCI_VERSION_1_1 )
2011-02-15 11:02:01 -05:00
warning ( " Unknown SCI1 kMacPlatform(0) call " ) ;
2011-02-06 00:05:27 +00:00
break ;
2011-02-15 11:02:01 -05:00
case 4 : // Handle icon bar code
2011-02-06 00:05:27 +00:00
return kIconBar ( s , argc - 1 , argv + 1 ) ;
2011-02-15 11:02:01 -05:00
case 7 : // Unknown, but always return -1
return SIGNAL_REG ;
2011-04-15 11:13:35 +03:00
case 1 : // Unknown, calls QuickDraw region functions (KQ5, QFG1VGA, Dr. Brain 1)
break ; // removed warning, as it produces a lot of spam in the console
2011-02-15 11:02:01 -05:00
case 2 : // Unknown, "UseNextWaitEvent" (Various)
case 3 : // Unknown, "ProcessOpenDocuments" (Various)
2020-01-30 17:13:19 -08:00
case 5 : // Unknown
2011-02-15 11:02:01 -05:00
case 6 : // Unknown, menu-related (Unused?)
warning ( " Unhandled kMacPlatform(%d) " , argv [ 0 ] . toUint16 ( ) ) ;
break ;
2011-02-06 00:05:27 +00:00
default :
2011-02-15 11:02:01 -05:00
error ( " Unknown kMacPlatform(%d) " , argv [ 0 ] . toUint16 ( ) ) ;
2011-02-06 00:05:27 +00:00
}
return s - > r_acc ;
2010-11-19 12:46:36 +00:00
}
2010-11-19 14:19:02 +00:00
2020-01-30 17:13:19 -08:00
# ifdef ENABLE_SCI32
2020-04-19 23:46:13 -07:00
// kMacKq7InitializeSave is a subop of kMacPlatform32.
// KQ7 Mac would display a native Save dialog with the prompt "Who's game?"
// and store the result in a global variable inside the interpreter
// for subsequent calls to kMacKq7SaveGame.
reg_t kMacKq7InitializeSave ( EngineState * s ) {
s - > _kq7MacSaveGameId = g_sci - > _guestAdditions - > runSaveRestore ( true , s - > _kq7MacSaveGameDescription ) ;
s - > _kq7MacSaveGameId = shiftSciToScummVMSaveId ( s - > _kq7MacSaveGameId ) ;
return ( s - > _kq7MacSaveGameId ! = - 1 ) ? TRUE_REG : NULL_REG ;
}
// kMacKq7SaveGame is a subop of kMacPlatform32.
// Saves the game using the current save id and description that's set
// when initializing or restoring a saved game.
reg_t kMacKq7SaveGame ( EngineState * s ) {
if ( s - > _kq7MacSaveGameId = = - 1 ) {
error ( " kMacKq7SaveGame: save game hasn't been initialized " ) ;
}
const reg_t version = s - > variables [ VAR_GLOBAL ] [ kGlobalVarVersion ] ;
const Common : : String versionString = s - > _segMan - > getString ( version ) ;
if ( gamestate_save ( s , s - > _kq7MacSaveGameId , s - > _kq7MacSaveGameDescription , versionString ) ) {
return TRUE_REG ;
}
return NULL_REG ;
}
// kMacKq7RestoreGame is a subop of kMacPlatform32.
// KQ7 Mac would display a native Open dialog with the prompt "Who's game?"
// and store the result in a global variable inside the interpreter to
// use in subsequent calls to kMacKq7SaveGame before restoring.
reg_t kMacKq7RestoreGame ( EngineState * s ) {
s - > _kq7MacSaveGameId = g_sci - > _guestAdditions - > runSaveRestore ( false , s - > _kq7MacSaveGameDescription ) ;
s - > _kq7MacSaveGameId = shiftSciToScummVMSaveId ( s - > _kq7MacSaveGameId ) ;
if ( s - > _kq7MacSaveGameId = = - 1 ) {
return NULL_REG ;
}
// gamestate_restore() resets s->_kq7MacSaveGameId and
// s->_kq7MacSaveGameDescription so save and restore them.
int kq7MacSaveGameId = s - > _kq7MacSaveGameId ;
Common : : String kq7MacSaveGameDescription = s - > _kq7MacSaveGameDescription ;
bool success = gamestate_restore ( s , s - > _kq7MacSaveGameId ) ;
s - > _kq7MacSaveGameId = kq7MacSaveGameId ;
s - > _kq7MacSaveGameDescription = kq7MacSaveGameDescription ;
return success ? TRUE_REG : NULL_REG ;
}
2020-05-05 14:49:11 -07:00
// kMacInitializeSave is a subop of kMacPlatform32.
reg_t kMacInitializeSave ( EngineState * s , int argc , reg_t * argv ) {
2020-04-19 23:46:13 -07:00
return TRUE_REG ; // NULL_REG if i/o errors
}
2020-05-05 14:49:11 -07:00
// kMacSaveGame is a subop of kMacPlatform32.
reg_t kMacSaveGame ( EngineState * s , int argc , reg_t * argv ) {
2020-04-19 23:46:13 -07:00
g_sci - > _gfxFrameout - > kernelFrameOut ( true ) ; // see kSaveGame32
const int saveId = shiftSciToScummVMSaveId ( argv [ 1 ] . toUint16 ( ) ) ;
const Common : : String description = s - > _segMan - > getString ( argv [ 2 ] ) ;
const reg_t version = s - > variables [ VAR_GLOBAL ] [ kGlobalVarVersion ] ;
const Common : : String versionString = s - > _segMan - > getString ( version ) ;
if ( gamestate_save ( s , saveId , description , versionString ) ) {
return TRUE_REG ;
}
return NULL_REG ;
}
2020-05-05 14:49:11 -07:00
// kMacRestoreGame is a subop of kMacPlatform32.
reg_t kMacRestoreGame ( EngineState * s , int argc , reg_t * argv ) {
2020-04-19 23:46:13 -07:00
const int saveId = shiftSciToScummVMSaveId ( argv [ 1 ] . toUint16 ( ) ) ;
if ( gamestate_restore ( s , saveId ) ) {
return TRUE_REG ;
}
return NULL_REG ;
}
2020-01-30 17:13:19 -08:00
reg_t kMacPlatform32 ( EngineState * s , int argc , reg_t * argv ) {
switch ( argv [ 0 ] . toUint16 ( ) ) {
case 0 : // build cursor view map
g_sci - > _gfxCursor32 - > setMacCursorRemapList ( argc - 1 , argv + 1 ) ;
2020-04-19 23:46:13 -07:00
return s - > r_acc ;
2020-01-30 17:13:19 -08:00
case 1 : // compact/purge mac memory
case 2 : // hands-off/hands-on for mac menus
2020-04-19 23:46:13 -07:00
return s - > r_acc ;
2020-01-30 17:13:19 -08:00
2020-04-19 23:46:13 -07:00
// Subops 3-5 are used for custom saving and restoring but they
// changed completely between each game that uses them.
//
// KQ7: 3-5 with no parameters
// Shivers: 3-5 with parameters
// Lighthouse: 3 with sub-subops: -1, 0, and 1 (TODO)
case 3 :
if ( argc = = 1 ) {
return kMacKq7InitializeSave ( s ) ;
} else if ( argc = = 3 ) {
2020-05-05 14:49:11 -07:00
return kMacInitializeSave ( s , argc - 1 , argv + 1 ) ;
2020-04-19 23:46:13 -07:00
}
break ;
case 4 :
if ( argc = = 1 ) {
return kMacKq7SaveGame ( s ) ;
} else if ( argc = = 4 ) {
2020-05-05 14:49:11 -07:00
return kMacSaveGame ( s , argc - 1 , argv + 1 ) ;
2020-04-19 23:46:13 -07:00
}
break ;
case 5 :
if ( argc = = 1 ) {
return kMacKq7RestoreGame ( s ) ;
} else if ( argc = = 3 ) {
2020-05-05 14:49:11 -07:00
return kMacRestoreGame ( s , argc - 1 , argv + 1 ) ;
2020-04-19 23:46:13 -07:00
}
2020-01-30 17:13:19 -08:00
break ;
2020-05-05 14:49:11 -07:00
// Subops 6-11 are used for saving and restoring by Mother Goose only.
2020-01-30 17:13:19 -08:00
case 6 :
2020-05-05 14:49:11 -07:00
return kMacInitializeSave ( s , argc - 1 , argv + 1 ) ;
2020-01-30 17:13:19 -08:00
case 7 :
2020-05-05 14:49:11 -07:00
return kMacSaveGame ( s , argc - 1 , argv + 1 ) ;
2020-01-30 17:13:19 -08:00
case 8 :
2020-05-05 14:49:11 -07:00
return kMacRestoreGame ( s , argc - 1 , argv + 1 ) ;
2020-01-30 17:13:19 -08:00
case 9 :
2020-05-05 14:49:11 -07:00
return kGetSaveFiles32 ( s , argc - 1 , argv + 1 ) ;
2020-01-30 17:13:19 -08:00
case 10 :
2020-05-05 14:49:11 -07:00
return kMakeSaveCatName ( s , argc - 1 , argv + 1 ) ;
2020-01-30 17:13:19 -08:00
case 11 :
2020-05-05 14:49:11 -07:00
return kMakeSaveFileName ( s , argc - 1 , argv + 1 ) ;
2020-01-30 17:13:19 -08:00
// TODO: Phantasmagoria music volume adjustment [ 0-15 ]
case 12 :
warning ( " Unimplemented kMacPlatform32(%d): Set volume: %d " , argv [ 0 ] . toUint16 ( ) , argv [ 1 ] . toUint16 ( ) ) ;
2020-04-19 23:46:13 -07:00
return s - > r_acc ;
2020-01-30 17:13:19 -08:00
default :
2020-04-19 23:46:13 -07:00
break ;
2020-01-30 17:13:19 -08:00
}
2020-04-19 23:46:13 -07:00
error ( " Unknown kMacPlatform32(%d) " , argv [ 0 ] . toUint16 ( ) ) ;
2020-01-30 17:13:19 -08:00
return s - > r_acc ;
}
# endif
2009-10-30 22:53:00 +00:00
enum kSciPlatforms {
2016-08-22 19:48:56 +03:00
kSciPlatformMacintosh = 0 ,
2009-10-30 22:53:00 +00:00
kSciPlatformDOS = 1 ,
kSciPlatformWindows = 2
} ;
- 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
reg_t kPlatform ( EngineState * s , int argc , reg_t * argv ) {
2016-08-16 09:44:45 -05:00
enum Operation {
kPlatformUnknown = 0 ,
kPlatformGetPlatform = 4 ,
kPlatformUnknown5 = 5 ,
kPlatformIsHiRes = 6 ,
kPlatformWin311OrHigher = 7
} ;
2010-02-13 17:42:49 +00:00
bool isWindows = g_sci - > getPlatform ( ) = = Common : : kPlatformWindows ;
2010-01-02 03:44:40 +00:00
2016-08-16 09:44:45 -05:00
if ( argc = = 0 ) {
2010-06-18 09:37:06 +00:00
// This is called in KQ5CD with no parameters, where it seems to do some
// graphics driver check. This kernel function didn't have subfunctions
// then. If 0 is returned, the game functions normally, otherwise all
// the animations show up like a slideshow (e.g. in the intro). So we
2016-08-16 09:44:45 -05:00
// return 0.
2010-01-01 17:16:12 +00:00
return NULL_REG ;
}
2009-12-27 19:16:06 +00:00
2016-08-16 09:44:45 -05:00
if ( g_sci - > forceHiresGraphics ( ) ) {
// force Windows platform, so that hires-graphics are enabled
isWindows = true ;
}
2010-01-02 03:44:40 +00:00
uint16 operation = ( argc = = 0 ) ? 0 : argv [ 0 ] . toUint16 ( ) ;
2009-10-30 22:53:00 +00:00
switch ( operation ) {
2016-08-16 09:44:45 -05:00
case kPlatformUnknown :
2017-08-06 13:30:51 +02:00
// For Mac versions, kPlatform(0) with other args has more functionality. Otherwise, fall through.
2011-02-15 11:02:01 -05:00
if ( g_sci - > getPlatform ( ) = = Common : : kPlatformMacintosh & & argc > 1 )
2011-02-06 00:05:27 +00:00
return kMacPlatform ( s , argc - 1 , argv + 1 ) ;
2017-08-06 13:30:51 +02:00
// fall through
2009-10-30 23:44:12 +00:00
case kPlatformGetPlatform :
2016-08-22 19:48:56 +03:00
if ( isWindows )
return make_reg ( 0 , kSciPlatformWindows ) ;
else if ( g_sci - > getPlatform ( ) = = Common : : kPlatformMacintosh )
return make_reg ( 0 , kSciPlatformMacintosh ) ;
else
return make_reg ( 0 , kSciPlatformDOS ) ;
2016-08-16 09:44:45 -05:00
case kPlatformUnknown5 :
2009-10-30 23:44:12 +00:00
// This case needs to return the opposite of case 6 to get hires graphics
2016-08-16 09:44:45 -05:00
return make_reg ( 0 , ! isWindows ) ;
2009-10-30 23:44:12 +00:00
case kPlatformIsHiRes :
2016-08-16 09:44:45 -05:00
case kPlatformWin311OrHigher :
2009-10-30 23:44:12 +00:00
return make_reg ( 0 , isWindows ) ;
default :
2010-06-28 12:29:06 +00:00
error ( " Unsupported kPlatform operation %d " , operation ) ;
2009-08-30 19:47:47 +00:00
}
2009-12-27 19:16:06 +00:00
2009-08-30 19:47:47 +00:00
return NULL_REG ;
}
2020-02-09 23:23:30 +02:00
extern int showScummVMDialog ( const Common : : String & message , const char * altButton = nullptr , bool alignCenter = true ) ;
2018-12-02 21:56:19 +01:00
2016-08-16 09:44:45 -05:00
# ifdef ENABLE_SCI32
reg_t kPlatform32 ( EngineState * s , int argc , reg_t * argv ) {
enum Operation {
kGetPlatform = 0 ,
kGetCDSpeed = 1 ,
kGetColorDepth = 2 ,
kGetCDDrive = 3
} ;
2017-05-18 11:25:53 -05:00
Operation operation ;
if ( getSciVersion ( ) < SCI_VERSION_2_1_MIDDLE ) {
if ( argc = = 0 | | argv [ 0 ] . toSint16 ( ) = = 0 ) {
operation = kGetPlatform ;
} else {
return NULL_REG ;
}
} else {
operation = argc > 0 ? ( Operation ) argv [ 0 ] . toSint16 ( ) : kGetPlatform ;
}
2016-08-16 09:44:45 -05:00
switch ( operation ) {
case kGetPlatform :
switch ( g_sci - > getPlatform ( ) ) {
case Common : : kPlatformDOS :
return make_reg ( 0 , kSciPlatformDOS ) ;
case Common : : kPlatformWindows :
return make_reg ( 0 , kSciPlatformWindows ) ;
2016-08-22 19:48:56 +03:00
case Common : : kPlatformMacintosh :
2016-08-22 19:56:06 +03:00
// For Mac versions, kPlatform(0) with other args has more functionality
2019-10-24 14:36:17 -07:00
if ( argc > 1 ) {
2020-01-30 17:13:19 -08:00
return kMacPlatform32 ( s , argc - 1 , argv + 1 ) ;
2019-10-24 14:36:17 -07:00
} else {
// SCI32 Mac claims to be DOS. GK1 depends on this in order to play its
// view-based slideshow movies. It appears that Sierra opted to change
// this return value instead of updating the game scripts for Mac.
return make_reg ( 0 , kSciPlatformDOS ) ;
}
2016-08-16 09:44:45 -05:00
default :
error ( " Unknown platform %d " , g_sci - > getPlatform ( ) ) ;
}
case kGetColorDepth :
2017-09-09 15:53:41 -05:00
if ( g_sci - > getGameId ( ) = = GID_PHANTASMAGORIA2 ) {
return make_reg ( 0 , /* 16-bit color */ 3 ) ;
} else {
return make_reg ( 0 , /* 256 color */ 2 ) ;
}
2016-08-16 09:44:45 -05:00
case kGetCDSpeed :
2017-05-30 21:28:26 -05:00
// The value `4` comes from Rama DOS resource.cfg installed in DOSBox,
// and seems to correspond to the highest expected CD speed value
return make_reg ( 0 , 4 ) ;
2016-08-16 09:44:45 -05:00
case kGetCDDrive :
default :
2017-05-18 11:25:53 -05:00
return NULL_REG ;
2016-08-16 09:44:45 -05:00
}
}
2017-01-03 20:19:45 -06:00
reg_t kWebConnect ( EngineState * s , int argc , reg_t * argv ) {
const Common : : String baseUrl = " https://web.archive.org/web/1996/ " ;
const Common : : String gameUrl = argc > 0 ? s - > _segMan - > getString ( argv [ 0 ] ) : " http://www.sierra.com " ;
2017-05-21 19:27:52 -05:00
return make_reg ( 0 , g_system - > openUrl ( baseUrl + gameUrl ) ) ;
2017-01-03 20:19:45 -06:00
}
reg_t kWinExec ( EngineState * s , int argc , reg_t * argv ) {
return NULL_REG ;
}
2018-08-20 04:33:13 +03:00
reg_t kWinDLL ( EngineState * s , int argc , reg_t * argv ) {
uint16 operation = argv [ 0 ] . toUint16 ( ) ;
Common : : String dllName = s - > _segMan - > getString ( argv [ 1 ] ) ;
switch ( operation ) {
case 0 : // load DLL
2019-10-08 01:36:10 +03:00
if ( dllName = = " PENGIN16.DLL " )
showScummVMDialog ( " The Poker logic is hardcoded in an external DLL, and is not implemented yet. There exists some dummy logic for now, where opponent actions are chosen randomly " ) ;
2018-08-20 04:33:13 +03:00
// This is originally a call to LoadLibrary() and to the Watcom function GetIndirectFunctionHandle
return make_reg ( 0 , 1000 ) ; // fake ID for loaded DLL, normally returned from Windows LoadLibrary()
case 1 : // free DLL
// In the original, FreeLibrary() was called here for the loaded DLL
return TRUE_REG ;
case 2 : // call DLL function
if ( dllName = = " PENGIN16.DLL " ) {
// Poker engine logic for Hoyle 5
// This is originally a call to the Watcom function InvokeIndirectFunction()
2019-07-07 22:25:24 +03:00
SciArray * data = s - > _segMan - > lookupArray ( argv [ 2 ] ) ;
return hoyle5PokerEngine ( data ) ;
2018-08-20 04:33:13 +03:00
} else {
error ( " kWinDLL: Unknown DLL to invoke: %s " , dllName . c_str ( ) ) ;
return NULL_REG ;
}
default :
return NULL_REG ;
}
}
2016-08-16 09:44:45 -05:00
# endif
2018-12-02 21:56:19 +01:00
reg_t kKawaHacks ( EngineState * s , int argc , reg_t * argv ) {
switch ( argv [ 0 ] . toUint16 ( ) ) {
case 0 : { // DoAlert
showScummVMDialog ( s - > _segMan - > getString ( argv [ 1 ] ) ) ;
return NULL_REG ;
}
2019-06-23 00:46:53 +02:00
case 1 : { // ZaWarudo
// Invert the color palette for the specified range.
uint16 from = argv [ 1 ] . toUint16 ( ) ;
uint16 to = argv [ 2 ] . toUint16 ( ) ;
Palette pal = g_sci - > _gfxPalette16 - > _sysPalette ;
for ( uint16 i = from ; i < = to ; i + + )
{
pal . colors [ i ] . r = 255 - pal . colors [ i ] . r ;
pal . colors [ i ] . g = 255 - pal . colors [ i ] . g ;
pal . colors [ i ] . b = 255 - pal . colors [ i ] . b ;
}
g_sci - > _gfxPalette16 - > set ( & pal , true ) ;
return NULL_REG ;
}
case 2 : // SetTitleColors
2018-12-02 21:56:19 +01:00
// Unused, would change the colors for plain windows' title bars.
return NULL_REG ;
case 3 : // IsDebug
2019-06-23 00:46:53 +02:00
// Return 1 if running with an internal debugger, 2 if we have AddMenu support, 3 if both.
return make_reg ( 0 , 3 ) ;
2019-12-01 05:06:31 +00:00
default :
break ;
2018-12-02 21:56:19 +01:00
}
return NULL_REG ;
}
2019-06-23 00:46:53 +02:00
reg_t kKawaDbugStr ( EngineState * s , int argc , reg_t * argv )
{
2019-07-24 19:43:26 +01:00
debug ( " %s " , Common : : String : : format ( s - > _segMan - > getString ( argv [ 0 ] ) . c_str ( ) , argc - 1 , argv + 1 ) . c_str ( ) ) ;
2019-06-23 00:46:53 +02:00
return NULL_REG ;
}
2018-12-02 21:56:19 +01:00
2010-06-11 07:47:57 +00:00
reg_t kEmpty ( EngineState * s , int argc , reg_t * argv ) {
2010-06-18 09:37:06 +00:00
// Placeholder for empty kernel functions which are still called from the
// engine scripts (like the empty kSetSynonyms function in SCI1.1). This
// differs from dummy functions because it does nothing and never throws a
// warning when it is called.
2010-06-11 07:47:57 +00:00
return s - > r_acc ;
}
2010-07-21 14:50:31 +00:00
reg_t kStub ( EngineState * s , int argc , reg_t * argv ) {
Kernel * kernel = g_sci - > getKernel ( ) ;
int kernelCallNr = - 1 ;
2016-04-02 00:04:00 +02:00
int kernelSubCallNr = - 1 ;
2010-07-21 14:50:31 +00:00
2011-03-07 23:21:27 +01:00
Common : : List < ExecStack > : : const_iterator callIterator = s - > _executionStack . end ( ) ;
2010-07-21 14:50:31 +00:00
if ( callIterator ! = s - > _executionStack . begin ( ) ) {
callIterator - - ;
ExecStack lastCall = * callIterator ;
2016-04-02 00:04:00 +02:00
kernelCallNr = lastCall . debugKernelFunction ;
kernelSubCallNr = lastCall . debugKernelSubFunction ;
2010-07-21 14:50:31 +00:00
}
2016-04-02 00:04:00 +02:00
Common : : String warningMsg ;
if ( kernelSubCallNr = = - 1 ) {
warningMsg = " Dummy function k " + kernel - > getKernelName ( kernelCallNr ) +
Common : : String : : format ( " [%x] " , kernelCallNr ) ;
} else {
warningMsg = " Dummy function k " + kernel - > getKernelName ( kernelCallNr , kernelSubCallNr ) +
Common : : String : : format ( " [%x:%x] " , kernelCallNr , kernelSubCallNr ) ;
}
warningMsg + = " invoked. Params: " +
Common : : String : : format ( " %d " , argc ) + " ( " ;
2010-07-21 14:50:31 +00:00
for ( int i = 0 ; i < argc ; i + + ) {
2010-11-01 16:02:28 +00:00
warningMsg + = Common : : String : : format ( " %04x:%04x " , PRINT_REG ( argv [ i ] ) ) ;
2010-07-21 14:50:31 +00:00
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 " ) ;
}
2009-05-20 17:51:55 +00:00
} // End of namespace Sci