@ -4,6 +4,7 @@
# include "viewport.h"
# include "player.h"
# include "gui.h"
# include "screenshot.h"
// called by the ScreenShot proc to generate screenshot lines.
typedef void ScreenshotCallback ( void * userdata , byte * buf , uint y , uint pitch , uint n ) ;
@ -13,7 +14,6 @@ typedef struct {
const char * name ;
const char * extension ;
ScreenshotHandlerProc * proc ;
byte id ;
} ScreenshotFormat ;
//************************************************
@ -89,7 +89,7 @@ static bool MakeBmpImage(const char *name, ScreenshotCallback *callb, void *user
bih . clrimp = 0 ;
// convert the palette to the windows format
for ( i = 0 ; i ! = 256 ; i + + ) {
for ( i = 0 ; i ! = 256 ; i + + ) {
rq [ i ] . red = * palette + + ;
rq [ i ] . green = * palette + + ;
rq [ i ] . blue = * palette + + ;
@ -97,15 +97,19 @@ static bool MakeBmpImage(const char *name, ScreenshotCallback *callb, void *user
}
// write file header and info header and palette
fwrite ( & bfh , 1 , sizeof ( bfh ) , f ) ;
fwrite ( & bih , 1 , sizeof ( bih ) , f ) ;
fwrite ( rq , 1 , sizeof ( rq ) , f ) ;
if ( fwrite ( & bfh , sizeof ( bfh ) , 1 , f ) ! = 1 ) return false ;
if ( fwrite ( & bih , sizeof ( bih ) , 1 , f ) ! = 1 ) return false ;
if ( fwrite ( rq , sizeof ( rq ) , 1 , f ) ! = 1 ) return false ;
// use by default 64k temp memory
maxlines = clamp ( 65536 / padw , 16 , 128 ) ;
// now generate the bitmap bits
buff = ( byte * ) alloca ( padw * maxlines ) ; // by default generate 128 lines at a time.
buff = malloc ( padw * maxlines ) ; // by default generate 128 lines at a time.
if ( buff = = NULL ) {
fclose ( f ) ;
return false ;
}
memset ( buff , 0 , padw * maxlines ) ; // zero the buffer to have the padding bytes set to 0
// start at the bottom, since bitmaps are stored bottom up.
@ -119,9 +123,14 @@ static bool MakeBmpImage(const char *name, ScreenshotCallback *callb, void *user
// write each line
while ( n )
fwrite ( buff + ( - - n ) * padw , 1 , padw , f ) ;
} while ( h ) ;
if ( fwrite ( buff + ( - - n ) * padw , padw , 1 , f ) ! = 1 ) {
free ( buff ) ;
fclose ( f ) ;
return false ;
}
} while ( h ! = 0 ) ;
free ( buff ) ;
fclose ( f ) ;
return true ;
@ -135,7 +144,7 @@ static bool MakeBmpImage(const char *name, ScreenshotCallback *callb, void *user
static void PNGAPI png_my_error ( png_structp png_ptr , png_const_charp message )
{
DEBUG ( misc , 0 ) ( " ERROR(libpng): %s - %s \n " , message , ( char * ) png_get_error_ptr ( png_ptr ) ) ;
DEBUG ( misc , 0 ) ( " ERROR(libpng): %s - %s \n " , message , ( char * ) png_get_error_ptr ( png_ptr ) ) ;
longjmp ( png_ptr - > jmpbuf , 1 ) ;
}
@ -161,15 +170,15 @@ static bool MakePNGImage(const char *name, ScreenshotCallback *callb, void *user
f = fopen ( name , " wb " ) ;
if ( f = = NULL ) return false ;
png_ptr = png_create_write_struct ( PNG_LIBPNG_VER_STRING , ( char * ) name , png_my_error , png_my_warning ) ;
png_ptr = png_create_write_struct ( PNG_LIBPNG_VER_STRING , ( char * ) name , png_my_error , png_my_warning ) ;
if ( ! png_ptr ) {
if ( png_ptr = = NULL ) {
fclose ( f ) ;
return false ;
}
info_ptr = png_create_info_struct ( png_ptr ) ;
if ( ! info_ptr ) {
if ( info_ptr = = NULL ) {
png_destroy_write_struct ( & png_ptr , ( png_infopp ) NULL ) ;
fclose ( f ) ;
return false ;
@ -185,15 +194,15 @@ static bool MakePNGImage(const char *name, ScreenshotCallback *callb, void *user
png_set_filter ( png_ptr , 0 , PNG_FILTER_NONE ) ;
png_set_IHDR ( png_ptr , info_ptr , w , h , pixelformat , PNG_COLOR_TYPE_PALETTE , PNG_INTERLACE_NONE ,
PNG_ COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ) ;
png_set_IHDR ( png_ptr , info_ptr , w , h , pixelformat , PNG_COLOR_TYPE_PALETTE ,
PNG_ INTERLACE_NONE, PNG_ COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ) ;
// convert the palette to the .PNG format.
{
// avoids "might be clobbered" warning of argument "palette"
const byte * pal = palette ;
for ( i = 0 ; i ! = 256 ; i + + ) {
for ( i = 0 ; i ! = 256 ; i + + ) {
rq [ i ] . red = * pal + + ;
rq [ i ] . green = * pal + + ;
rq [ i ] . blue = * pal + + ;
@ -208,7 +217,12 @@ static bool MakePNGImage(const char *name, ScreenshotCallback *callb, void *user
maxlines = clamp ( 65536 / w , 16 , 128 ) ;
// now generate the bitmap bits
buff = ( byte * ) alloca ( w * maxlines ) ; // by default generate 128 lines at a time.
buff = malloc ( w * maxlines ) ; // by default generate 128 lines at a time.
if ( buff = = NULL ) {
png_destroy_write_struct ( & png_ptr , & info_ptr ) ;
fclose ( f ) ;
return false ;
}
memset ( buff , 0 , w * maxlines ) ; // zero the buffer to have the padding bytes set to 0
y = 0 ;
@ -221,13 +235,14 @@ static bool MakePNGImage(const char *name, ScreenshotCallback *callb, void *user
y + = n ;
// write them to png
for ( i = 0 ; i ! = n ; i + + )
for ( i = 0 ; i ! = n ; i + + )
png_write_row ( png_ptr , buff + i * w ) ;
} while ( y ! = h ) ;
png_write_end ( png_ptr , info_ptr ) ;
png_destroy_write_struct ( & png_ptr , & info_ptr ) ;
free ( buff ) ;
fclose ( f ) ;
return true ;
}
@ -278,8 +293,8 @@ static bool MakePCXImage(const char *name, ScreenshotCallback *callb, void *user
pcx . version = 5 ;
pcx . rle = 1 ;
pcx . bpp = 8 ;
pcx . xmax = TO_LE16 ( w - 1 ) ;
pcx . ymax = TO_LE16 ( h - 1 ) ;
pcx . xmax = TO_LE16 ( w - 1 ) ;
pcx . ymax = TO_LE16 ( h - 1 ) ;
pcx . hdpi = TO_LE16 ( 320 ) ;
pcx . vdpi = TO_LE16 ( 320 ) ;
@ -289,53 +304,86 @@ static bool MakePCXImage(const char *name, ScreenshotCallback *callb, void *user
pcx . height = TO_LE16 ( h ) ;
// write pcx header
fwrite ( & pcx , sizeof ( pcx ) , 1 , f ) ;
if ( fwrite ( & pcx , sizeof ( pcx ) , 1 , f ) ! = 1 ) {
fclose ( f ) ;
return false ;
}
// use by default 64k temp memory
maxlines = clamp ( 65536 / w , 16 , 128 ) ;
// now generate the bitmap bits
buff = ( byte * ) alloca ( w * maxlines ) ; // by default generate 128 lines at a time.
memset ( buff , 0 , w * maxlines ) ; // zero the buffer to have the padding bytes set to 0
buff = malloc ( w * maxlines ) ; // by default generate 128 lines at a time.
if ( buff = = NULL ) {
fclose ( f ) ;
return false ;
}
memset ( buff , 0 , w * maxlines ) ; // zero the buffer to have the padding bytes set to 0
y = 0 ;
do {
// determine # lines to write
uint n = min ( h - y , maxlines ) , i ;
uint n = min ( h - y , maxlines ) ;
uint i ;
// render the pixels into the buffer
callb ( userdata , buff , y , w , n ) ;
y + = n ;
// write them to pcx
for ( i = 0 ; i ! = n ; i + + ) {
for ( i = 0 ; i ! = n ; i + + ) {
int runcount = 1 ;
byte * bufp = buff + i * w ;
byte runchar = buff [ 0 ] ;
uint left = w - 1 ;
uint left ;
// for each pixel...
while ( left ) {
for ( left = w - 1 ; left > 0 ; - - left ) {
byte ch = * bufp + + ;
if ( ch ! = runchar | | runcount > = 0x3f ) {
if ( runcount > 1 | | ( runchar & 0xC0 ) = = 0xC0 ) fputc ( 0xC0 | runcount , f ) ;
fputc ( runchar , f ) ;
if ( runcount > 1 | | ( runchar & 0xC0 ) = = 0xC0 )
if ( fputc ( 0xC0 | runcount , f ) = = EOF ) {
free ( buff ) ;
fclose ( f ) ;
return false ;
}
if ( fputc ( runchar , f ) = = EOF ) {
free ( buff ) ;
fclose ( f ) ;
return false ;
}
runcount = 0 ;
runchar = ch ;
}
runcount + + ;
left - - ;
}
// write remaining bytes..
if ( runcount > 1 | | ( runchar & 0xC0 ) = = 0xC0 ) fputc ( 0xC0 | runcount , f ) ;
fputc ( runchar , f ) ;
if ( runcount > 1 | | ( runchar & 0xC0 ) = = 0xC0 )
if ( fputc ( 0xC0 | runcount , f ) = = EOF ) {
free ( buff ) ;
fclose ( f ) ;
return false ;
}
if ( fputc ( runchar , f ) = = EOF ) {
free ( buff ) ;
fclose ( f ) ;
return false ;
}
}
} while ( y ! = h ) ;
free ( buff ) ;
// write 8-bit color palette
fputc ( 12 , f ) ;
fwrite ( palette , 256 * 3 , 1 , f ) ;
if ( fputc ( 12 , f ) = = EOF ) {
fclose ( f ) ;
return false ;
}
if ( fwrite ( palette , 256 * 3 , 1 , f ) ! = 1 ) {
fclose ( f ) ;
return false ;
}
fclose ( f ) ;
return true ;
@ -353,11 +401,14 @@ static const ScreenshotFormat _screenshot_formats[] = {
{ " PCX " , " pcx " , & MakePCXImage } ,
} ;
void InitializeScreenshotFormats ( )
void InitializeScreenshotFormats ( void )
{
int i , j ;
for ( i = 0 , j = 0 ; i ! = lengthof ( _screenshot_formats ) ; i + + )
if ( ! strcmp ( _screenshot_format_name , _screenshot_formats [ i ] . extension ) ) { j = i ; break ; }
int i , j ;
for ( i = 0 , j = 0 ; i ! = lengthof ( _screenshot_formats ) ; i + + )
if ( ! strcmp ( _screenshot_format_name , _screenshot_formats [ i ] . extension ) ) {
j = i ;
break ;
}
_cur_screenshot_format = j ;
_num_screenshot_formats = lengthof ( _screenshot_formats ) ;
}
@ -376,16 +427,13 @@ void SetScreenshotFormat(int i)
// screenshot generator that dumps the current video buffer
static void CurrentScreenCallback ( void * userdata , byte * buf , uint y , uint pitch , uint n )
{
for ( ; n > 0 ; - - n )
{
for ( ; n > 0 ; - - n ) {
memcpy ( buf , _screen . dst_ptr + y * _screen . pitch , _screen . width ) ;
+ + y ;
buf + = pitch ;
}
}
extern void ViewportDoDraw ( ViewPort * vp , int left , int top , int right , int bottom ) ;
// generate a large piece of the world
static void LargeWorldCallback ( void * userdata , byte * buf , uint y , uint pitch , uint n )
{
@ -413,7 +461,7 @@ static void LargeWorldCallback(void *userdata, byte *buf, uint y, uint pitch, ui
( ( left - wx - vp - > left ) < < vp - > zoom ) + vp - > virtual_left ,
( ( y - vp - > top ) < < vp - > zoom ) + vp - > virtual_top ,
( ( left - vp - > left ) < < vp - > zoom ) + vp - > virtual_left ,
( ( ( y + n ) - vp - > top ) < < vp - > zoom ) + vp - > virtual_top
( ( ( y + n ) - vp - > top ) < < vp - > zoom ) + vp - > virtual_top
) ;
}
@ -440,7 +488,7 @@ static char *MakeScreenshotName(const char *ext)
base [ 0 ] = ' . ' ; strcpy ( base + 1 , ext ) ;
serial = 0 ;
for ( ; ; ) {
for ( ; ; ) {
snprintf ( filename , sizeof ( filename ) , " %s%s " , _path . personal_dir , _screenshot_name ) ;
if ( ! FileExists ( filename ) )
break ;
@ -450,9 +498,7 @@ static char *MakeScreenshotName(const char *ext)
return filename ;
}
extern byte _cur_palette [ 768 ] ;
bool MakeScreenshot ( )
bool MakeScreenshot ( void )
{
const ScreenshotFormat * sf = _screenshot_formats + _cur_screenshot_format ;
return sf - > proc ( MakeScreenshotName ( sf - > extension ) , CurrentScreenCallback , NULL , _screen . width , _screen . height , 8 , _cur_palette ) ;