nkeynes@31: /** nkeynes@481: * $Id: util.c,v 1.12 2007-10-31 12:05:23 nkeynes Exp $ nkeynes@31: * nkeynes@31: * Miscellaneous utility functions. nkeynes@31: * nkeynes@31: * Copyright (c) 2005 Nathan Keynes. nkeynes@31: * nkeynes@31: * This program is free software; you can redistribute it and/or modify nkeynes@31: * it under the terms of the GNU General Public License as published by nkeynes@31: * the Free Software Foundation; either version 2 of the License, or nkeynes@31: * (at your option) any later version. nkeynes@31: * nkeynes@31: * This program is distributed in the hope that it will be useful, nkeynes@31: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@31: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@31: * GNU General Public License for more details. nkeynes@31: */ nkeynes@31: nkeynes@477: #include nkeynes@425: #include nkeynes@437: #include nkeynes@437: #include nkeynes@437: #include nkeynes@437: #include nkeynes@477: #include nkeynes@477: #include nkeynes@477: #include nkeynes@17: #include "dream.h" nkeynes@477: #include "display.h" nkeynes@481: #include "gui.h" nkeynes@437: #include "sh4/sh4core.h" nkeynes@437: nkeynes@437: char *msg_levels[] = { "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" }; nkeynes@437: int global_msg_level = EMIT_WARN; nkeynes@17: nkeynes@422: void fwrite_string( const char *s, FILE *f ) nkeynes@17: { nkeynes@17: uint32_t len = 0; nkeynes@17: if( s == NULL ) { nkeynes@17: fwrite( &len, sizeof(len), 1, f ); nkeynes@17: } else { nkeynes@17: len = strlen(s)+1; nkeynes@17: fwrite( &len, sizeof(len), 1, f ); nkeynes@17: fwrite( s, len, 1, f ); nkeynes@17: } nkeynes@17: } nkeynes@17: nkeynes@17: int fread_string( char *s, int maxlen, FILE *f ) nkeynes@17: { nkeynes@17: uint32_t len; nkeynes@17: fread( &len, sizeof(len), 1, f ); nkeynes@17: if( len != 0 ) { nkeynes@17: fread( s, len > maxlen ? maxlen : len, 1, f ); nkeynes@17: } nkeynes@17: return len; nkeynes@17: } nkeynes@117: nkeynes@477: void fwrite_gzip( void *p, size_t sz, size_t count, FILE *f ) nkeynes@477: { nkeynes@477: uLongf size = sz*count; nkeynes@477: uLongf csize = ((int)(size*1.001))+13; nkeynes@477: unsigned char *tmp = g_malloc0( csize ); nkeynes@477: int status = compress( tmp, &csize, p, size ); nkeynes@477: assert( status == Z_OK ); nkeynes@477: fwrite( &csize, sizeof(csize), 1, f ); nkeynes@477: fwrite( tmp, csize, 1, f ); nkeynes@477: g_free(tmp); nkeynes@477: } nkeynes@477: nkeynes@477: int fread_gzip( void *p, size_t sz, size_t count, FILE *f ) nkeynes@477: { nkeynes@477: uLongf size = sz*count; nkeynes@477: uLongf csize; nkeynes@477: unsigned char *tmp; nkeynes@477: nkeynes@477: fread( &csize, sizeof(csize), 1, f ); nkeynes@477: assert( csize <= (size*2) ); nkeynes@477: tmp = g_malloc0( csize ); nkeynes@477: fread( tmp, csize, 1, f ); nkeynes@477: int status = uncompress( p, &size, tmp, csize ); nkeynes@477: g_free(tmp); nkeynes@477: if( status == Z_OK ) { nkeynes@477: return count; nkeynes@477: } else { nkeynes@477: fprintf( stderr, "Error reading compressed data\n" ); nkeynes@477: return 0; nkeynes@477: } nkeynes@477: } nkeynes@477: nkeynes@117: void fwrite_dump( unsigned char *data, unsigned int length, FILE *f ) nkeynes@117: { nkeynes@117: unsigned int i, j; nkeynes@117: for( i =0; i>2; i+=wordsPerLine ) { nkeynes@187: fprintf( f, "%08X:", i); nkeynes@220: for( j=i; jcolour_format ) { nkeynes@477: case COLFMT_BGR888: nkeynes@477: coltype = PNG_COLOR_TYPE_RGB; nkeynes@477: break; nkeynes@477: case COLFMT_BGRA8888: nkeynes@477: coltype = PNG_COLOR_TYPE_RGB_ALPHA; nkeynes@477: break; nkeynes@477: case COLFMT_BGR0888: nkeynes@477: coltype = PNG_COLOR_TYPE_RGB; nkeynes@477: break; nkeynes@477: default: nkeynes@477: coltype = PNG_COLOR_TYPE_RGB; nkeynes@477: } nkeynes@477: png_set_IHDR(png_ptr, info_ptr, buffer->width, buffer->height, nkeynes@477: 8, coltype, PNG_INTERLACE_NONE, nkeynes@477: PNG_COMPRESSION_TYPE_DEFAULT, nkeynes@477: PNG_FILTER_TYPE_DEFAULT ); nkeynes@477: png_write_info(png_ptr, info_ptr); nkeynes@477: if( buffer->colour_format == COLFMT_BGR0888 ) { nkeynes@477: png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); nkeynes@477: } nkeynes@477: png_set_bgr(png_ptr); nkeynes@477: if( buffer->inverted ) { nkeynes@481: p = (png_bytep)(buffer->data + (buffer->height*buffer->rowstride) - buffer->rowstride); nkeynes@477: for(i=0; iheight; i++ ) { nkeynes@477: png_write_row(png_ptr, p); nkeynes@477: p-=buffer->rowstride; nkeynes@477: } nkeynes@477: } else { nkeynes@481: p = (png_bytep)buffer->data; nkeynes@477: for(i=0; iheight; i++ ) { nkeynes@477: png_write_row(png_ptr, p); nkeynes@477: p+=buffer->rowstride; nkeynes@477: } nkeynes@477: } nkeynes@477: png_write_end(png_ptr, info_ptr); nkeynes@477: png_destroy_write_struct(&png_ptr, &info_ptr); nkeynes@477: return TRUE; nkeynes@477: } nkeynes@477: nkeynes@477: frame_buffer_t read_png_from_stream( FILE *f ) nkeynes@477: { nkeynes@477: png_bytep p; nkeynes@477: int i; nkeynes@477: png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nkeynes@477: NULL, NULL, NULL); nkeynes@477: if (!png_ptr) { nkeynes@477: return NULL; nkeynes@477: } nkeynes@477: nkeynes@477: png_infop info_ptr = png_create_info_struct(png_ptr); nkeynes@477: if (!info_ptr) { nkeynes@477: png_destroy_read_struct(&png_ptr, NULL, NULL); nkeynes@477: return NULL; nkeynes@477: } nkeynes@477: nkeynes@477: png_infop end_info = png_create_info_struct(png_ptr); nkeynes@477: if (!end_info) { nkeynes@477: png_destroy_read_struct(&png_ptr, &info_ptr, NULL ); nkeynes@477: return NULL; nkeynes@477: } nkeynes@477: nkeynes@477: if( setjmp(png_jmpbuf(png_ptr)) ) { nkeynes@477: png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); nkeynes@477: return NULL; nkeynes@477: } nkeynes@477: nkeynes@477: png_init_io(png_ptr, f); nkeynes@477: png_read_info(png_ptr, info_ptr); nkeynes@477: nkeynes@477: png_uint_32 width, height; nkeynes@477: int bit_depth, color_type, interlace_type, nkeynes@477: compression_type, filter_method; nkeynes@477: png_get_IHDR(png_ptr, info_ptr, &width, &height, nkeynes@477: &bit_depth, &color_type, &interlace_type, nkeynes@477: &compression_type, &filter_method); nkeynes@477: assert( interlace_type == PNG_INTERLACE_NONE ); nkeynes@477: int rowbytes = png_get_rowbytes(png_ptr, info_ptr); nkeynes@477: int channels = png_get_channels(png_ptr, info_ptr); nkeynes@477: frame_buffer_t buffer = g_malloc( sizeof(struct frame_buffer) + rowbytes*height ); nkeynes@477: buffer->data = (char *)(buffer+1); nkeynes@477: buffer->width = width; nkeynes@477: buffer->height = height; nkeynes@477: buffer->rowstride = rowbytes; nkeynes@477: buffer->address = -1; nkeynes@477: buffer->size = rowbytes*height; nkeynes@477: buffer->inverted = FALSE; nkeynes@477: if( channels == 4 ) { nkeynes@477: buffer->colour_format = COLFMT_BGRA8888; nkeynes@477: } else if( channels == 3 ) { nkeynes@477: buffer->colour_format = COLFMT_RGB888; nkeynes@477: } nkeynes@477: nkeynes@481: p = (png_bytep)buffer->data; nkeynes@477: for( i=0; i global_msg_level ) { nkeynes@437: return; // ignored nkeynes@437: } nkeynes@447: nkeynes@437: va_start(ap, msg); nkeynes@437: nkeynes@447: if( level <= EMIT_ERR ) { nkeynes@447: gchar *text = g_strdup_vprintf( msg, ap ); nkeynes@447: if( gui_error_dialog( text ) ) { nkeynes@447: g_free(text); nkeynes@447: va_end(ap); nkeynes@447: return; nkeynes@447: } nkeynes@447: g_free(text); nkeynes@447: } nkeynes@447: nkeynes@447: nkeynes@437: strftime( buf, sizeof(buf), "%H:%M:%S", localtime(&tm) ); nkeynes@437: fprintf( stderr, "%s %08X %-5s ", buf, sh4r.pc, msg_levels[level] ); nkeynes@437: vfprintf( stderr, msg, ap ); nkeynes@447: va_end(ap); nkeynes@437: fprintf( stderr, "\n" ); nkeynes@437: }