2014-10-06 14:50:05 +02: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 .
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright ( c ) 1993 Terra Nova Development
* Copyright ( c ) 2004 The Wyrmkeep Entertainment Co .
*
*/
2015-07-17 10:52:30 +03:00
# include "common/config-manager.h"
2014-10-06 14:50:05 +02:00
# include "common/debug-channels.h"
# include "common/scummsys.h"
# include "common/error.h"
# include "common/fs.h"
# include "common/rect.h"
2015-07-17 10:52:30 +03:00
# include "engines/dialogs.h"
# include "engines/engine.h"
2014-10-06 14:50:05 +02:00
# include "engines/util.h"
2015-02-25 03:13:26 +02:00
# include "gui/message.h"
2015-12-01 20:10:42 +01:00
# include "engines/advancedDetector.h"
2015-02-25 03:13:26 +02:00
2014-10-06 14:50:05 +02:00
# include "lab/lab.h"
# include "lab/labfun.h"
2015-10-08 06:02:34 +03:00
# include "lab/resource.h"
2015-12-01 20:10:42 +01:00
# include "lab/anim.h"
2015-12-04 16:52:13 +01:00
# include "lab/graphics.h"
2014-12-27 12:23:20 +01:00
2014-10-06 14:50:05 +02:00
namespace Lab {
2014-12-25 19:13:52 +01:00
LabEngine * g_lab ;
2015-12-04 16:52:13 +01:00
const uint16 INIT_TILE [ 4 ] [ 4 ] = {
{ 1 , 5 , 9 , 13 } ,
{ 2 , 6 , 10 , 14 } ,
{ 3 , 7 , 11 , 15 } ,
{ 4 , 8 , 12 , 0 }
} ;
const uint16 SOLUTION [ 4 ] [ 4 ] = {
{ 7 , 1 , 8 , 3 } ,
{ 2 , 11 , 15 , 4 } ,
{ 9 , 5 , 14 , 6 } ,
{ 10 , 13 , 12 , 0 }
} ;
const int COMBINATION_X [ 6 ] = { 45 , 83 , 129 , 166 , 211 , 248 } ;
2014-12-27 12:23:20 +01:00
LabEngine : : LabEngine ( OSystem * syst , const ADGameDescription * gameDesc )
2015-02-25 03:13:26 +02:00
: Engine ( syst ) , _gameDescription ( gameDesc ) , _extraGameFeatures ( 0 ) {
2014-12-25 19:13:52 +01:00
g_lab = this ;
2015-07-17 10:52:30 +03:00
2015-12-04 13:32:08 +01:00
_screenWidth = 320 ;
2015-11-23 17:34:02 +01:00
_screenHeight = 200 ;
2015-12-04 13:32:08 +01:00
_currentDisplayBuffer = 0 ;
_displayBuffer = 0 ;
2015-11-24 23:59:30 +01:00
2015-12-04 13:32:08 +01:00
_lastWaitTOFTicks = 0 ;
2015-11-24 23:59:30 +01:00
2015-11-30 00:12:01 +01:00
_isHiRes = false ;
2015-11-30 01:42:12 +01:00
_roomNum = - 1 ;
2015-11-30 07:13:09 +01:00
for ( int i = 0 ; i < MAX_CRUMBS ; i + + ) {
_breadCrumbs [ i ] . _roomNum = 0 ;
_breadCrumbs [ i ] . _direction = NORTH ;
}
_numCrumbs = 0 ;
_droppingCrumbs = false ;
_followingCrumbs = false ;
_followCrumbsFast = false ;
_isCrumbTurning = false ;
_isCrumbWaiting = false ;
_crumbSecs = 0 ;
_crumbMicros = 0 ;
2015-11-30 00:34:43 +01:00
_event = nullptr ;
_resource = nullptr ;
2015-11-30 01:17:05 +01:00
_music = nullptr ;
2015-12-01 20:10:42 +01:00
_anim = nullptr ;
2015-12-04 13:32:08 +01:00
_graphics = nullptr ;
2015-11-30 00:34:43 +01:00
2015-12-04 13:32:08 +01:00
_lastTooLong = false ;
2015-12-03 01:06:04 +01:00
_interfaceOff = false ;
_alternate = false ;
for ( int i = 0 ; i < 20 ; i + + )
2015-12-03 02:06:39 +01:00
_moveImages [ i ] = nullptr ;
2015-12-02 20:32:06 +01:00
2015-12-04 16:52:13 +01:00
for ( int i = 0 ; i < 10 ; i + + ) {
2015-12-03 02:06:39 +01:00
_invImages [ i ] = nullptr ;
2015-12-04 16:52:13 +01:00
Images [ i ] = nullptr ;
}
2015-12-03 01:06:04 +01:00
_moveGadgetList = nullptr ;
_invGadgetList = nullptr ;
_curFileName = nullptr ;
_nextFileName = nullptr ;
_newFileName = nullptr ;
2015-12-01 10:35:31 +01:00
2015-12-04 13:32:08 +01:00
_curFileName = " " ;
_msgFont = 0 ;
_inventory = 0 ;
2015-12-03 19:49:55 +01:00
2015-12-04 16:52:13 +01:00
for ( int i = 0 ; i < 16 ; i + + )
Tiles [ i ] = nullptr ;
for ( int i = 0 ; i < 4 ; i + + ) {
for ( int j = 0 ; j < 4 ; j + + )
CurTile [ i ] [ j ] = INIT_TILE [ i ] [ j ] ;
}
for ( int i = 0 ; i < 6 ; i + + )
combination [ i ] = 0 ;
2015-07-17 10:52:30 +03:00
//const Common::FSNode gameDataDir(ConfMan.get("path"));
//SearchMan.addSubDirectoryMatching(gameDataDir, "game");
//SearchMan.addSubDirectoryMatching(gameDataDir, "game/pict");
//SearchMan.addSubDirectoryMatching(gameDataDir, "game/spict");
//SearchMan.addSubDirectoryMatching(gameDataDir, "music");
2014-10-06 14:50:05 +02:00
}
LabEngine : : ~ LabEngine ( ) {
// Remove all of our debug levels here
DebugMan . clearAllDebugChannels ( ) ;
2015-11-30 00:34:43 +01:00
delete _event ;
delete _resource ;
2015-11-30 01:17:05 +01:00
delete _music ;
2015-12-01 20:10:42 +01:00
delete _anim ;
2015-12-04 13:32:08 +01:00
delete _graphics ;
2015-12-04 16:52:13 +01:00
for ( int i = 0 ; i < 16 ; i + + )
delete Tiles [ i ] ;
2014-10-06 14:50:05 +02:00
}
Common : : Error LabEngine : : run ( ) {
2014-12-27 14:18:40 +01:00
if ( getFeatures ( ) & GF_LOWRES )
initGraphics ( 320 , 200 , false ) ;
else
initGraphics ( 640 , 480 , true ) ;
2014-10-06 14:50:05 +02:00
2015-11-29 18:10:06 +01:00
_event = new EventManager ( this ) ;
2015-11-30 00:34:43 +01:00
_resource = new Resource ( this ) ;
2015-11-30 01:17:05 +01:00
_music = new Music ( this ) ;
2015-12-01 20:10:42 +01:00
_anim = new Anim ( this ) ;
2015-12-04 13:32:08 +01:00
_graphics = new DisplayMan ( this ) ;
2014-10-06 14:50:05 +02:00
2015-02-25 03:13:26 +02:00
if ( getPlatform ( ) = = Common : : kPlatformWindows ) {
// Check if this is the Wyrmkeep trial
Common : : File roomFile ;
bool knownVersion = true ;
bool roomFileOpened = roomFile . open ( " game/rooms/48 " ) ;
if ( ! roomFileOpened )
knownVersion = false ;
else if ( roomFile . size ( ) ! = 892 )
knownVersion = false ;
else {
roomFile . seek ( 352 ) ;
byte checkByte = roomFile . readByte ( ) ;
if ( checkByte = = 0x00 ) {
// Full Windows version
} else if ( checkByte = = 0x80 ) {
// Wyrmkeep trial version
_extraGameFeatures = GF_WINDOWS_TRIAL ;
GUI : : MessageDialog trialMessage ( " This is a trial Windows version of the game. To play the full version, you will need to use the original interpreter and purchase a key from Wyrmkeep " ) ;
trialMessage . runModal ( ) ;
} else {
knownVersion = false ;
}
2015-11-23 17:34:02 +01:00
2015-02-25 03:13:26 +02:00
roomFile . close ( ) ;
if ( ! knownVersion ) {
warning ( " Unknown Windows version found, please report this version to the ScummVM team " ) ;
return Common : : kNoGameDataFoundError ;
}
}
}
2014-12-27 14:18:40 +01:00
go ( ) ;
2014-10-06 14:50:05 +02:00
return Common : : kNoError ;
}
2015-02-19 15:20:05 +02:00
Common : : String LabEngine : : generateSaveFileName ( uint slot ) {
return Common : : String : : format ( " %s.%03u " , _targetName . c_str ( ) , slot ) ;
}
2015-12-04 16:52:13 +01:00
/*****************************************************************************/
/* Converts SVGA cords to VGA if necessary, otherwise returns VGA cords. */
/*****************************************************************************/
int LabEngine : : VGAUnScaleX ( int x ) {
if ( _isHiRes )
return ( x / 2 ) ;
else
return x ;
}
/*****************************************************************************/
/* Converts SVGA cords to VGA if necessary, otherwise returns VGA cords. */
/*****************************************************************************/
int LabEngine : : VGAUnScaleY ( int y ) {
if ( _isHiRes )
return ( ( y * 5 ) / 12 ) ;
else
return y ;
}
/*****************************************************************************/
/* Processes mouse clicks and changes the combination. */
/*****************************************************************************/
void LabEngine : : mouseTile ( Common : : Point pos ) {
int x = VGAUnScaleX ( pos . x ) ;
int y = VGAUnScaleY ( pos . y ) ;
if ( ( x < 101 ) | | ( y < 26 ) )
return ;
x = ( x - 101 ) / 30 ;
y = ( y - 26 ) / 25 ;
if ( ( x < 4 ) & & ( y < 4 ) )
changeTile ( x , y ) ;
}
/*****************************************************************************/
/* Changes the combination number of one of the slots */
/*****************************************************************************/
void LabEngine : : changeTile ( uint16 col , uint16 row ) {
int16 scrolltype = - 1 ;
if ( row > 0 ) {
if ( CurTile [ col ] [ row - 1 ] = = 0 ) {
CurTile [ col ] [ row - 1 ] = CurTile [ col ] [ row ] ;
CurTile [ col ] [ row ] = 0 ;
scrolltype = DOWNSCROLL ;
}
}
if ( col > 0 ) {
if ( CurTile [ col - 1 ] [ row ] = = 0 ) {
CurTile [ col - 1 ] [ row ] = CurTile [ col ] [ row ] ;
CurTile [ col ] [ row ] = 0 ;
scrolltype = RIGHTSCROLL ;
}
}
if ( row < 3 ) {
if ( CurTile [ col ] [ row + 1 ] = = 0 ) {
CurTile [ col ] [ row + 1 ] = CurTile [ col ] [ row ] ;
CurTile [ col ] [ row ] = 0 ;
scrolltype = UPSCROLL ;
}
}
if ( col < 3 ) {
if ( CurTile [ col + 1 ] [ row ] = = 0 ) {
CurTile [ col + 1 ] [ row ] = CurTile [ col ] [ row ] ;
CurTile [ col ] [ row ] = 0 ;
scrolltype = LEFTSCROLL ;
}
}
if ( scrolltype ! = - 1 ) {
doTileScroll ( col , row , scrolltype ) ;
if ( getFeatures ( ) & GF_WINDOWS_TRIAL ) {
GUI : : MessageDialog trialMessage ( " This puzzle is not available in the trial version of the game " ) ;
trialMessage . runModal ( ) ;
return ;
}
bool check = true ;
2015-12-04 16:59:09 +01:00
row = 0 ;
col = 0 ;
2015-12-04 16:52:13 +01:00
while ( row < 4 ) {
while ( col < 4 ) {
check = check & & ( CurTile [ row ] [ col ] = = SOLUTION [ row ] [ col ] ) ;
col + + ;
}
row + + ;
col = 0 ;
}
if ( check ) {
_conditions - > inclElement ( BRICKOPEN ) ; /* unlocked combination */
_anim - > _doBlack = true ;
check = _graphics - > readPict ( " p:Up/BDOpen " , true ) ;
}
}
}
/*****************************************************************************/
/* Processes mouse clicks and changes the combination. */
/*****************************************************************************/
void LabEngine : : mouseCombination ( Common : : Point pos ) {
uint16 number ;
int x = VGAUnScaleX ( pos . x ) ;
int y = VGAUnScaleY ( pos . y ) ;
if ( ( y > = 63 ) & & ( y < = 99 ) ) {
if ( ( x > = 44 ) & & ( x < 83 ) )
number = 0 ;
else if ( x < 127 )
number = 1 ;
else if ( x < 165 )
number = 2 ;
else if ( x < 210 )
number = 3 ;
else if ( x < 245 )
number = 4 ;
else if ( x < 286 )
number = 5 ;
else
return ;
changeCombination ( number ) ;
}
}
/*****************************************************************************/
/* Draws the images of the combination lock to the display bitmap. */
/*****************************************************************************/
void LabEngine : : doTile ( bool showsolution ) {
uint16 row = 0 , col = 0 , rowm , colm , num ;
int16 rows , cols ;
if ( showsolution ) {
rowm = _graphics - > VGAScaleY ( 23 ) ;
colm = _graphics - > VGAScaleX ( 27 ) ;
2015-07-17 10:52:30 +03:00
2015-12-04 16:52:13 +01:00
rows = _graphics - > VGAScaleY ( 31 ) ;
cols = _graphics - > VGAScaleX ( 105 ) ;
} else {
_graphics - > setAPen ( 0 ) ;
_graphics - > rectFill ( _graphics - > VGAScaleX ( 97 ) , _graphics - > VGAScaleY ( 22 ) , _graphics - > VGAScaleX ( 220 ) , _graphics - > VGAScaleY ( 126 ) ) ;
rowm = _graphics - > VGAScaleY ( 25 ) ;
colm = _graphics - > VGAScaleX ( 30 ) ;
rows = _graphics - > VGAScaleY ( 25 ) ;
cols = _graphics - > VGAScaleX ( 100 ) ;
}
while ( row < 4 ) {
while ( col < 4 ) {
if ( showsolution )
num = SOLUTION [ col ] [ row ] ;
else
num = CurTile [ col ] [ row ] ;
if ( showsolution | | num )
Tiles [ num ] - > drawImage ( cols + ( col * colm ) , rows + ( row * rowm ) ) ;
col + + ;
}
row + + ;
col = 0 ;
}
}
/*****************************************************************************/
/* Reads in a backdrop picture. */
/*****************************************************************************/
void LabEngine : : showTile ( const char * filename , bool showsolution ) {
uint16 start = showsolution ? 0 : 1 ;
2015-12-04 16:59:09 +01:00
_anim - > _doBlack = true ;
_anim - > _noPalChange = true ;
_graphics - > readPict ( filename , true ) ;
_anim - > _noPalChange = false ;
_graphics - > blackScreen ( ) ;
2015-12-04 16:52:13 +01:00
2015-12-04 16:59:09 +01:00
Common : : File * tileFile = tileFile = _resource - > openDataFile ( showsolution ? " P:TileSolution " : " P:Tile " ) ;
2015-12-04 16:52:13 +01:00
for ( uint16 curBit = start ; curBit < 16 ; curBit + + )
Tiles [ curBit ] = new Image ( tileFile ) ;
delete tileFile ;
2015-12-04 16:59:09 +01:00
doTile ( showsolution ) ;
setPalette ( _anim - > _diffPalette , 256 ) ;
2015-12-04 16:52:13 +01:00
}
/*****************************************************************************/
/* Does the scrolling for the tiles on the tile puzzle. */
/*****************************************************************************/
void LabEngine : : doTileScroll ( uint16 col , uint16 row , uint16 scrolltype ) {
int16 dX = 0 , dY = 0 , dx = 0 , dy = 0 , sx = 0 , sy = 0 ;
uint16 last = 0 , x1 , y1 ;
if ( scrolltype = = LEFTSCROLL ) {
2015-12-04 16:59:09 +01:00
dX = _graphics - > VGAScaleX ( 5 ) ;
sx = _graphics - > VGAScaleX ( 5 ) ;
2015-12-04 16:52:13 +01:00
last = 6 ;
} else if ( scrolltype = = RIGHTSCROLL ) {
2015-12-04 16:59:09 +01:00
dX = _graphics - > VGAScaleX ( - 5 ) ;
dx = _graphics - > VGAScaleX ( - 5 ) ;
sx = _graphics - > VGAScaleX ( 5 ) ;
2015-12-04 16:52:13 +01:00
last = 6 ;
} else if ( scrolltype = = UPSCROLL ) {
2015-12-04 16:59:09 +01:00
dY = _graphics - > VGAScaleY ( 5 ) ;
sy = _graphics - > VGAScaleY ( 5 ) ;
2015-12-04 16:52:13 +01:00
last = 5 ;
} else if ( scrolltype = = DOWNSCROLL ) {
2015-12-04 16:59:09 +01:00
dY = _graphics - > VGAScaleY ( - 5 ) ;
dy = _graphics - > VGAScaleY ( - 5 ) ;
sy = _graphics - > VGAScaleY ( 5 ) ;
2015-12-04 16:52:13 +01:00
last = 5 ;
}
2015-12-04 16:59:09 +01:00
sx + = _graphics - > SVGACord ( 2 ) ;
2015-12-04 16:52:13 +01:00
2015-12-04 16:59:09 +01:00
x1 = _graphics - > VGAScaleX ( 100 ) + ( col * _graphics - > VGAScaleX ( 30 ) ) + dx ;
y1 = _graphics - > VGAScaleY ( 25 ) + ( row * _graphics - > VGAScaleY ( 25 ) ) + dy ;
2015-12-04 16:52:13 +01:00
for ( uint16 i = 0 ; i < last ; i + + ) {
2015-12-04 16:59:09 +01:00
waitTOF ( ) ;
scrollRaster ( dX , dY , x1 , y1 , x1 + _graphics - > VGAScaleX ( 28 ) + sx , y1 + _graphics - > VGAScaleY ( 23 ) + sy ) ;
2015-12-04 16:52:13 +01:00
x1 + = dX ;
y1 + = dY ;
}
}
/*****************************************************************************/
/* Changes the combination number of one of the slots */
/*****************************************************************************/
void LabEngine : : changeCombination ( uint16 number ) {
static const int solution [ 6 ] = { 0 , 4 , 0 , 8 , 7 , 2 } ;
Image display ;
uint16 combnum ;
bool unlocked = true ;
if ( combination [ number ] < 9 )
( combination [ number ] ) + + ;
else
combination [ number ] = 0 ;
combnum = combination [ number ] ;
2015-12-04 16:59:09 +01:00
display . _imageData = getCurrentDrawingBuffer ( ) ;
display . _width = _screenWidth ;
display . _height = _screenHeight ;
2015-12-04 16:52:13 +01:00
for ( uint16 i = 1 ; i < = ( Images [ combnum ] - > _height / 2 ) ; i + + ) {
2015-12-04 16:59:09 +01:00
if ( _isHiRes ) {
2015-12-04 16:52:13 +01:00
if ( i & 1 )
2015-12-04 16:59:09 +01:00
waitTOF ( ) ;
2015-12-04 16:52:13 +01:00
} else
2015-12-04 16:59:09 +01:00
waitTOF ( ) ;
2015-12-04 16:52:13 +01:00
2015-12-04 16:59:09 +01:00
display . _imageData = getCurrentDrawingBuffer ( ) ;
2015-12-04 16:52:13 +01:00
2015-12-04 16:59:09 +01:00
scrollDisplayY ( 2 , _graphics - > VGAScaleX ( COMBINATION_X [ number ] ) , _graphics - > VGAScaleY ( 65 ) , _graphics - > VGAScaleX ( COMBINATION_X [ number ] ) + ( Images [ combnum ] ) - > _width - 1 , _graphics - > VGAScaleY ( 65 ) + ( Images [ combnum ] ) - > _height ) ;
2015-12-04 16:52:13 +01:00
2015-12-04 16:59:09 +01:00
Images [ combnum ] - > bltBitMap ( 0 , ( Images [ combnum ] ) - > _height - ( 2 * i ) , & ( display ) , _graphics - > VGAScaleX ( COMBINATION_X [ number ] ) , _graphics - > VGAScaleY ( 65 ) , ( Images [ combnum ] ) - > _width , 2 ) ;
2015-12-04 16:52:13 +01:00
}
for ( uint16 i = 0 ; i < 6 ; i + + )
unlocked = ( combination [ i ] = = solution [ i ] ) & & unlocked ;
if ( unlocked )
_conditions - > inclElement ( COMBINATIONUNLOCKED ) ;
else
_conditions - > exclElement ( COMBINATIONUNLOCKED ) ;
}
void LabEngine : : scrollRaster ( int16 dx , int16 dy , uint16 x1 , uint16 y1 , uint16 x2 , uint16 y2 ) {
if ( dx )
scrollDisplayX ( dx , x1 , y1 , x2 , y2 ) ;
if ( dy )
scrollDisplayY ( dy , x1 , y1 , x2 , y2 ) ;
}
/*****************************************************************************/
/* Draws the images of the combination lock to the display bitmap. */
/*****************************************************************************/
void LabEngine : : doCombination ( ) {
for ( uint16 i = 0 ; i < = 5 ; i + + )
Images [ combination [ i ] ] - > drawImage ( _graphics - > VGAScaleX ( COMBINATION_X [ i ] ) , _graphics - > VGAScaleY ( 65 ) ) ;
}
/*****************************************************************************/
/* Reads in a backdrop picture. */
/*****************************************************************************/
void LabEngine : : showCombination ( const char * filename ) {
2015-12-04 16:59:09 +01:00
_anim - > _doBlack = true ;
_anim - > _noPalChange = true ;
_graphics - > readPict ( filename , true ) ;
_anim - > _noPalChange = false ;
2015-12-04 16:52:13 +01:00
2015-12-04 16:59:09 +01:00
_graphics - > blackScreen ( ) ;
2015-12-04 16:52:13 +01:00
2015-12-04 16:59:09 +01:00
Common : : File * numFile = _resource - > openDataFile ( " P:Numbers " ) ;
2015-12-04 16:52:13 +01:00
for ( uint16 CurBit = 0 ; CurBit < 10 ; CurBit + + )
Images [ CurBit ] = new Image ( numFile ) ;
delete numFile ;
doCombination ( ) ;
2015-12-04 16:59:09 +01:00
setPalette ( _anim - > _diffPalette , 256 ) ;
2015-12-04 16:52:13 +01:00
}
2015-07-17 10:52:30 +03:00
2014-10-06 14:50:05 +02:00
} // End of namespace Lab