2003-07-28 01:44:38 +00:00
/* Copyright (C) 1994-2003 Revolution Software Ltd
*
* 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 . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*
* $ Header $
*/
//------------------------------------------------------------------------------------
// BUILD_DISPLAY.CPP like the old spr_engi but slightly more aptly named
//------------------------------------------------------------------------------------
//#include <mmsystem.h>
# include <stdarg.h>
# include <stdio.h>
# include <stdlib.h>
//#include <windows.h>
//#include <windowsx.h>
2003-07-28 03:12:49 +00:00
# include "stdafx.h"
2003-07-28 01:44:38 +00:00
# include "driver/driver96.h"
# include "build_display.h"
# include "console.h"
# include "debug.h"
# include "defs.h"
# include "events.h"
# include "function.h"
# include "header.h"
# include "interpreter.h"
# include "layers.h"
# include "logic.h"
# include "maketext.h"
# include "memory.h"
# include "mouse.h"
# include "object.h"
# include "protocol.h"
# include "resman.h"
# include "router.h"
# include "save_rest.h"
# include "scroll.h"
# include "sword2.h"
//------------------------------------------------------------------------------------
buildit bgp0_list [ MAX_bgp0_sprites ] ;
buildit bgp1_list [ MAX_bgp1_sprites ] ;
buildit back_list [ MAX_back_sprites ] ;
buildit sort_list [ MAX_sort_sprites ] ;
buildit fore_list [ MAX_fore_sprites ] ;
buildit fgp0_list [ MAX_fgp0_sprites ] ;
buildit fgp1_list [ MAX_fgp1_sprites ] ;
uint16 sort_order [ MAX_sort_sprites ] ; //holds the order of the sort list - i.e the list stays static and we sort this
uint32 cur_bgp0 ;
uint32 cur_bgp1 ;
uint32 cur_back ;
uint32 cur_sort ;
uint32 cur_fore ;
uint32 cur_fgp0 ;
uint32 cur_fgp1 ;
2003-07-30 19:25:31 +00:00
# ifdef _SWORD2_DEBUG
2003-07-28 01:44:38 +00:00
uint32 largest_layer_area = 0 ; // should be reset to zero at start of each screen change
uint32 largest_sprite_area = 0 ; // - " -
char largest_layer_info [ 128 ] = { " largest layer: none registered " } ;
char largest_sprite_info [ 128 ] = { " largest sprite: none registered " } ;
# endif
//------------------------------------------------------------------------------------
// last palette used - so that we can restore the correct one after a pause (which dims the screen)
// - and it's not always the main screen palette that we want, eg. during the eclipse
// This flag gets set in Start_new_palette() and SetFullPalette()
uint32 lastPaletteRes = 0 ;
//------------------------------------------------------------------------------------
// 'frames per second' counting stuff
uint32 fps = 0 ;
uint32 cycleTime = 0 ;
uint32 frameCount = 0 ;
extern uint32 mouse_status ; // So I know if the control Panel can be activated - CJR 1-5-97
//------------------------------------------------------------------------------------
// function prototypes not needed externally
void Start_new_palette ( void ) ; //Tony25Sept96
void Register_frame ( int32 * params , buildit * build_unit ) ; // (1nov96JEL)
void Process_layer ( uint32 layer_number ) ; //Tony24Sept96
void Sort_the_sort_list ( void ) ; //Tony18Sept96
void Send_back_par0_frames ( void ) ; //James23Jan97
void Send_back_par1_frames ( void ) ; //James23Jan97
void Send_back_frames ( void ) ; //Tony23Sept96
void Send_sort_frames ( void ) ;
void Send_fore_frames ( void ) ;
void Send_fore_par0_frames ( void ) ; //James23Jan97
void Send_fore_par1_frames ( void ) ; //James23Jan97
//------------------------------------------------------------------------------------
//
// PC Build_display
//
//------------------------------------------------------------------------------------
void Build_display ( void ) //Tony21Sept96
{
BOOL end ;
2003-07-30 19:25:31 +00:00
# ifdef _SWORD2_DEBUG
2003-07-28 01:44:38 +00:00
uint8 pal [ 12 ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 255 , 0 , 0 } ;
2003-07-28 02:10:24 +00:00
# endif
2003-07-28 01:44:38 +00:00
uint8 * file ;
_multiScreenHeader * screenLayerTable ;
2003-07-30 19:25:31 +00:00
# ifdef _SWORD2_DEBUG // only used by console
2003-07-28 01:44:38 +00:00
_spriteInfo spriteInfo ;
uint32 rv ; // drivers error return value
# endif
if ( ( ! console_status ) & & ( this_screen . new_palette ) )
{
Start_new_palette ( ) ; // start the layer palette fading up
2003-07-30 19:25:31 +00:00
# ifdef _SWORD2_DEBUG // (James23jun97)
2003-07-28 01:44:38 +00:00
largest_layer_area = 0 ; // should be reset to zero at start of each screen change
largest_sprite_area = 0 ; // - " -
# endif
}
if ( ( ! console_status ) & & ( this_screen . background_layer_id ) ) // there is a valid screen to run
{
SetScrollTarget ( this_screen . scroll_offset_x , this_screen . scroll_offset_y ) ; // set the scroll position
AnimateMouse ( ) ; // increment the mouse frame
StartRenderCycle ( ) ;
while ( 1 ) // START OF RENDER CYCLE
{
//----------------------------------------------------
// clear the back buffer, before building up the new screen
// from the back forwards
EraseBackBuffer ( ) ;
//----------------------------------------------------
// first background parallax + related anims
file = res_man . Res_open ( this_screen . background_layer_id ) ; // open the screen resource
screenLayerTable = ( _multiScreenHeader * ) ( ( uint8 * ) file + sizeof ( _standardHeader ) ) ;
if ( screenLayerTable - > bg_parallax [ 0 ] )
{
RenderParallax ( FetchBackgroundParallaxLayer ( file , 0 ) , 0 ) ;
res_man . Res_close ( this_screen . background_layer_id ) ; // release the screen resource before cacheing the sprites
Send_back_par0_frames ( ) ;
}
else
res_man . Res_close ( this_screen . background_layer_id ) ; // release the screen resource
//----------------------------------------------------
// second background parallax + related anims
file = res_man . Res_open ( this_screen . background_layer_id ) ; // open the screen resource
screenLayerTable = ( _multiScreenHeader * ) ( ( uint8 * ) file + sizeof ( _standardHeader ) ) ;
if ( screenLayerTable - > bg_parallax [ 1 ] )
{
RenderParallax ( FetchBackgroundParallaxLayer ( file , 1 ) , 1 ) ;
res_man . Res_close ( this_screen . background_layer_id ) ; // release the screen resource before cacheing the sprites
Send_back_par1_frames ( ) ;
}
else
res_man . Res_close ( this_screen . background_layer_id ) ; // release the screen resource
//----------------------------------------------------
// normal backround layer (just the one!)
file = res_man . Res_open ( this_screen . background_layer_id ) ; // open the screen resource
RenderParallax ( FetchBackgroundLayer ( file ) , 2 ) ;
res_man . Res_close ( this_screen . background_layer_id ) ; // release the screen resource
//----------------------------------------------------
// sprites & layers
Send_back_frames ( ) ; // background sprites
Sort_the_sort_list ( ) ;
Send_sort_frames ( ) ; // sorted sprites & layers
Send_fore_frames ( ) ; // foreground sprites
//----------------------------------------------------
// first foreground parallax + related anims
file = res_man . Res_open ( this_screen . background_layer_id ) ; // open the screen resource
screenLayerTable = ( _multiScreenHeader * ) ( ( uint8 * ) file + sizeof ( _standardHeader ) ) ;
if ( screenLayerTable - > fg_parallax [ 0 ] )
{
RenderParallax ( FetchForegroundParallaxLayer ( file , 0 ) , 3 ) ;
res_man . Res_close ( this_screen . background_layer_id ) ; // release the screen resource before cacheing the sprites
Send_fore_par0_frames ( ) ;
}
else
res_man . Res_close ( this_screen . background_layer_id ) ; // release the screen resource
//----------------------------------------------------
// second foreground parallax + related anims
file = res_man . Res_open ( this_screen . background_layer_id ) ; // open the screen resource
screenLayerTable = ( _multiScreenHeader * ) ( ( uint8 * ) file + sizeof ( _standardHeader ) ) ;
if ( screenLayerTable - > fg_parallax [ 1 ] )
{
RenderParallax ( FetchForegroundParallaxLayer ( file , 1 ) , 4 ) ;
res_man . Res_close ( this_screen . background_layer_id ) ; // release the screen resource before cacheing the sprites
Send_fore_par1_frames ( ) ;
}
else
res_man . Res_close ( this_screen . background_layer_id ) ; // release the screen resource
//----------------------------------------------------
// walkgrid, mouse & player markers & mouse area rectangle
Draw_debug_graphics ( ) ; // JAMES (08apr97)
//----------------------------------------------------
// text blocks
Print_text_blocs ( ) ; // speech blocks and headup debug text
//----------------------------------------------------
// menu bar & icons
ProcessMenu ( ) ;
//----------------------------------------------------
// ready - blit to screen
CopyScreenBuffer ( ) ;
//----------------------------------------------------
// update our fps reading
frameCount + = 1 ;
2003-07-28 07:47:21 +00:00
if ( SVM_timeGetTime ( ) > cycleTime )
2003-07-28 01:44:38 +00:00
{
fps = frameCount ;
2003-08-23 13:02:21 +00:00
debug ( 2 , " FPS: %d " , fps ) ;
2003-07-28 01:44:38 +00:00
frameCount = 0 ;
2003-07-28 07:47:21 +00:00
cycleTime = SVM_timeGetTime ( ) + 1000 ;
2003-07-28 01:44:38 +00:00
}
//----------------------------------------------------
// check if we've got time to render the screen again this cycle
// (so drivers can smooth out the scrolling in between normal game cycles)
2003-08-28 12:26:28 +00:00
// FIXME: If we have already reached the scroll target,
// we should sleep for the rest of the render cycle.
2003-07-28 01:44:38 +00:00
EndRenderCycle ( & end ) ;
if ( end ) // if we haven't got time to render again this cycle, drop out of 'render cycle' while-loop
break ;
if ( ServiceWindows ( ) = = RDERR_APPCLOSED ) // if the game is being shut down, drop out
break ;
//----------------------------------------------------
} // END OF RENDER CYCLE
}
2003-07-30 19:25:31 +00:00
# ifdef _SWORD2_DEBUG
2003-07-28 01:44:38 +00:00
else if ( console_status )
{
spriteInfo . x = 0 ;
spriteInfo . y = con_y ;
spriteInfo . w = con_width ;
spriteInfo . h = con_depth ;
spriteInfo . scale = 0 ;
spriteInfo . scaledWidth = 0 ;
spriteInfo . scaledHeight = 0 ;
spriteInfo . type = RDSPR_DISPLAYALIGN + RDSPR_NOCOMPRESSION ; // no compression!
spriteInfo . blend = 0 ;
spriteInfo . data = console_sprite - > ad ;
spriteInfo . colourTable = 0 ;
rv = DrawSprite ( & spriteInfo ) ;
if ( rv )
ExitWithReport ( " Driver Error %.8x (drawing console) [%s line %u] " , rv , __FILE__ , __LINE__ ) ;
CopyScreenBuffer ( ) ;
}
else
{
StartConsole ( ) ;
2003-08-23 14:42:37 +00:00
BS2_SetPalette ( 0 , 3 , pal , RDPAL_INSTANT ) ; //force the palette
2003-07-28 01:44:38 +00:00
Print_to_console ( " no valid screen? " ) ;
}
2003-07-30 19:25:31 +00:00
# endif // _SWORD2_DEBUG
2003-07-28 01:44:38 +00:00
}
//------------------------------------------------------------------------------------
//
// Fades down and displays a message on the screen for time seconds
//
void DisplayMsg ( uint8 * text , int time ) // Chris 15May97
{
mem * text_spr ;
_frameHeader * frame ;
_spriteInfo spriteInfo ;
_palEntry pal [ 256 ] ;
_palEntry oldPal [ 256 ] ;
int16 oldY ;
int16 oldX ;
uint32 rv ; // drivers error return value
warning ( " DisplayMsg: %s " , ( char * ) text ) ;
if ( GetFadeStatus ( ) ! = RDFADE_BLACK )
{
FadeDown ( ( float ) 0.75 ) ;
do
{
//--------------------------------------------------
// Service windows
while ( ! gotTheFocus )
if ( ServiceWindows ( ) = = RDERR_APPCLOSED )
break ;
if ( ServiceWindows ( ) = = RDERR_APPCLOSED ) // if we pressed Ctrl-Q
{
Close_game ( ) ; //close engine systems down
CloseAppWindow ( ) ;
exit ( 0 ) ; //quit the game
}
//--------------------------------------------------
}
while ( GetFadeStatus ( ) = = RDFADE_DOWN ) ;
}
2003-07-28 03:49:25 +00:00
Set_mouse ( 0 ) ;
2003-07-28 01:44:38 +00:00
Set_luggage ( 0 ) ; //tw28Aug
EraseBackBuffer ( ) ; // for hardware rendering
EraseSoftwareScreenBuffer ( ) ; // for software rendering
text_spr = MakeTextSprite ( text , 640 , 187 , speech_font_id ) ;
frame = ( _frameHeader * ) text_spr - > ad ;
spriteInfo . x = screenWide / 2 - frame - > width / 2 ;
if ( ! time )
spriteInfo . y = screenDeep / 2 - frame - > height / 2 - RDMENU_MENUDEEP ;
else
spriteInfo . y = 400 - frame - > height ;
spriteInfo . w = frame - > width ;
spriteInfo . h = frame - > height ;
spriteInfo . scale = 0 ;
spriteInfo . scaledWidth = 0 ;
spriteInfo . scaledHeight = 0 ;
spriteInfo . type = RDSPR_DISPLAYALIGN + RDSPR_NOCOMPRESSION + RDSPR_TRANS ;
spriteInfo . blend = 0 ;
spriteInfo . data = text_spr - > ad + sizeof ( _frameHeader ) ;
spriteInfo . colourTable = 0 ;
oldX = spriteInfo . x ;
oldY = spriteInfo . y ;
rv = DrawSprite ( & spriteInfo ) ;
if ( rv )
ExitWithReport ( " Driver Error %.8x (in DisplayMsg) [%s line %u] " , rv , __FILE__ , __LINE__ ) ;
spriteInfo . x = oldX ;
spriteInfo . y = oldY ;
memcpy ( ( char * ) oldPal , ( char * ) palCopy , 256 * sizeof ( _palEntry ) ) ;
memset ( pal , 0 , 256 * sizeof ( _palEntry ) ) ;
pal [ 187 ] . red = 255 ;
pal [ 187 ] . green = 255 ;
pal [ 187 ] . blue = 255 ;
2003-08-23 14:42:37 +00:00
BS2_SetPalette ( 0 , 256 , ( uint8 * ) pal , RDPAL_FADE ) ;
2003-07-28 01:44:38 +00:00
CopyScreenBuffer ( ) ;
FadeUp ( ( float ) 0.75 ) ;
Free_mem ( text_spr ) ;
do
{
//--------------------------------------------------
// Service windows
while ( ! gotTheFocus )
if ( ServiceWindows ( ) = = RDERR_APPCLOSED )
break ;
if ( ServiceWindows ( ) = = RDERR_APPCLOSED ) // if we pressed Ctrl-Q
{
Close_game ( ) ; //close engine systems down
CloseAppWindow ( ) ;
exit ( 0 ) ; //quit the game
}
//--------------------------------------------------
}
while ( GetFadeStatus ( ) = = RDFADE_UP ) ;
2003-07-28 08:04:03 +00:00
uint32 targetTime = SVM_timeGetTime ( ) + ( time * 1000 ) ;
2003-07-28 01:44:38 +00:00
2003-07-28 07:47:21 +00:00
while ( SVM_timeGetTime ( ) < targetTime )
2003-07-28 01:44:38 +00:00
{
//--------------------------------------------------
// Service windows
while ( ! gotTheFocus )
if ( ServiceWindows ( ) = = RDERR_APPCLOSED )
break ;
if ( ServiceWindows ( ) = = RDERR_APPCLOSED ) // if we pressed Ctrl-Q
{
Close_game ( ) ; //close engine systems down
CloseAppWindow ( ) ;
exit ( 0 ) ; //quit the game
}
//--------------------------------------------------
EraseBackBuffer ( ) ; // for hardware rendering
EraseSoftwareScreenBuffer ( ) ; // for software rendering
rv = DrawSprite ( & spriteInfo ) ; // Keep the message there even when the user task swaps.
if ( rv )
ExitWithReport ( " Driver Error %.8x (in DisplayMsg) [%s line %u] " , rv , __FILE__ , __LINE__ ) ;
spriteInfo . y = oldY ; // Drivers change the y co-ordinate, don't know why...
spriteInfo . x = oldX ;
CopyScreenBuffer ( ) ;
}
2003-08-23 14:42:37 +00:00
BS2_SetPalette ( 0 , 256 , ( uint8 * ) oldPal , RDPAL_FADE ) ;
2003-07-28 01:44:38 +00:00
}
//------------------------------------------------------------------------------------
//
// Fades message down and removes it, fading up again afterwards
//
void RemoveMsg ( void ) // Chris 15May97
{
FadeDown ( ( float ) 0.75 ) ;
do
{
//--------------------------------------------------
// Service windows
while ( ! gotTheFocus )
if ( ServiceWindows ( ) = = RDERR_APPCLOSED )
break ;
if ( ServiceWindows ( ) = = RDERR_APPCLOSED ) // if we pressed Ctrl-Q
{
Close_game ( ) ; //close engine systems down
CloseAppWindow ( ) ;
exit ( 0 ) ; //quit the game
}
//--------------------------------------------------
}
while ( GetFadeStatus ( ) = = RDFADE_DOWN ) ;
EraseBackBuffer ( ) ; // for hardware rendering
EraseSoftwareScreenBuffer ( ) ; // for software rendering
CopyScreenBuffer ( ) ;
// FadeUp((float)0.75);
// removed by JEL (08oct97) to prevent "eye" smacker corruption when restarting game from CD2
// and also to prevent palette flicker when restoring game to a different CD
// - since the "insert CD" message uses this routine to clean up!
}
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
void Send_back_par0_frames ( void ) //James23Jan97
{
uint32 j ;
for ( j = 0 ; j < cur_bgp0 ; j + + ) // could be none at all - theoretically at least
{
Process_image ( & bgp0_list [ j ] ) ; // frame attached to 1st background parallax
}
}
//------------------------------------------------------------------------------------
void Send_back_par1_frames ( void ) //James23Jan97
{
uint32 j ;
for ( j = 0 ; j < cur_bgp1 ; j + + ) // could be none at all - theoretically at least
{
Process_image ( & bgp1_list [ j ] ) ; // frame attached to 1nd background parallax
}
}
//------------------------------------------------------------------------------------
void Send_back_frames ( void ) //Tony23Sept96
{
uint32 j ;
for ( j = 0 ; j < cur_back ; j + + ) // could be none at all - theoretically at least
{
Process_image ( & back_list [ j ] ) ;
}
}
//------------------------------------------------------------------------------------
void Send_sort_frames ( void ) //Tony23Sept96
{
//send the sort frames for printing - layers, shrinkers & normal flat sprites
uint32 j ;
for ( j = 0 ; j < cur_sort ; j + + ) // could be none at all - theoretically at least
{
if ( sort_list [ sort_order [ j ] ] . layer_number ) //its a layer - minus 1 for true layer number
Process_layer ( sort_list [ sort_order [ j ] ] . layer_number - 1 ) ; //we need to know from the buildit because the layers will have been sorted in random order
else
Process_image ( & sort_list [ sort_order [ j ] ] ) ; // sprite
}
}
//------------------------------------------------------------------------------------
void Send_fore_frames ( void ) //Tony23Sept96
{
uint32 j ;
for ( j = 0 ; j < cur_fore ; j + + ) // could be none at all - theoretically at least
{
Process_image ( & fore_list [ j ] ) ;
}
}
//------------------------------------------------------------------------------------
void Send_fore_par0_frames ( void ) //James23Jan97
{
uint32 j ;
for ( j = 0 ; j < cur_fgp0 ; j + + ) // could be none at all - theoretically at least
{
Process_image ( & fgp0_list [ j ] ) ; // frame attached to 1st foreground parallax
}
}
//------------------------------------------------------------------------------------
void Send_fore_par1_frames ( void ) //James23Jan97
{
uint32 j ;
for ( j = 0 ; j < cur_fgp1 ; j + + ) // could be none at all - theoretically at least
{
Process_image ( & fgp1_list [ j ] ) ; // frame attached to 2nd foreground parallax
}
}
//------------------------------------------------------------------------------------
void Process_layer ( uint32 layer_number ) //Tony24Sept96
{
uint8 * file ;
_layerHeader * layer_head ;
_spriteInfo spriteInfo ;
uint32 rv ;
2003-07-30 19:25:31 +00:00
# ifdef _SWORD2_DEBUG
2003-07-28 01:44:38 +00:00
uint32 current_layer_area = 0 ;
# endif
file = res_man . Res_open ( this_screen . background_layer_id ) ; // file points to 1st byte in the layer file
layer_head = FetchLayerHeader ( file , layer_number ) ; // point to layer header
spriteInfo . x = layer_head - > x ;
spriteInfo . y = layer_head - > y ;
spriteInfo . w = layer_head - > width ;
spriteInfo . scale = 0 ;
spriteInfo . scaledWidth = 0 ;
spriteInfo . scaledHeight = 0 ;
spriteInfo . h = layer_head - > height ;
spriteInfo . type = RDSPR_TRANS + RDSPR_RLE256FAST ;
spriteInfo . blend = 0 ;
spriteInfo . data = file + sizeof ( _standardHeader ) + layer_head - > offset ;
spriteInfo . colourTable = 0 ;
//------------------------------------------
// check for largest layer for debug info
2003-07-30 19:25:31 +00:00
# ifdef _SWORD2_DEBUG
2003-07-28 01:44:38 +00:00
current_layer_area = layer_head - > width * layer_head - > height ;
if ( current_layer_area > largest_layer_area )
{
largest_layer_area = current_layer_area ;
sprintf ( largest_layer_info , " largest layer: %s layer(%d) is %dx%d " , FetchObjectName ( this_screen . background_layer_id ) , layer_number , layer_head - > width , layer_head - > height ) ;
}
# endif
//------------------------------------------
rv = DrawSprite ( & spriteInfo ) ;
if ( rv )
ExitWithReport ( " Driver Error %.8x in Process_layer(%d) [%s line %u] " , rv , layer_number , __FILE__ , __LINE__ ) ;
res_man . Res_close ( this_screen . background_layer_id ) ;
}
//------------------------------------------------------------------------------------
void Process_image ( buildit * build_unit ) // (5nov96 JEL)
{
uint8 * file , * colTablePtr = NULL ;
_animHeader * anim_head ;
_frameHeader * frame_head ;
_cdtEntry * cdt_entry ;
_spriteInfo spriteInfo ;
uint32 spriteType ;
uint32 rv ;
2003-07-30 19:25:31 +00:00
# ifdef _SWORD2_DEBUG
2003-07-28 01:44:38 +00:00
uint32 current_sprite_area = 0 ;
# endif
file = res_man . Res_open ( build_unit - > anim_resource ) ; // open anim resource file & point to base
anim_head = FetchAnimHeader ( file ) ;
cdt_entry = FetchCdtEntry ( file , build_unit - > anim_pc ) ;
frame_head = FetchFrameHeader ( file , build_unit - > anim_pc ) ;
spriteType = RDSPR_TRANS ; // so that 0-colour is transparent
if ( anim_head - > blend )
spriteType + = RDSPR_BLEND ;
if ( ( cdt_entry - > frameType ) & FRAME_FLIPPED ) // if the frame is to be flipped (only really applicable to frames using offsets)
spriteType + = RDSPR_FLIP ;
if ( ( cdt_entry - > frameType ) & FRAME_256_FAST )
{
if ( ( build_unit - > scale ) | | ( anim_head - > blend ) | | ( build_unit - > shadingFlag ) ) // scaling, shading & blending don't work with RLE256FAST
spriteType + = RDSPR_RLE256 ; // but the same compression can be decompressed using the RLE256 routines!
else
spriteType + = RDSPR_RLE256FAST ;
}
else
{
switch ( anim_head - > runTimeComp ) // what compression was used?
{
case NONE :
spriteType + = RDSPR_NOCOMPRESSION ;
break ;
case RLE256 :
spriteType + = RDSPR_RLE256 ;
break ;
case RLE16 :
spriteType + = RDSPR_RLE16 ;
colTablePtr = ( uint8 * ) ( anim_head + 1 ) + anim_head - > noAnimFrames * sizeof ( _cdtEntry ) ;
// points to just after last cdt_entry, ie. start of colour table
break ;
}
}
if ( build_unit - > shadingFlag = = 1 ) // if we want this frame to be affected by the shading mask
spriteType + = RDSPR_SHADOW ; // add the status bit
spriteInfo . x = build_unit - > x ;
spriteInfo . y = build_unit - > y ;
spriteInfo . w = frame_head - > width ;
spriteInfo . h = frame_head - > height ;
spriteInfo . scale = build_unit - > scale ;
spriteInfo . scaledWidth = build_unit - > scaled_width ;
spriteInfo . scaledHeight = build_unit - > scaled_height ;
spriteInfo . type = spriteType ;
spriteInfo . blend = anim_head - > blend ;
spriteInfo . data = ( uint8 * ) ( frame_head + 1 ) ; // points to just after frame header, ie. start of sprite data
spriteInfo . colourTable = colTablePtr ;
//------------------------------------------
// check for largest layer for debug info
2003-07-30 19:25:31 +00:00
# ifdef _SWORD2_DEBUG
2003-07-28 01:44:38 +00:00
current_sprite_area = frame_head - > width * frame_head - > height ;
if ( current_sprite_area > largest_sprite_area )
{
largest_sprite_area = current_sprite_area ;
sprintf ( largest_sprite_info , " largest sprite: %s frame(%d) is %dx%d " , FetchObjectName ( build_unit - > anim_resource ) , build_unit - > anim_pc , frame_head - > width , frame_head - > height ) ;
}
# endif
//------------------------------------------
//-----------------------------------------------------------
2003-07-30 19:25:31 +00:00
# ifdef _SWORD2_DEBUG
2003-07-28 01:44:38 +00:00
if ( SYSTEM_TESTING_ANIMS ) // see anims.cpp
{
if ( ( spriteInfo . x + spriteInfo . scaledWidth ) > = 639 ) // bring the anim into the visible screen
spriteInfo . x = 639 - spriteInfo . scaledWidth ; // but leave extra pixel at edge for box
if ( ( spriteInfo . y + spriteInfo . scaledHeight ) > = 399 )
spriteInfo . y = 399 - spriteInfo . scaledHeight ;
if ( spriteInfo . x < 1 )
spriteInfo . x = 1 ;
if ( spriteInfo . y < 1 )
spriteInfo . y = 1 ;
rect_x1 = spriteInfo . x - 1 ; // create box to surround sprite - just outside sprite box
rect_y1 = spriteInfo . y - 1 ;
rect_x2 = spriteInfo . x + spriteInfo . scaledWidth ;
rect_y2 = spriteInfo . y + spriteInfo . scaledHeight ;
}
# endif
//-----------------------------------------------------------
//--------------------------------------------------
2003-07-30 19:25:31 +00:00
// #ifdef _SWORD2_DEBUG
2003-07-28 01:44:38 +00:00
// if (frame_head->width <= 1)
// {
// Zdebug(8,"WARNING: 1-pixel-wide frame found in %s (%d)", FetchObjectName(build_unit->anim_resource), build_unit->anim_resource);
// }
// #endif
//--------------------------------------------------
rv = DrawSprite ( & spriteInfo ) ;
if ( rv )
ExitWithReport ( " Driver Error %.8x with sprite %s (%d) in Process_image [%s line %u] " , rv , FetchObjectName ( build_unit - > anim_resource ) , build_unit - > anim_resource , __FILE__ , __LINE__ ) ;
res_man . Res_close ( build_unit - > anim_resource ) ; // release the anim resource
}
//------------------------------------------------------------------------------------
void Reset_render_lists ( void ) //Tony18Sept96
{
//reset the sort lists - do this before a logic loop
//takes into account the fact that the start of the list is pre-built with the special sortable layers
uint32 j ;
cur_bgp0 = 0 ;
cur_bgp1 = 0 ;
cur_back = 0 ;
cur_sort = this_screen . number_of_layers ; //beginning of sort list is setup with the special sort layers
cur_fore = 0 ;
cur_fgp0 = 0 ;
cur_fgp1 = 0 ;
if ( cur_sort ) //there are some layers - so rebuild the sort order positioning
for ( j = 0 ; j < cur_sort ; j + + )
sort_order [ j ] = j ; //rebuild the order list
}
//------------------------------------------------------------------------------------
void Sort_the_sort_list ( void ) //Tony18Sept96
{
//sort the list
uint16 i , j , swap ;
//sort the list
if ( cur_sort > 1 ) //cannot bubble sort 0 or 1 items!
for ( i = 0 ; i < cur_sort - 1 ; i + + )
for ( j = 0 ; j < cur_sort - 1 ; j + + )
if ( sort_list [ sort_order [ j ] ] . sort_y > sort_list [ sort_order [ j + 1 ] ] . sort_y ) //this > next then swap
{ swap = sort_order [ j ] ;
sort_order [ j ] = sort_order [ j + 1 ] ;
sort_order [ j + 1 ] = swap ;
}
}
//------------------------------------------------------------------------------------
void Register_frame ( int32 * params , buildit * build_unit ) // (1nov96JEL)
{
// params: 0 pointer to mouse structure or NULL for no write to mouse list (non-zero means write sprite-shape to mouse list)
// 1 pointer to graphic structure
// 2 pointer to mega structure
Object_mega * ob_mega ;
Object_graphic * ob_graph ;
Object_mouse * ob_mouse ;
uint8 * file ;
_frameHeader * frame_head ;
_animHeader * anim_head ;
_cdtEntry * cdt_entry ;
int scale = 0 ;
//-------------------------------------------
// open animation file & set up the necessary pointers
ob_graph = ( Object_graphic * ) params [ 1 ] ;
2003-07-30 19:25:31 +00:00
# ifdef _SWORD2_DEBUG
2003-07-28 01:44:38 +00:00
if ( ob_graph - > anim_resource = = 0 )
Con_fatal_error ( " ERROR: %s(%d) has no anim resource in Register_frame [line=%d file=%s] " , FetchObjectName ( ID ) , ID , __LINE__ , __FILE__ ) ;
# endif
file = res_man . Res_open ( ob_graph - > anim_resource ) ;
anim_head = FetchAnimHeader ( file ) ;
cdt_entry = FetchCdtEntry ( file , ob_graph - > anim_pc ) ;
frame_head = FetchFrameHeader ( file , ob_graph - > anim_pc ) ;
2003-07-30 19:25:31 +00:00
# ifdef _SWORD2_DEBUG
2003-07-28 01:44:38 +00:00
if ( ID = = CUR_PLAYER_ID ) // update player graphic details for on-screen debug info
{
playerGraphic . type = ob_graph - > type ;
playerGraphic . anim_resource = ob_graph - > anim_resource ;
playerGraphic . anim_pc = ob_graph - > anim_pc + 1 ; // counting 1st frame as 'frame 1'
player_graphic_no_frames = anim_head - > noAnimFrames ;
}
# endif
//-------------------------------------------
// fill in the buildit structure for this frame
build_unit - > anim_resource = ob_graph - > anim_resource ; //retrieve the resource
build_unit - > anim_pc = ob_graph - > anim_pc ; //retrieve the frame
build_unit - > layer_number = 0 ; //not a layer
if ( ob_graph - > type & SHADED_SPRITE )
build_unit - > shadingFlag = 1 ; // affected by shading mask
else
build_unit - > shadingFlag = 0 ; // not shaded
//-------------------------------------------
// check if this frame has offsets ie. this is a scalable mega frame
if ( ( cdt_entry - > frameType ) & FRAME_OFFSET )
{
ob_mega = ( Object_mega * ) params [ 2 ] ; // param 2 is pointer to mega structure
// calc scale at which to print the sprite, based on feet y-coord & scaling constants (NB. 'scale' is actually 256*true_scale, to maintain accuracy)
scale = ( ob_mega - > scale_a * ob_mega - > feet_y + ob_mega - > scale_b ) / 256 ; // Ay+B gives 256*scale ie. 256*256*true_scale for even better accuracy, ie. scale = (Ay+B)/256
// calc final render coordinates (top-left of sprite), based on feet coords & scaled offsets
build_unit - > x = ob_mega - > feet_x + ( cdt_entry - > x * scale ) / 256 ; // add scaled offsets to feet coords
build_unit - > y = ob_mega - > feet_y + ( cdt_entry - > y * scale ) / 256 ;
// work out new width and height
build_unit - > scaled_width = ( ( scale * frame_head - > width ) / 256 ) ; // always divide by 256 after everything else, to maintain accurary
build_unit - > scaled_height = ( ( scale * frame_head - > height ) / 256 ) ;
}
else // it's a non-scaling anim
{
// get render coords for sprite, from cdt
build_unit - > x = cdt_entry - > x ; //retrieve the x
build_unit - > y = cdt_entry - > y ; //retrieve the y
// get width and height
build_unit - > scaled_width = frame_head - > width ;
build_unit - > scaled_height = frame_head - > height ;
}
//-------------------------------------------
build_unit - > scale = scale ; // either 0 or required scale, depending on whether 'scale' computed
// calc the bottom y-coord for sorting purposes
build_unit - > sort_y = build_unit - > y + build_unit - > scaled_height - 1 ;
//-------------------------------------------
if ( params [ 0 ] ) // passed a mouse structure, so add to the mouse_list
{
ob_mouse = ( Object_mouse * ) params [ 0 ] ;
if ( ob_mouse - > pointer ) // only if 'pointer' isn't NULL (James13feb97)
{
2003-07-30 19:25:31 +00:00
# ifdef _SWORD2_DEBUG
2003-07-28 01:44:38 +00:00
if ( cur_mouse = = TOTAL_mouse_list )
Con_fatal_error ( " ERROR: mouse_list full [%s line %u] " , __FILE__ , __LINE__ ) ;
# endif
mouse_list [ cur_mouse ] . x1 = build_unit - > x ;
mouse_list [ cur_mouse ] . y1 = build_unit - > y ;
mouse_list [ cur_mouse ] . x2 = build_unit - > x + build_unit - > scaled_width ;
mouse_list [ cur_mouse ] . y2 = build_unit - > y + build_unit - > scaled_height ;
mouse_list [ cur_mouse ] . priority = ob_mouse - > priority ;
mouse_list [ cur_mouse ] . pointer = ob_mouse - > pointer ;
//-----------------------------------------------
// (James17jun97)
// check if pointer text field is set due to previous object using this slot (ie. not correct for this one)
if ( ( mouse_list [ cur_mouse ] . pointer_text ) & & ( mouse_list [ cur_mouse ] . id ! = ( int32 ) ID ) ) // if 'pointer_text' field is set, but the 'id' field isn't same is current id
mouse_list [ cur_mouse ] . pointer_text = 0 ; // then we don't want this "left over" pointer text
//-----------------------------------------------
mouse_list [ cur_mouse ] . id = ID ;
mouse_list [ cur_mouse ] . anim_resource = 0 ; // not using sprite as detection mask
mouse_list [ cur_mouse ] . anim_pc = 0 ;
cur_mouse + + ;
}
}
//-------------------------------------------
res_man . Res_close ( ob_graph - > anim_resource ) ; // close animation file
}
//------------------------------------------------------------------------------------
int32 FN_register_frame ( int32 * params ) // (27nov96 JEL)
{
//this call would be made from an objects service script 0
// params: 0 pointer to mouse structure or NULL for no write to mouse list (non-zero means write sprite-shape to mouse list)
// 1 pointer to graphic structure
// 2 pointer to mega structure or NULL if not a mega
Object_graphic * ob_graph = ( Object_graphic * ) params [ 1 ] ;
switch ( ob_graph - > type & 0x0000ffff ) // check low word for sprite type
{
//---------------
case BGP0_SPRITE :
{
2003-07-30 19:25:31 +00:00
# ifdef _SWORD2_DEBUG
2003-07-28 01:44:38 +00:00
if ( cur_bgp0 = = MAX_bgp0_sprites )
Con_fatal_error ( " ERROR: bgp0_list full in FN_register_frame [line=%d file=%s] " , __LINE__ , __FILE__ ) ;
# endif
Register_frame ( params , & bgp0_list [ cur_bgp0 ] ) ;
cur_bgp0 + + ;
}
break ;
//---------------
case BGP1_SPRITE :
{
2003-07-30 19:25:31 +00:00
# ifdef _SWORD2_DEBUG
2003-07-28 01:44:38 +00:00
if ( cur_bgp1 = = MAX_bgp1_sprites )
Con_fatal_error ( " ERROR: bgp1_list full in FN_register_frame [line=%d file=%s] " , __LINE__ , __FILE__ ) ;
# endif
Register_frame ( params , & bgp1_list [ cur_bgp1 ] ) ;
cur_bgp1 + + ;
}
break ;
//---------------
case BACK_SPRITE :
{
2003-07-30 19:25:31 +00:00
# ifdef _SWORD2_DEBUG
2003-07-28 01:44:38 +00:00
if ( cur_back = = MAX_back_sprites )
Con_fatal_error ( " ERROR: back_list full in FN_register_frame [line=%d file=%s] " , __LINE__ , __FILE__ ) ;
# endif
Register_frame ( params , & back_list [ cur_back ] ) ;
cur_back + + ;
}
break ;
//---------------
case SORT_SPRITE :
{
2003-07-30 19:25:31 +00:00
# ifdef _SWORD2_DEBUG
2003-07-28 01:44:38 +00:00
if ( cur_sort = = MAX_sort_sprites )
Con_fatal_error ( " ERROR: sort_list full in FN_register_frame [line=%d file=%s] " , __LINE__ , __FILE__ ) ;
# endif
sort_order [ cur_sort ] = cur_sort ;
Register_frame ( params , & sort_list [ cur_sort ] ) ;
cur_sort + + ;
}
break ;
//---------------
case FORE_SPRITE :
{
2003-07-30 19:25:31 +00:00
# ifdef _SWORD2_DEBUG
2003-07-28 01:44:38 +00:00
if ( cur_fore = = MAX_fore_sprites )
Con_fatal_error ( " ERROR: fore_list full in FN_register_frame [line=%d file=%s] " , __LINE__ , __FILE__ ) ;
# endif
Register_frame ( params , & fore_list [ cur_fore ] ) ;
cur_fore + + ;
}
break ;
//---------------
case FGP0_SPRITE :
{
2003-07-30 19:25:31 +00:00
# ifdef _SWORD2_DEBUG
2003-07-28 01:44:38 +00:00
if ( cur_fgp0 = = MAX_fgp0_sprites )
Con_fatal_error ( " ERROR: fgp0_list full in FN_register_frame [line=%d file=%s] " , __LINE__ , __FILE__ ) ;
# endif
Register_frame ( params , & fgp0_list [ cur_fgp0 ] ) ;
cur_fgp0 + + ;
}
break ;
//---------------
case FGP1_SPRITE :
{
2003-07-30 19:25:31 +00:00
# ifdef _SWORD2_DEBUG
2003-07-28 01:44:38 +00:00
if ( cur_fgp1 = = MAX_fgp1_sprites )
Con_fatal_error ( " ERROR: fgp1_list full in FN_register_frame [line=%d file=%s] " , __LINE__ , __FILE__ ) ;
# endif
Register_frame ( params , & fgp1_list [ cur_fgp1 ] ) ;
cur_fgp1 + + ;
}
break ;
//---------------
// NO_SPRITE no registering!
}
return ( IR_CONT ) ;
}
//------------------------------------------------------------------------------------
void Start_new_palette ( void ) //Tony25Sept96
{
//start layer palette fading up
uint8 * screenFile ;
//if the screen is still fading down then wait for black - could happen when everythings cached into a large memory model
do
{
ServiceWindows ( ) ;
}
while ( GetFadeStatus ( ) = = RDFADE_DOWN ) ;
screenFile = res_man . Res_open ( this_screen . background_layer_id ) ; // open the screen file
UpdatePaletteMatchTable ( ( uint8 * ) FetchPaletteMatchTable ( screenFile ) ) ;
2003-08-23 14:42:37 +00:00
BS2_SetPalette ( 0 , 256 , FetchPalette ( screenFile ) , RDPAL_FADE ) ;
2003-07-28 01:44:38 +00:00
lastPaletteRes = 0 ; // indicating that it's a screen palette
res_man . Res_close ( this_screen . background_layer_id ) ; // close screen file
//FadeUp((float)1.75); // start fade up
FadeUp ( ( float ) 0.75 ) ; // start fade up
this_screen . new_palette = 0 ; // reset
}
//------------------------------------------------------------------------------------
int32 FN_update_player_stats ( int32 * params ) //Tony28Nov96
{
//engine needs to know certain info about the player
Object_mega * ob_mega = ( Object_mega * ) params [ 0 ] ;
this_screen . player_feet_x = ob_mega - > feet_x ;
this_screen . player_feet_y = ob_mega - > feet_y ;
PLAYER_FEET_X = ob_mega - > feet_x ; //for the script
PLAYER_FEET_Y = ob_mega - > feet_y ;
PLAYER_CUR_DIR = ob_mega - > current_dir ;
SCROLL_OFFSET_X = this_screen . scroll_offset_x ;
//Zdebug(42,"%d %d", ob_mega->feet_x, ob_mega->feet_y);
return ( IR_CONT ) ;
}
//------------------------------------------------------------------------------------
int32 FN_fade_down ( int32 * params ) //Tony5Dec96
{
if ( GetFadeStatus ( ) = = RDFADE_NONE ) //NONE means up! can only be called when screen is fully faded up - multiple calls wont have strange effects
{
FadeDown ( ( float ) 0.75 ) ;
return ( IR_CONT ) ;
}
return ( IR_CONT ) ;
}
int32 FN_fade_up ( int32 * params ) //Chris 15May97
{
do
{
ServiceWindows ( ) ;
}
while ( GetFadeStatus ( ) = = RDFADE_DOWN ) ;
if ( GetFadeStatus ( ) = = RDFADE_BLACK )
{
FadeUp ( ( float ) 0.75 ) ;
return ( IR_CONT ) ;
}
return ( IR_CONT ) ;
}
//------------------------------------------------------------------------------------
// typedef struct
// {
// uint8 red;
// uint8 green;
// uint8 blue;
// uint8 alpha;
// } _palEntry;
//------------------------------------------------------------
// typedef struct
// {
// uint8 firstEntry; // first colour number in this palette (0..255)
// uint8 noEntries; // number of Entries-1 (0..255) to be taken as (1..256)
// } _paletteHeader;
//------------------------------------------------------------
int32 FN_set_palette ( int32 * params ) // James05jun97
{
SetFullPalette ( params [ 0 ] ) ;
return ( IR_CONT ) ;
}
//------------------------------------------------------------
void SetFullPalette ( int32 palRes ) // James17jun97
{
// params 0 resource number of palette file
// or 0 if it's to be the palette from the current screen
uint8 * file ;
_standardHeader * head ;
//----------------------------------
// fudge for hut interior
// - unpausing should restore last palette as normal (could be screen palette or 'dark_palette_13')
// - but restoring the screen palette after 'dark_plaette_13' should now work properly too!
if ( LOCATION = = 13 ) // hut interior
{
2003-07-28 02:10:24 +00:00
if ( palRes = = - 1 ) // unpausing
2003-07-28 01:44:38 +00:00
palRes = lastPaletteRes ; // restore whatever palette was last set (screen palette or 'dark_palette_13')
}
else
{
// (James 03sep97)
// check if we're just restoring the current screen palette
// because we might actually need to use a separate palette file anyway
// eg. for pausing & unpausing during the eclipse
2003-07-28 02:10:24 +00:00
if ( palRes = = - 1 ) // unpausing (fudged for location 13)
2003-07-28 01:44:38 +00:00
palRes = 0 ; // we really meant '0'
if ( ( palRes = = 0 ) & & ( lastPaletteRes ) )
palRes = lastPaletteRes ;
}
//----------------------------------
if ( palRes ) // non-zero: set palette to this separate palette file
{
head = ( _standardHeader * ) res_man . Res_open ( palRes ) ; // open the palette file
2003-07-30 19:25:31 +00:00
# ifdef _SWORD2_DEBUG
2003-07-28 01:44:38 +00:00
if ( head - > fileType ! = PALETTE_FILE )
Con_fatal_error ( " FN_set_palette() called with invalid resource! (%s line %u) " , __FILE__ , __LINE__ ) ;
# endif
file = ( uint8 * ) ( head + 1 ) ;
file [ 0 ] = 0 ; // always set colour 0 to black
file [ 1 ] = 0 ; // because most background screen palettes have a bright colour 0
file [ 2 ] = 0 ; // although it should come out as black in the game!
file [ 3 ] = 0 ;
// UpdatePaletteMatchTable(file+(256*4)); // not yet in separate palette files
2003-08-23 14:42:37 +00:00
BS2_SetPalette ( 0 , 256 , file , RDPAL_INSTANT ) ;
2003-07-28 01:44:38 +00:00
if ( palRes ! = CONTROL_PANEL_PALETTE ) // (James 03sep97)
lastPaletteRes = palRes ; // indicating that it's a separate palette resource
res_man . Res_close ( palRes ) ; // close palette file
}
else // 0: set palette to current screen palette
{
if ( this_screen . background_layer_id )
{
file = res_man . Res_open ( this_screen . background_layer_id ) ; // open the screen file
UpdatePaletteMatchTable ( ( uint8 * ) FetchPaletteMatchTable ( file ) ) ;
2003-08-23 14:42:37 +00:00
BS2_SetPalette ( 0 , 256 , FetchPalette ( file ) , RDPAL_INSTANT ) ;
2003-07-28 01:44:38 +00:00
lastPaletteRes = 0 ; // indicating that it's a screen palette
res_man . Res_close ( this_screen . background_layer_id ) ; // close screen file
}
else
Con_fatal_error ( " FN_set_palette(0) called, but no current screen available! (%s line %u) " , __FILE__ , __LINE__ ) ;
}
}
//------------------------------------------------------------
int32 FN_restore_game ( int32 * params )
{
return ( IR_CONT ) ;
}
//------------------------------------------------------------
2003-07-28 10:28:29 +00:00
int32 FN_change_shadows ( int32 * params )
2003-07-28 01:44:38 +00:00
{
uint32 rv ;
if ( this_screen . mask_flag ) // if last screen was using a shading mask (see below) (James 08apr97)
{
rv = CloseLightMask ( ) ;
if ( rv )
ExitWithReport ( " Driver Error %.8x [%s line %u] " , rv , __FILE__ , __LINE__ ) ;
this_screen . mask_flag = 0 ;
}
return ( IR_CONT ) ;
}
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------