2003-03-05 19:04:34 +00:00
/* ScummVM - Scumm Interpreter
* Copyright ( C ) 2003 The ScummVM project
*
* 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
2003-03-06 02:37:37 +00:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
2003-03-05 19:04:34 +00:00
* 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 . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*
* $ Header $
*
*/
2003-10-12 13:33:21 +00:00
# include "stdafx.h"
2003-10-05 20:21:20 +00:00
# include "common/system.h"
# include "sky/disk.h"
# include "sky/logic.h"
# include "sky/screen.h"
# include "sky/sky.h"
# include "sky/skydefs.h"
# include "sky/struc.h"
2003-03-05 19:04:34 +00:00
2003-05-14 22:33:39 +00:00
uint8 SkyScreen : : _top16Colours [ 16 * 3 ] =
2003-03-05 19:04:34 +00:00
{
2003-03-06 02:37:37 +00:00
0 , 0 , 0 ,
38 , 38 , 38 ,
63 , 63 , 63 ,
0 , 0 , 0 ,
0 , 0 , 0 ,
0 , 0 , 0 ,
0 , 0 , 0 ,
54 , 54 , 54 ,
45 , 47 , 49 ,
32 , 31 , 41 ,
29 , 23 , 37 ,
23 , 18 , 30 ,
49 , 11 , 11 ,
39 , 5 , 5 ,
29 , 1 , 1 ,
63 , 63 , 63
2003-03-05 19:04:34 +00:00
} ;
2003-05-14 22:33:39 +00:00
SkyScreen : : SkyScreen ( OSystem * pSystem , SkyDisk * pDisk ) {
_system = pSystem ;
_skyDisk = pDisk ;
2003-03-06 02:37:37 +00:00
int i ;
2003-03-07 14:52:24 +00:00
uint8 tmpPal [ 1024 ] ;
2003-03-06 07:52:40 +00:00
2003-03-07 14:52:24 +00:00
_system - > init_size ( FULL_SCREEN_WIDTH , FULL_SCREEN_HEIGHT ) ;
2003-07-07 00:14:16 +00:00
_gameGrid = ( uint8 * ) malloc ( GRID_X * GRID_Y * 2 ) ;
2003-05-27 16:42:20 +00:00
forceRefresh ( ) ;
2003-05-14 22:33:39 +00:00
_currentScreen = NULL ;
2003-05-27 16:42:20 +00:00
_scrollScreen = NULL ;
2003-03-05 19:04:34 +00:00
2003-03-06 02:37:37 +00:00
//blank the first 240 colors of the palette
2003-03-07 14:52:24 +00:00
memset ( tmpPal , 0 , GAME_COLOURS * 4 ) ;
2003-03-05 19:04:34 +00:00
2003-03-06 02:37:37 +00:00
//set the remaining colors
2003-03-07 14:52:24 +00:00
for ( i = 0 ; i < ( VGA_COLOURS - GAME_COLOURS ) ; i + + ) {
2003-05-14 22:33:39 +00:00
tmpPal [ 4 * GAME_COLOURS + i * 4 ] = ( _top16Colours [ i * 3 ] < < 2 ) + ( _top16Colours [ i * 3 ] & 3 ) ;
tmpPal [ 4 * GAME_COLOURS + i * 4 + 1 ] = ( _top16Colours [ i * 3 + 1 ] < < 2 ) + ( _top16Colours [ i * 3 + 1 ] & 3 ) ;
tmpPal [ 4 * GAME_COLOURS + i * 4 + 2 ] = ( _top16Colours [ i * 3 + 2 ] < < 2 ) + ( _top16Colours [ i * 3 + 2 ] & 3 ) ;
2003-05-03 23:32:04 +00:00
tmpPal [ 4 * GAME_COLOURS + i * 4 + 3 ] = 0x00 ;
2003-03-06 02:37:37 +00:00
}
2003-03-05 19:04:34 +00:00
2003-03-06 02:37:37 +00:00
//set the palette
2003-05-03 23:32:04 +00:00
_system - > set_palette ( tmpPal , 0 , VGA_COLOURS ) ;
2003-05-27 16:42:20 +00:00
_currentPalette = 0 ;
2003-05-14 22:33:39 +00:00
_seqInfo . framesLeft = 0 ;
_seqInfo . seqData = _seqInfo . seqDataPos = NULL ;
_seqInfo . running = false ;
}
SkyScreen : : ~ SkyScreen ( void ) {
free ( _gameGrid ) ;
if ( _currentScreen ) free ( _currentScreen ) ;
2003-03-05 19:04:34 +00:00
}
2003-06-02 06:42:42 +00:00
void SkyScreen : : clearScreen ( void ) {
memset ( _currentScreen , 0 , FULL_SCREEN_WIDTH * FULL_SCREEN_HEIGHT ) ;
_system - > copy_rect ( _currentScreen , GAME_SCREEN_WIDTH , 0 , 0 , GAME_SCREEN_WIDTH , GAME_SCREEN_HEIGHT ) ;
_system - > update_screen ( ) ;
}
2003-03-05 19:04:34 +00:00
//set a new palette, pal is a pointer to dos vga rgb components 0..63
2003-05-14 22:33:39 +00:00
void SkyScreen : : setPalette ( uint8 * pal ) {
2003-03-07 14:52:24 +00:00
convertPalette ( pal , _palette ) ;
2003-05-03 23:32:04 +00:00
_system - > set_palette ( _palette , 0 , GAME_COLOURS ) ;
2003-05-14 22:33:39 +00:00
_system - > update_screen ( ) ;
}
2003-07-10 20:09:19 +00:00
void SkyScreen : : setPaletteEndian ( uint8 * pal ) {
# ifdef SCUMM_BIG_ENDIAN
uint8 endPalette [ 256 * 3 ] ;
for ( uint16 cnt = 0 ; cnt < 256 * 3 ; cnt + + )
endPalette [ cnt ] = pal [ cnt ^ 1 ] ;
2003-07-10 20:22:26 +00:00
convertPalette ( endPalette , _palette ) ;
2003-07-10 20:09:19 +00:00
# else
convertPalette ( pal , _palette ) ;
2003-07-10 20:15:11 +00:00
# endif
2003-07-10 20:09:19 +00:00
_system - > set_palette ( _palette , 0 , GAME_COLOURS ) ;
_system - > update_screen ( ) ;
}
2003-05-27 16:42:20 +00:00
void SkyScreen : : halvePalette ( void ) {
uint8 halfPalette [ 1024 ] ;
for ( uint8 cnt = 0 ; cnt < GAME_COLOURS ; cnt + + ) {
halfPalette [ ( cnt < < 2 ) | 0 ] = _palette [ ( cnt < < 2 ) | 0 ] > > 1 ;
halfPalette [ ( cnt < < 2 ) | 1 ] = _palette [ ( cnt < < 2 ) | 1 ] > > 1 ;
halfPalette [ ( cnt < < 2 ) | 2 ] = _palette [ ( cnt < < 2 ) | 2 ] > > 1 ;
halfPalette [ ( cnt < < 2 ) | 3 ] = 0 ;
}
_system - > set_palette ( halfPalette , 0 , GAME_COLOURS ) ;
}
2003-05-14 22:33:39 +00:00
void SkyScreen : : setPalette ( uint16 fileNum ) {
uint8 * tmpPal = _skyDisk - > loadFile ( fileNum , NULL ) ;
if ( tmpPal ) {
setPalette ( tmpPal ) ;
free ( tmpPal ) ;
2003-07-13 16:22:17 +00:00
} else warning ( " SkyScreen::setPalette: can't load file nr. %d " , fileNum ) ;
2003-05-14 22:33:39 +00:00
}
void SkyScreen : : showScreen ( uint16 fileNum ) {
if ( _currentScreen ) free ( _currentScreen ) ;
_currentScreen = _skyDisk - > loadFile ( fileNum , NULL ) ;
if ( _currentScreen ) showScreen ( _currentScreen ) ;
2003-07-13 16:22:17 +00:00
else warning ( " SkyScreen::showScreen: can't load file nr. %d " , fileNum ) ;
2003-05-14 22:33:39 +00:00
}
void SkyScreen : : showScreen ( uint8 * pScreen ) {
_system - > copy_rect ( pScreen , 320 , 0 , 0 , GAME_SCREEN_WIDTH , GAME_SCREEN_HEIGHT ) ;
_system - > update_screen ( ) ;
2003-03-05 19:04:34 +00:00
}
2003-05-14 22:33:39 +00:00
void SkyScreen : : convertPalette ( uint8 * inPal , uint8 * outPal ) { //convert 3 byte 0..63 rgb to 4byte 0..255 rgbx
2003-03-07 14:52:24 +00:00
2003-03-06 02:37:37 +00:00
int i ;
2003-03-05 19:04:34 +00:00
2003-03-07 14:52:24 +00:00
for ( i = 0 ; i < VGA_COLOURS ; i + + ) {
outPal [ 4 * i ] = ( inPal [ 3 * i ] < < 2 ) + ( inPal [ 3 * i ] & 3 ) ;
outPal [ 4 * i + 1 ] = ( inPal [ 3 * i + 1 ] < < 2 ) + ( inPal [ 3 * i + 1 ] & 3 ) ;
outPal [ 4 * i + 2 ] = ( inPal [ 3 * i + 2 ] < < 2 ) + ( inPal [ 3 * i + 2 ] & 3 ) ;
outPal [ 4 * i + 3 ] = 0x00 ;
2003-03-06 02:37:37 +00:00
}
2003-03-05 19:04:34 +00:00
}
2003-03-08 12:46:51 +00:00
2003-05-27 16:42:20 +00:00
void SkyScreen : : recreate ( void ) {
2003-03-08 12:46:51 +00:00
2003-05-27 16:42:20 +00:00
// check the game grid for changed blocks
if ( ! SkyLogic : : _scriptVariables [ LAYER_0_ID ] ) return ;
uint8 * gridPos = _gameGrid ;
2003-10-05 20:21:20 +00:00
uint8 * screenData = ( uint8 * ) SkyEngine : : fetchItem ( SkyLogic : : _scriptVariables [ LAYER_0_ID ] ) ;
2003-05-27 16:42:20 +00:00
if ( ! screenData ) {
2003-10-05 20:21:20 +00:00
error ( " SkyScreen::recreate(): \n SkyEngine::fetchItem(SkyLogic::_scriptVariables[LAYER_0_ID](%X)) returned NULL " , SkyLogic : : _scriptVariables [ LAYER_0_ID ] ) ;
2003-05-27 16:42:20 +00:00
}
2003-07-12 04:21:20 +00:00
uint8 * screenPos = _currentScreen ;
2003-05-27 16:42:20 +00:00
for ( uint8 cnty = 0 ; cnty < GRID_Y ; cnty + + ) {
for ( uint8 cntx = 0 ; cntx < GRID_X ; cntx + + ) {
if ( gridPos [ 0 ] & 0x80 ) {
gridPos [ 0 ] & = 0x7F ; // reset recreate flag
gridPos [ 0 ] | = 1 ; // set bit for flip routine
uint8 * savedScreenY = screenPos ;
for ( uint8 gridCntY = 0 ; gridCntY < GRID_H ; gridCntY + + ) {
memcpy ( screenPos , screenData , GRID_W ) ;
screenPos + = GAME_SCREEN_WIDTH ;
2003-06-01 13:29:28 +00:00
screenData + = GRID_W ;
2003-05-27 16:42:20 +00:00
}
screenPos = savedScreenY + GRID_W ;
} else {
screenPos + = GRID_W ;
screenData + = GRID_W * GRID_H ;
}
gridPos + + ;
}
screenPos + = ( GRID_H - 1 ) * GAME_SCREEN_WIDTH ;
}
}
2003-07-11 22:59:56 +00:00
void SkyScreen : : flip ( bool doUpdate ) {
2003-05-27 16:42:20 +00:00
2003-06-02 00:53:31 +00:00
uint32 copyX , copyWidth ;
2003-06-02 21:43:45 +00:00
copyX = copyWidth = 0 ;
2003-05-27 16:42:20 +00:00
for ( uint8 cnty = 0 ; cnty < GRID_Y ; cnty + + ) {
for ( uint8 cntx = 0 ; cntx < GRID_X ; cntx + + ) {
2003-05-28 20:55:25 +00:00
if ( _gameGrid [ cnty * GRID_X + cntx ] & 1 ) {
_gameGrid [ cnty * GRID_X + cntx ] & = ~ 1 ;
2003-06-02 00:53:31 +00:00
if ( ! copyWidth ) copyX = cntx * GRID_W ;
copyWidth + = GRID_W ;
} else if ( copyWidth ) {
_system - > copy_rect ( _currentScreen + cnty * GRID_H * GAME_SCREEN_WIDTH + copyX , GAME_SCREEN_WIDTH , copyX , cnty * GRID_H , copyWidth , GRID_H ) ;
copyWidth = 0 ;
2003-05-27 16:42:20 +00:00
}
}
2003-06-02 00:53:31 +00:00
if ( copyWidth ) {
_system - > copy_rect ( _currentScreen + cnty * GRID_H * GAME_SCREEN_WIDTH + copyX , GAME_SCREEN_WIDTH , copyX , cnty * GRID_H , copyWidth , GRID_H ) ;
copyWidth = 0 ;
}
2003-05-27 16:42:20 +00:00
}
2003-07-11 22:59:56 +00:00
if ( doUpdate )
_system - > update_screen ( ) ;
2003-05-27 16:42:20 +00:00
}
void SkyScreen : : fnDrawScreen ( uint32 palette , uint32 scroll ) {
// set up the new screen
fnFadeDown ( scroll ) ;
forceRefresh ( ) ;
recreate ( ) ;
spriteEngine ( ) ;
2003-07-11 22:59:56 +00:00
flip ( false ) ;
2003-05-27 16:42:20 +00:00
fnFadeUp ( palette , scroll ) ;
}
void SkyScreen : : fnFadeDown ( uint32 scroll ) {
2003-03-08 12:46:51 +00:00
2003-10-05 20:21:20 +00:00
if ( scroll & & ( ! ( SkyEngine : : _systemVars . systemFlags & SF_NO_SCROLL ) ) ) {
2003-05-27 16:42:20 +00:00
// scrolling is performed by fnFadeUp. It's just prepared here
_scrollScreen = _currentScreen ;
2003-07-07 00:14:16 +00:00
_currentScreen = ( uint8 * ) malloc ( FULL_SCREEN_WIDTH * FULL_SCREEN_HEIGHT ) ;
2003-05-27 16:42:20 +00:00
// the game will draw the new room into _currentScreen which
// will be scrolled into the visible screen by fnFadeUp
// fnFadeUp also frees the _scrollScreen
2003-03-08 12:46:51 +00:00
} else {
2003-05-14 22:33:39 +00:00
for ( uint8 cnt = 0 ; cnt < 32 ; cnt + + ) {
2003-05-03 23:32:04 +00:00
palette_fadedown_helper ( ( uint32 * ) _palette , GAME_COLOURS ) ;
_system - > set_palette ( _palette , 0 , GAME_COLOURS ) ;
2003-03-08 12:46:51 +00:00
_system - > update_screen ( ) ;
2003-06-01 22:53:44 +00:00
_system - > delay_msecs ( 20 ) ;
2003-05-14 22:33:39 +00:00
}
2003-03-08 12:46:51 +00:00
}
}
2003-05-14 22:33:39 +00:00
void SkyScreen : : palette_fadedown_helper ( uint32 * pal , uint num ) {
2003-03-08 12:46:51 +00:00
byte * p = ( byte * ) pal ;
do {
if ( p [ 0 ] > = 8 )
p [ 0 ] - = 8 ;
else
p [ 0 ] = 0 ;
if ( p [ 1 ] > = 8 )
p [ 1 ] - = 8 ;
else
p [ 1 ] = 0 ;
if ( p [ 2 ] > = 8 )
p [ 2 ] - = 8 ;
else
p [ 2 ] = 0 ;
p + = sizeof ( uint32 ) ;
} while ( - - num ) ;
}
2003-05-14 22:33:39 +00:00
void SkyScreen : : paletteFadeUp ( uint16 fileNr ) {
uint8 * pal = _skyDisk - > loadFile ( fileNr , NULL ) ;
if ( pal ) {
paletteFadeUp ( pal ) ;
2003-06-01 13:29:28 +00:00
free ( pal ) ;
2003-07-13 16:22:17 +00:00
} else warning ( " SkyScreen::paletteFadeUp: Can't load palette #%d " , fileNr ) ;
2003-05-14 22:33:39 +00:00
}
void SkyScreen : : paletteFadeUp ( uint8 * pal ) {
2003-03-08 12:46:51 +00:00
byte tmpPal [ 1024 ] ;
convertPalette ( pal , tmpPal ) ;
2003-05-15 19:14:40 +00:00
for ( uint8 cnt = 1 ; cnt < = 32 ; cnt + + ) {
for ( uint8 colCnt = 0 ; colCnt < GAME_COLOURS ; colCnt + + ) {
_palette [ ( colCnt < < 2 ) | 0 ] = ( tmpPal [ ( colCnt < < 2 ) | 0 ] * cnt ) > > 5 ;
_palette [ ( colCnt < < 2 ) | 1 ] = ( tmpPal [ ( colCnt < < 2 ) | 1 ] * cnt ) > > 5 ;
_palette [ ( colCnt < < 2 ) | 2 ] = ( tmpPal [ ( colCnt < < 2 ) | 2 ] * cnt ) > > 5 ;
}
2003-05-03 23:32:04 +00:00
_system - > set_palette ( _palette , 0 , GAME_COLOURS ) ;
2003-03-08 12:46:51 +00:00
_system - > update_screen ( ) ;
2003-06-01 22:53:44 +00:00
_system - > delay_msecs ( 20 ) ;
2003-05-14 22:33:39 +00:00
}
2003-03-08 12:46:51 +00:00
}
2003-05-27 16:42:20 +00:00
void SkyScreen : : fnFadeUp ( uint32 palNum , uint32 scroll ) {
//_currentScreen points to new screen,
//_scrollScreen points to graphic showing old room
2003-07-01 01:29:29 +00:00
if ( ( scroll ! = 123 ) & & ( scroll ! = 321 ) ) {
2003-06-30 16:59:41 +00:00
scroll = 0 ;
}
2003-10-05 20:21:20 +00:00
if ( ( scroll = = 0 ) | | ( SkyEngine : : _systemVars . systemFlags & SF_NO_SCROLL ) ) {
uint8 * palette = ( uint8 * ) SkyEngine : : fetchCompact ( palNum ) ;
2003-06-01 21:21:10 +00:00
if ( palette = = NULL )
2003-07-13 16:22:17 +00:00
error ( " SkyScreen::fnFadeUp: can't fetch compact %X " , palNum ) ;
2003-06-01 21:21:10 +00:00
# ifdef SCUMM_BIG_ENDIAN
byte tmpPal [ 256 * 3 ] ;
for ( uint16 cnt = 0 ; cnt < 256 * 3 ; cnt + + )
tmpPal [ cnt ] = palette [ cnt ^ 1 ] ;
paletteFadeUp ( tmpPal ) ;
# else
paletteFadeUp ( palette ) ;
# endif
} else if ( scroll = = 123 ) {
2003-05-27 16:42:20 +00:00
// scroll left (going right)
2003-07-13 16:22:17 +00:00
if ( ! _currentScreen ) error ( " SkyScreen::fnFadeUp[Scroll L]: _currentScreen is NULL " ) ;
if ( ! _scrollScreen ) error ( " SkyScreen::fnFadeUp[Scroll L]: _scrollScreen is NULL " ) ;
2003-05-27 16:42:20 +00:00
uint8 * scrNewPtr , * scrOldPtr ;
for ( uint8 scrollCnt = 0 ; scrollCnt < ( GAME_SCREEN_WIDTH / SCROLL_JUMP ) - 1 ; scrollCnt + + ) {
scrNewPtr = _currentScreen + scrollCnt * SCROLL_JUMP ;
scrOldPtr = _scrollScreen ;
for ( uint8 lineCnt = 0 ; lineCnt < GAME_SCREEN_HEIGHT ; lineCnt + + ) {
memmove ( scrOldPtr , scrOldPtr + SCROLL_JUMP , GAME_SCREEN_WIDTH - SCROLL_JUMP ) ;
memcpy ( scrOldPtr + GAME_SCREEN_WIDTH - SCROLL_JUMP , scrNewPtr , SCROLL_JUMP ) ;
scrNewPtr + = GAME_SCREEN_WIDTH ;
scrOldPtr + = GAME_SCREEN_WIDTH ;
}
showScreen ( _scrollScreen ) ;
waitForTimer ( ) ;
}
showScreen ( _currentScreen ) ;
free ( _scrollScreen ) ;
} else if ( scroll = = 321 ) {
// scroll right (going left)
2003-07-13 16:22:17 +00:00
if ( ! _currentScreen ) error ( " SkyScreen::fnFadeUp[Scroll R]: _currentScreen is NULL " ) ;
if ( ! _scrollScreen ) error ( " SkyScreen::fnFadeUp[Scroll R]: _scrollScreen is NULL " ) ;
2003-05-27 16:42:20 +00:00
uint8 * scrNewPtr , * scrOldPtr ;
for ( uint8 scrollCnt = 0 ; scrollCnt < ( GAME_SCREEN_WIDTH / SCROLL_JUMP ) - 1 ; scrollCnt + + ) {
scrNewPtr = _currentScreen + GAME_SCREEN_WIDTH - ( scrollCnt + 1 ) * SCROLL_JUMP ;
scrOldPtr = _scrollScreen ;
for ( uint8 lineCnt = 0 ; lineCnt < GAME_SCREEN_HEIGHT ; lineCnt + + ) {
memmove ( scrOldPtr + SCROLL_JUMP , scrOldPtr , GAME_SCREEN_WIDTH - SCROLL_JUMP ) ;
memcpy ( scrOldPtr , scrNewPtr , SCROLL_JUMP ) ;
scrNewPtr + = GAME_SCREEN_WIDTH ;
scrOldPtr + = GAME_SCREEN_WIDTH ;
}
showScreen ( _scrollScreen ) ;
waitForTimer ( ) ;
}
showScreen ( _currentScreen ) ;
free ( _scrollScreen ) ;
2003-06-30 16:59:41 +00:00
}
2003-05-27 16:42:20 +00:00
}
2003-05-14 22:33:39 +00:00
void SkyScreen : : waitForTimer ( void ) {
_gotTick = false ;
2003-07-11 15:52:46 +00:00
while ( ! _gotTick ) {
OSystem : : Event event ;
2003-05-14 22:33:39 +00:00
_system - > delay_msecs ( 10 ) ;
2003-07-11 15:52:46 +00:00
while ( _system - > poll_event ( & event ) ) ;
}
2003-05-14 22:33:39 +00:00
}
2003-08-06 10:06:19 +00:00
void SkyScreen : : waitForSequence ( void ) {
2003-10-01 09:40:28 +00:00
while ( _seqInfo . running ) {
OSystem : : Event event ;
2003-08-06 10:06:19 +00:00
2003-10-01 09:40:28 +00:00
_system - > delay_msecs ( 20 ) ;
while ( _system - > poll_event ( & event ) ) ;
}
2003-08-06 10:06:19 +00:00
}
2003-05-14 22:33:39 +00:00
void SkyScreen : : handleTimer ( void ) {
_gotTick = true ;
if ( _seqInfo . running ) processSequence ( ) ;
}
void SkyScreen : : startSequence ( uint16 fileNum ) {
_seqInfo . seqData = _skyDisk - > loadFile ( fileNum , NULL ) ;
_seqInfo . framesLeft = _seqInfo . seqData [ 0 ] ;
_seqInfo . seqDataPos = _seqInfo . seqData + 1 ;
_seqInfo . delay = SEQ_DELAY ;
_seqInfo . running = true ;
2003-06-02 06:42:42 +00:00
_seqInfo . runningItem = false ;
}
void SkyScreen : : startSequenceItem ( uint16 itemNum ) {
2003-10-05 20:21:20 +00:00
_seqInfo . seqData = ( uint8 * ) SkyEngine : : fetchItem ( itemNum ) ;
2003-07-01 13:04:00 +00:00
_seqInfo . framesLeft = _seqInfo . seqData [ 0 ] - 1 ;
2003-06-02 06:42:42 +00:00
_seqInfo . seqDataPos = _seqInfo . seqData + 1 ;
_seqInfo . delay = SEQ_DELAY ;
_seqInfo . running = true ;
_seqInfo . runningItem = true ;
2003-05-14 22:33:39 +00:00
}
void SkyScreen : : stopSequence ( ) {
_seqInfo . running = false ;
waitForTimer ( ) ;
waitForTimer ( ) ;
_seqInfo . framesLeft = 0 ;
free ( _seqInfo . seqData ) ;
_seqInfo . seqData = _seqInfo . seqDataPos = NULL ;
}
void SkyScreen : : processSequence ( void ) {
uint32 screenPos = 0 ;
_seqInfo . delay - - ;
if ( _seqInfo . delay = = 0 ) {
_seqInfo . delay = SEQ_DELAY ;
2003-06-03 18:10:32 +00:00
memset ( _seqGrid , 0 , 12 * 20 ) ;
2003-05-14 22:33:39 +00:00
2003-10-01 09:40:28 +00:00
uint8 nrToSkip , nrToDo , cnt ;
2003-05-14 22:33:39 +00:00
do {
do {
nrToSkip = _seqInfo . seqDataPos [ 0 ] ;
_seqInfo . seqDataPos + + ;
screenPos + = nrToSkip ;
} while ( nrToSkip = = 0xFF ) ;
do {
nrToDo = _seqInfo . seqDataPos [ 0 ] ;
_seqInfo . seqDataPos + + ;
2003-06-01 22:53:44 +00:00
2003-06-03 18:10:32 +00:00
uint8 gridSta = ( uint8 ) ( ( screenPos / ( GAME_SCREEN_WIDTH * 16 ) ) * 20 + ( ( screenPos % GAME_SCREEN_WIDTH ) > > 4 ) ) ;
2003-07-07 17:00:55 +00:00
uint8 gridEnd = ( uint8 ) ( ( ( screenPos + nrToDo ) / ( GAME_SCREEN_WIDTH * 16 ) ) * 20 + ( ( ( screenPos + nrToDo ) % GAME_SCREEN_WIDTH ) > > 4 ) ) ;
2003-07-08 22:27:17 +00:00
if ( gridEnd > = gridSta )
for ( cnt = gridSta ; cnt < = gridEnd ; cnt + + )
_seqGrid [ cnt ] = 1 ;
else {
for ( cnt = gridSta ; cnt < ( gridSta / 20 + 1 ) * 20 ; cnt + + )
_seqGrid [ cnt ] = 1 ;
for ( cnt = ( gridEnd / 20 ) * 20 ; cnt < = gridEnd ; cnt + + )
_seqGrid [ cnt ] = 1 ;
}
2003-05-14 22:33:39 +00:00
for ( cnt = 0 ; cnt < nrToDo ; cnt + + ) {
_currentScreen [ screenPos ] = _seqInfo . seqDataPos [ 0 ] ;
_seqInfo . seqDataPos + + ;
screenPos + + ;
}
} while ( nrToDo = = 0xFF ) ;
} while ( screenPos < ( GAME_SCREEN_WIDTH * GAME_SCREEN_HEIGHT ) ) ;
2003-06-03 18:35:18 +00:00
uint8 * gridPtr = _seqGrid ; uint8 * scrPtr = _currentScreen ; uint8 * rectPtr = NULL ;
uint8 rectWid = 0 , rectX = 0 , rectY = 0 ;
2003-06-03 18:10:32 +00:00
for ( uint8 cnty = 0 ; cnty < 12 ; cnty + + ) {
for ( uint8 cntx = 0 ; cntx < 20 ; cntx + + ) {
if ( * gridPtr ) {
if ( ! rectWid ) {
rectX = cntx ;
rectY = cnty ;
rectPtr = scrPtr ;
}
rectWid + + ;
} else if ( rectWid ) {
_system - > copy_rect ( rectPtr , GAME_SCREEN_WIDTH , rectX < < 4 , rectY < < 4 , rectWid < < 4 , 16 ) ;
rectWid = 0 ;
}
scrPtr + = 16 ;
gridPtr + + ;
}
if ( rectWid ) {
_system - > copy_rect ( rectPtr , GAME_SCREEN_WIDTH , rectX < < 4 , rectY < < 4 , rectWid < < 4 , 16 ) ;
rectWid = 0 ;
}
scrPtr + = 15 * GAME_SCREEN_WIDTH ;
}
2003-06-01 22:53:44 +00:00
_system - > update_screen ( ) ;
2003-05-14 22:33:39 +00:00
_seqInfo . framesLeft - - ;
}
if ( _seqInfo . framesLeft = = 0 ) {
_seqInfo . running = false ;
2003-06-02 06:42:42 +00:00
if ( ! _seqInfo . runningItem ) free ( _seqInfo . seqData ) ;
2003-05-14 22:33:39 +00:00
_seqInfo . seqData = _seqInfo . seqDataPos = NULL ;
}
}
2003-05-27 16:42:20 +00:00
//- sprites.asm routines
void SkyScreen : : spriteEngine ( void ) {
doSprites ( BACK ) ;
sortSprites ( ) ;
doSprites ( FORE ) ;
}
void SkyScreen : : sortSprites ( void ) {
StSortList sortList [ 30 ] ;
uint32 currDrawList = DRAW_LIST_NO ;
2003-05-28 20:55:25 +00:00
uint32 loadDrawList ;
2003-05-27 16:42:20 +00:00
bool nextDrawList = false ;
while ( SkyLogic : : _scriptVariables [ currDrawList ] ) {
// big_sort_loop
uint32 spriteCnt = 0 ;
2003-05-28 20:55:25 +00:00
loadDrawList = SkyLogic : : _scriptVariables [ currDrawList ] ;
currDrawList + + ;
2003-05-27 16:42:20 +00:00
do { // a_new_draw_list:
2003-10-05 20:21:20 +00:00
uint16 * drawListData = ( uint16 * ) SkyEngine : : fetchCompact ( loadDrawList ) ;
2003-05-27 16:42:20 +00:00
nextDrawList = false ;
while ( ( ! nextDrawList ) & & ( drawListData [ 0 ] ) ) {
if ( drawListData [ 0 ] = = 0xFFFF ) {
2003-05-28 20:55:25 +00:00
loadDrawList = drawListData [ 1 ] ;
2003-05-27 16:42:20 +00:00
nextDrawList = true ;
} else {
// process_this_id:
2003-10-05 20:21:20 +00:00
Compact * spriteComp = SkyEngine : : fetchCompact ( drawListData [ 0 ] ) ;
2003-05-27 16:42:20 +00:00
if ( ( spriteComp - > status & 4 ) & & // is it sortable playfield?(!?!)
( spriteComp - > screen = = SkyLogic : : _scriptVariables [ SCREEN ] ) ) { // on current screen
dataFileHeader * spriteData =
2003-10-05 20:21:20 +00:00
( dataFileHeader * ) SkyEngine : : fetchItem ( spriteComp - > frame > > 6 ) ;
2003-05-27 16:42:20 +00:00
if ( ! spriteData ) {
2003-07-13 16:22:17 +00:00
debug ( 9 , " Missing file %d " , spriteComp - > frame > > 6 ) ;
2003-05-27 16:42:20 +00:00
spriteComp - > status = 0 ;
} else {
2003-07-06 23:06:53 +00:00
sortList [ spriteCnt ] . yCood = spriteComp - > ycood + spriteData - > s_offset_y + spriteData - > s_height ;
2003-05-27 16:42:20 +00:00
sortList [ spriteCnt ] . compact = spriteComp ;
sortList [ spriteCnt ] . sprite = spriteData ;
spriteCnt + + ;
}
}
drawListData + + ;
}
}
} while ( nextDrawList ) ;
// made_list:
if ( spriteCnt > 1 ) { // bubble sort
2003-05-28 20:55:25 +00:00
for ( uint32 cnt1 = 0 ; cnt1 < spriteCnt - 1 ; cnt1 + + )
2003-05-27 16:42:20 +00:00
for ( uint32 cnt2 = cnt1 + 1 ; cnt2 < spriteCnt ; cnt2 + + )
2003-07-06 15:56:13 +00:00
if ( sortList [ cnt1 ] . yCood > sortList [ cnt2 ] . yCood ) {
2003-05-27 16:42:20 +00:00
StSortList tmp ;
tmp . yCood = sortList [ cnt1 ] . yCood ;
tmp . sprite = sortList [ cnt1 ] . sprite ;
tmp . compact = sortList [ cnt1 ] . compact ;
sortList [ cnt1 ] . yCood = sortList [ cnt2 ] . yCood ;
sortList [ cnt1 ] . sprite = sortList [ cnt2 ] . sprite ;
sortList [ cnt1 ] . compact = sortList [ cnt2 ] . compact ;
sortList [ cnt2 ] . yCood = tmp . yCood ;
sortList [ cnt2 ] . sprite = tmp . sprite ;
sortList [ cnt2 ] . compact = tmp . compact ;
}
}
for ( uint32 cnt = 0 ; cnt < spriteCnt ; cnt + + ) {
2003-07-07 00:14:16 +00:00
drawSprite ( ( uint8 * ) sortList [ cnt ] . sprite , sortList [ cnt ] . compact ) ;
2003-05-27 16:42:20 +00:00
if ( sortList [ cnt ] . compact - > status & 8 ) vectorToGame ( 0x81 ) ;
else vectorToGame ( 1 ) ;
2003-05-29 03:19:46 +00:00
if ( ! ( sortList [ cnt ] . compact - > status & 0x200 ) ) verticalMask ( ) ;
2003-05-27 16:42:20 +00:00
}
}
}
void SkyScreen : : doSprites ( uint8 layer ) {
uint16 drawListNum = DRAW_LIST_NO ;
uint32 idNum ;
uint16 * drawList ;
while ( SkyLogic : : _scriptVariables [ drawListNum ] ) { // std sp loop
idNum = SkyLogic : : _scriptVariables [ drawListNum ] ;
drawListNum + + ;
2003-10-05 20:21:20 +00:00
drawList = ( uint16 * ) SkyEngine : : fetchCompact ( idNum ) ;
2003-05-27 16:42:20 +00:00
while ( drawList [ 0 ] ) {
// new_draw_list:
2003-05-29 03:19:46 +00:00
while ( ( drawList [ 0 ] ! = 0 ) & & ( drawList [ 0 ] ! = 0xFFFF ) ) {
2003-05-27 16:42:20 +00:00
// back_loop:
2003-06-01 13:29:28 +00:00
// not_new_list
2003-10-05 20:21:20 +00:00
Compact * spriteData = SkyEngine : : fetchCompact ( drawList [ 0 ] ) ;
2003-06-01 13:29:28 +00:00
drawList + + ;
if ( ( spriteData - > status & ( 1 < < layer ) ) & &
( spriteData - > screen = = SkyLogic : : _scriptVariables [ SCREEN ] ) ) {
2003-10-05 20:21:20 +00:00
uint8 * toBeDrawn = ( uint8 * ) SkyEngine : : fetchItem ( spriteData - > frame > > 6 ) ;
2003-06-01 13:29:28 +00:00
if ( ! toBeDrawn ) {
2003-07-13 16:22:17 +00:00
debug ( 9 , " Spritedata %d not loaded " , spriteData - > frame > > 6 ) ;
2003-06-01 13:29:28 +00:00
spriteData - > status = 0 ;
} else {
drawSprite ( toBeDrawn , spriteData ) ;
if ( layer = = BACK ) verticalMask ( ) ;
if ( spriteData - > status & 8 ) vectorToGame ( 0x81 ) ;
else vectorToGame ( 1 ) ;
}
}
2003-05-27 16:42:20 +00:00
}
2003-06-09 02:33:27 +00:00
while ( drawList [ 0 ] = = 0xFFFF )
2003-10-05 20:21:20 +00:00
drawList = ( uint16 * ) SkyEngine : : fetchCompact ( drawList [ 1 ] ) ;
2003-05-27 16:42:20 +00:00
}
}
}
void SkyScreen : : drawSprite ( uint8 * spriteInfo , Compact * sprCompact ) {
if ( spriteInfo = = NULL ) {
2003-07-13 16:22:17 +00:00
warning ( " SkyScreen::drawSprite Can't draw sprite. Data %d was not loaded " , sprCompact - > frame > > 6 ) ;
2003-05-27 16:42:20 +00:00
sprCompact - > status = 0 ;
return ;
}
dataFileHeader * sprDataFile = ( dataFileHeader * ) spriteInfo ;
2003-07-06 23:06:53 +00:00
_sprWidth = sprDataFile - > s_width ;
_sprHeight = sprDataFile - > s_height ;
2003-05-27 16:42:20 +00:00
_maskX1 = _maskX2 = 0 ;
2003-07-06 23:06:53 +00:00
uint8 * spriteData = spriteInfo + ( sprCompact - > frame & 0x3F ) * sprDataFile - > s_sp_size ;
2003-05-27 16:42:20 +00:00
spriteData + = sizeof ( dataFileHeader ) ;
2003-07-06 23:06:53 +00:00
int32 spriteY = sprCompact - > ycood + sprDataFile - > s_offset_y - TOP_LEFT_Y ;
2003-05-27 16:42:20 +00:00
if ( spriteY < 0 ) {
2003-06-05 18:54:26 +00:00
spriteY = - spriteY ;
2003-05-27 16:42:20 +00:00
if ( _sprHeight < = ( uint32 ) spriteY ) {
_sprWidth = 0 ;
return ;
}
_sprHeight - = spriteY ;
2003-07-06 23:06:53 +00:00
spriteData + = sprDataFile - > s_width * spriteY ;
2003-05-27 16:42:20 +00:00
spriteY = 0 ;
} else {
2003-07-06 23:06:53 +00:00
int32 botClip = GAME_SCREEN_HEIGHT - sprDataFile - > s_height - spriteY ;
2003-05-27 16:42:20 +00:00
if ( botClip < 0 ) {
2003-06-09 23:02:56 +00:00
botClip = - botClip ;
2003-06-09 23:21:31 +00:00
if ( _sprHeight < = ( uint32 ) botClip ) {
2003-05-27 16:42:20 +00:00
_sprWidth = 0 ;
return ;
}
2003-06-09 23:02:56 +00:00
_sprHeight - = botClip ;
2003-05-27 16:42:20 +00:00
}
}
_sprY = ( uint32 ) spriteY ;
2003-07-06 23:06:53 +00:00
int32 spriteX = sprCompact - > xcood + sprDataFile - > s_offset_x - TOP_LEFT_X ;
2003-05-27 16:42:20 +00:00
if ( spriteX < 0 ) {
2003-06-05 18:54:26 +00:00
spriteX = - spriteX ;
2003-05-27 16:42:20 +00:00
if ( _sprWidth < = ( uint32 ) spriteX ) {
_sprWidth = 0 ;
return ;
}
_sprWidth - = spriteX ;
_maskX1 = spriteX ;
spriteX = 0 ;
} else {
2003-07-06 23:06:53 +00:00
int32 rightClip = GAME_SCREEN_WIDTH - ( sprDataFile - > s_width + spriteX ) ;
2003-05-27 16:42:20 +00:00
if ( rightClip < 0 ) {
2003-06-05 18:54:26 +00:00
rightClip = ( - rightClip ) + 1 ;
2003-05-27 16:42:20 +00:00
if ( _sprWidth < = ( uint32 ) rightClip ) {
_sprWidth = 0 ;
return ;
}
2003-06-01 13:29:28 +00:00
_sprWidth - = rightClip ;
_maskX2 = rightClip ;
2003-05-27 16:42:20 +00:00
}
}
_sprX = ( uint32 ) spriteX ;
2003-07-12 04:21:20 +00:00
uint8 * screenPtr = _currentScreen + _sprY * GAME_SCREEN_WIDTH + _sprX ;
2003-06-09 23:02:56 +00:00
if ( ( _sprHeight > 192 ) | | ( _sprY > 192 ) ) {
_sprWidth = 0 ;
return ;
}
2003-05-29 14:34:40 +00:00
if ( ( _sprX + _sprWidth > 320 ) | | ( _sprY + _sprHeight > 192 ) ) {
2003-07-13 16:22:17 +00:00
warning ( " SkyScreen::drawSprite fatal error: got x = %d, y = %d, w = %d, h = %d " , _sprX , _sprY , _sprWidth , _sprHeight ) ;
2003-05-27 16:42:20 +00:00
_sprWidth = 0 ;
return ;
}
2003-05-29 03:19:46 +00:00
2003-06-09 23:02:56 +00:00
for ( uint16 cnty = 0 ; cnty < _sprHeight ; cnty + + ) {
2003-06-09 02:33:27 +00:00
for ( uint16 cntx = 0 ; cntx < _sprWidth ; cntx + + )
2003-05-28 20:55:25 +00:00
if ( spriteData [ cntx + _maskX1 ] ) screenPtr [ cntx ] = spriteData [ cntx + _maskX1 ] ;
2003-06-06 17:59:22 +00:00
spriteData + = _sprWidth + _maskX2 + _maskX1 ;
2003-05-27 16:42:20 +00:00
screenPtr + = GAME_SCREEN_WIDTH ;
}
// Convert the sprite coordinate/size values to blocks for vertical mask and/or vector to game
_sprWidth + = _sprX + GRID_W - 1 ;
_sprHeight + = _sprY + GRID_H - 1 ;
_sprX > > = GRID_W_SHIFT ;
_sprWidth > > = GRID_W_SHIFT ;
_sprY > > = GRID_H_SHIFT ;
_sprHeight > > = GRID_H_SHIFT ;
_sprWidth - = _sprX ;
_sprHeight - = _sprY ;
}
void SkyScreen : : vectorToGame ( uint8 gridVal ) {
2003-05-28 20:55:25 +00:00
if ( _sprWidth = = 0 ) return ;
uint8 * trgGrid = _gameGrid + _sprY * GRID_X + _sprX ;
2003-05-27 16:42:20 +00:00
for ( uint32 cnty = 0 ; cnty < _sprHeight ; cnty + + ) {
for ( uint32 cntx = 0 ; cntx < _sprWidth ; cntx + + )
trgGrid [ cntx ] | = gridVal ;
trgGrid + = GRID_X ;
}
}
void SkyScreen : : vertMaskSub ( uint16 * grid , uint32 gridOfs , uint8 * screenPtr , uint32 layerId ) {
for ( uint32 cntx = 0 ; cntx < _sprHeight ; cntx + + ) { // start_x | block_loop
if ( grid [ gridOfs ] ) {
2003-06-01 13:29:28 +00:00
if ( ! ( FROM_LE_16 ( grid [ gridOfs ] ) & 0x8000 ) ) {
uint32 gridVal = FROM_LE_16 ( grid [ gridOfs ] ) - 1 ;
2003-05-27 16:42:20 +00:00
gridVal * = GRID_W * GRID_H ;
2003-10-05 20:21:20 +00:00
uint8 * dataSrc = ( uint8 * ) SkyEngine : : fetchItem ( SkyLogic : : _scriptVariables [ layerId ] ) + gridVal ;
2003-05-27 16:42:20 +00:00
uint8 * dataTrg = screenPtr ;
2003-06-01 05:02:14 +00:00
for ( uint32 grdCntY = 0 ; grdCntY < GRID_H ; grdCntY + + ) {
2003-05-27 16:42:20 +00:00
for ( uint32 grdCntX = 0 ; grdCntX < GRID_W ; grdCntX + + )
if ( dataSrc [ grdCntX ] ) dataTrg [ grdCntX ] = dataSrc [ grdCntX ] ;
dataSrc + = GRID_W ;
dataTrg + = GAME_SCREEN_WIDTH ;
}
} // dummy_end:
screenPtr - = GRID_H * GAME_SCREEN_WIDTH ;
gridOfs - = GRID_X ;
} else return ;
} // next_x
}
void SkyScreen : : verticalMask ( void ) {
if ( _sprWidth = = 0 ) return ;
uint32 startGridOfs = ( _sprY + _sprHeight - 1 ) * GRID_X + _sprX ;
2003-07-12 04:21:20 +00:00
uint8 * startScreenPtr = ( _sprY + _sprHeight - 1 ) * GRID_H * GAME_SCREEN_WIDTH + _sprX * GRID_W + _currentScreen ;
2003-05-27 16:42:20 +00:00
for ( uint32 layerCnt = LAYER_1_ID ; layerCnt < = LAYER_3_ID ; layerCnt + + ) {
uint32 gridOfs = startGridOfs ;
uint8 * screenPtr = startScreenPtr ;
for ( uint32 widCnt = 0 ; widCnt < _sprWidth ; widCnt + + ) { // x_loop
uint32 nLayerCnt = layerCnt ;
while ( SkyLogic : : _scriptVariables [ nLayerCnt + 3 ] ) {
uint16 * scrGrid ;
2003-10-05 20:21:20 +00:00
scrGrid = ( uint16 * ) SkyEngine : : fetchItem ( SkyLogic : : _scriptVariables [ layerCnt + 3 ] ) ;
2003-05-27 16:42:20 +00:00
if ( scrGrid [ gridOfs ] ) {
2003-06-01 13:29:28 +00:00
vertMaskSub ( scrGrid , gridOfs , screenPtr , layerCnt ) ;
2003-05-27 16:42:20 +00:00
break ;
} else nLayerCnt + + ;
}
// next_x:
screenPtr + = GRID_W ;
gridOfs + + ;
}
}
}
2003-07-01 01:29:29 +00:00
void SkyScreen : : paintBox ( uint16 x , uint16 y ) {
uint8 * screenPos = _currentScreen + y * GAME_SCREEN_WIDTH + x ;
memset ( screenPos , 255 , 8 ) ;
for ( uint8 cnt = 1 ; cnt < 8 ; cnt + + ) {
* ( screenPos + cnt * GAME_SCREEN_WIDTH ) = 255 ;
* ( screenPos + cnt * GAME_SCREEN_WIDTH + 7 ) = 255 ;
}
memset ( screenPos + 7 * GAME_SCREEN_WIDTH , 255 , 7 ) ;
}
void SkyScreen : : showGrid ( uint8 * gridBuf ) {
uint32 gridData = 0 ;
uint8 bitsLeft = 0 ;
for ( uint16 cnty = 0 ; cnty < GAME_SCREEN_HEIGHT > > 3 ; cnty + + ) {
for ( uint16 cntx = 0 ; cntx < GAME_SCREEN_WIDTH > > 3 ; cntx + + ) {
if ( ! bitsLeft ) {
bitsLeft = 32 ;
2003-07-07 00:14:16 +00:00
gridData = * ( uint32 * ) gridBuf ;
2003-07-01 01:29:29 +00:00
gridBuf + = 4 ;
}
if ( gridData & 0x80000000 )
paintBox ( cntx < < 3 , cnty < < 3 ) ;
bitsLeft - - ;
gridData < < = 1 ;
}
}
_system - > copy_rect ( _currentScreen , GAME_SCREEN_WIDTH , 0 , 0 , GAME_SCREEN_WIDTH , GAME_SCREEN_HEIGHT ) ;
}