/* * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) * Copyright © 2002-2006 Fenix Team (Fenix) * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) * * This file is part of Bennu - Game Development * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 3. This notice may not be removed or altered from any source * distribution. * */ /* --------------------------------------------------------------------------- */ #include "mod_map.h" /* --------------------------------------------------------------------------- */ struct { int code ; int regsize ; char name[32] ; char fpname[12] ; int width ; int height ; int flags ; } chunk ; /* --------------------------------------------------------------------------- */ /* Static convenience function */ static int gr_read_lib( file * fp ) { char header[8] ; short int px, py ; int bpp, libid, code; uint32_t y ; unsigned c; GRLIB * lib ; GRAPH * gr ; PALETTE * pal = NULL ; int st = 0; libid = grlib_new() ; if ( libid < 0 ) return -1 ; lib = grlib_get( libid ); if ( !lib ) { grlib_destroy( libid ) ; return -1 ; } if ( file_read( fp, header, sizeof( header ) ) != sizeof( header ) ) { grlib_destroy( libid ) ; return -1 ; } if ( strcmp( header, F32_MAGIC ) == 0 ) bpp = 32 ; else if ( strcmp( header, F16_MAGIC ) == 0 ) bpp = 16 ; else if ( strcmp( header, FPG_MAGIC ) == 0 ) bpp = 8 ; else if ( strcmp( header, F01_MAGIC ) == 0 ) bpp = 1 ; else { grlib_destroy( libid ) ; return -1 ; } if ( bpp == 8 && !( pal = gr_read_pal_with_gamma( fp ) ) ) { grlib_destroy( libid ) ; return -1 ; } while ( !file_eof( fp ) ) { if ( file_read( fp, &chunk, sizeof( chunk ) ) != sizeof( chunk ) ) break ; ARRANGE_DWORD( &chunk.code ) ; if ( chunk.code < 0 || chunk.code > 999 ) break; ARRANGE_DWORD( &chunk.regsize ) ; ARRANGE_DWORD( &chunk.width ) ; ARRANGE_DWORD( &chunk.height ) ; ARRANGE_DWORD( &chunk.flags ) ; /* Cabecera del gráfico */ gr = bitmap_new( chunk.code, chunk.width, chunk.height, bpp ) ; if ( !gr ) { grlib_destroy( libid ) ; if ( bpp == 8 ) pal_destroy( pal ) ; // Elimino la instancia inicial return -1 ; } memcpy( gr->name, chunk.name, sizeof( chunk.name ) ) ; gr->name[31] = 0 ; gr->ncpoints = chunk.flags ; gr->modified = 2 ; // bitmap_analize( gr ); /* Puntos de control */ if ( gr->ncpoints ) { gr->cpoints = ( CPOINT * ) malloc( gr->ncpoints * sizeof( CPOINT ) ) ; if ( !gr->cpoints ) { bitmap_destroy( gr ) ; grlib_destroy( libid ) ; if ( bpp == 8 ) pal_destroy( pal ) ; return -1 ; } for ( c = 0 ; c < gr->ncpoints ; c++ ) { file_readSint16( fp, &px ) ; file_readSint16( fp, &py ) ; if ( px == -1 && py == -1 ) { gr->cpoints[c].x = CPOINT_UNDEFINED ; gr->cpoints[c].y = CPOINT_UNDEFINED ; } else { gr->cpoints[c].x = px ; gr->cpoints[c].y = py ; } } } else gr->cpoints = 0 ; /* Datos del gráfico */ for ( y = 0 ; y < gr->height ; y++ ) { uint8_t * line = ( uint8_t * )gr->data + gr->pitch * y; switch ( bpp ) { case 32: st = file_readUint32A( fp, ( uint32_t * ) line, gr->width ); break; case 16: st = file_readUint16A( fp, ( uint16_t * ) line, gr->width ); break; case 8: case 1: if ( ( st = file_read( fp, line, gr->widthb ) ) != gr->widthb ) st = 0; break; } if ( !st ) { bitmap_destroy( gr ); grlib_destroy( libid ) ; if ( bpp == 8 ) pal_destroy( pal ); return -1 ; } } code = grlib_add_map( libid, gr ) ; if ( bpp == 8 ) pal_map_assign( libid, code, pal ) ; } if ( bpp == 8 ) pal_destroy( pal ) ; // Elimino la instancia inicial return libid ; } /* --------------------------------------------------------------------------- */ /* * FUNCTION : gr_load_fpg * * Load a FPG file * * PARAMS : * libname Name of the file * * RETURN VALUE : * Internal ID of the library or -1 if invalid file * */ int gr_load_fpg( const char * libname ) { int libid ; file * fp = file_open( libname, "rb" ) ; if ( !fp ) return -1 ; libid = gr_read_lib( fp ) ; file_close( fp ) ; return libid ; } /* --------------------------------------------------------------------------- */ /* * FUNCTION : gr_save_fpg * * Save a FPG file * * PARAMS : * filename Name of the file * * RETURN VALUE : * 1 if succeded * >= 0 error * */ int gr_save_fpg( int libid, const char * filename ) { file * fp; GRLIB * lib; uint8_t * block = NULL; int n, y, c; int bpp; int nmaps; uint8_t header[8]; rgb_component * palette = NULL; /* Get the library and open the file */ /* if ( !libid ) lib = syslib ; else */ lib = grlib_get( libid ); if ( !lib ) return 0; /* Guess the FPG depth */ nmaps = lib->map_reserved < 1000 ? lib->map_reserved : 1000; for ( bpp = n = 0 ; n < nmaps ; n++ ) { if ( lib->maps[n] ) { if ( bpp && lib->maps[n]->format->depth != bpp ) return 0; /* save_fpg: don't allow save maps with differents bpp */ bpp = lib->maps[n]->format->depth; if ( !palette && bpp == 8 && lib->maps[n]->format->palette ) palette = lib->maps[n]->format->palette->rgb; } } if ( bpp == 32 ) strcpy( ( char * ) header, F32_MAGIC ); else if ( bpp == 16 ) strcpy( ( char * ) header, F16_MAGIC ); else if ( bpp == 8 ) strcpy( ( char * ) header, FPG_MAGIC ); else if ( bpp == 1 ) strcpy( ( char * ) header, F01_MAGIC ); else return 0; /* No maps for save */ /* Create fpg */ fp = file_open( filename, "wb" ); if ( !fp ) return 0; /* Write the header */ header[7] = 0x00; /* Version */ file_write( fp, header, sizeof( header ) ); /* Write the color palette */ if ( bpp == 8 ) { uint8_t colors[256][3] ; uint8_t gamma[576]; if ( !palette ) { if ( sys_pixel_format->palette ) palette = sys_pixel_format->palette->rgb; else palette = ( rgb_component * ) default_palette; } for ( n = 0 ; n < 256 ; n++ ) { colors[n][0] = palette[n].r >> 2 ; colors[n][1] = palette[n].g >> 2 ; colors[n][2] = palette[n].b >> 2 ; } file_write( fp, &colors, 768 ) ; memset( gamma, '\0', sizeof( gamma ) ); file_write( fp, gamma, sizeof( gamma ) ) ; } /* Write each map */ for ( n = 0 ; n < nmaps ; n++ ) { GRAPH * gr = lib->maps[n]; if ( gr ) { /* Write the bitmap header */ chunk.code = n; chunk.regsize = 0; chunk.width = gr->width; chunk.height = gr->height; chunk.flags = gr->ncpoints; chunk.fpname[0] = 0; strncpy( chunk.name, gr->name, sizeof( chunk.name ) ); ARRANGE_DWORD( &chunk.code ); ARRANGE_DWORD( &chunk.regsize ); ARRANGE_DWORD( &chunk.width ); ARRANGE_DWORD( &chunk.height ); ARRANGE_DWORD( &chunk.flags ); file_write( fp, &chunk, sizeof( chunk ) ); /* Write the control points */ for ( c = 0 ; c < gr->ncpoints ; c++ ) { file_writeSint16( fp, &gr->cpoints[c].x ); file_writeSint16( fp, &gr->cpoints[c].y ); } /* Write the bitmap pixel data */ if ( bpp > 8 ) { if ( !( block = malloc( gr->widthb ) ) ) { file_close( fp ); return 0; /* No memory */ } } for ( y = 0 ; y < gr->height ; y++ ) { if ( bpp > 8 ) { memcpy( block, ( uint8_t * )gr->data + gr->pitch*y, gr->widthb ); if ( bpp == 16 ) { /* gr_convert16_ScreenTo565(( uint16_t * )block, gr->width ); */ file_writeUint16A( fp, ( uint16_t * ) block, gr->width ); } else file_writeUint32A( fp, ( uint32_t * ) block, gr->width ); } else { file_write( fp, ( uint8_t * )gr->data + gr->pitch*y, gr->widthb ); } } if ( bpp > 8 ) free( block ); } } file_close( fp ); return 1; } /* --------------------------------------------------------------------------- */