Search
lxdream.org :: lxdream/src/util.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/util.c
changeset 561:533f6b478071
prev556:72dbf70344db
next564:dc7b5ffb0535
author nkeynes
date Tue Jan 01 05:08:38 2008 +0000 (12 years ago)
branchlxdream-mmu
permissions -rw-r--r--
last change Enable Id keyword on all source files
view annotate diff log raw
     1 /**
     2  * $Id$
     3  *
     4  * Miscellaneous utility functions.
     5  *
     6  * Copyright (c) 2005 Nathan Keynes.
     7  *
     8  * This program is free software; you can redistribute it and/or modify
     9  * it under the terms of the GNU General Public License as published by
    10  * the Free Software Foundation; either version 2 of the License, or
    11  * (at your option) any later version.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  */
    19 #define HAVE_EXECINFO_H 1
    21 #include <assert.h>
    22 #include <ctype.h>
    23 #include <stdarg.h>
    24 #include <stdio.h>
    25 #include <stdlib.h>
    26 #include <signal.h>
    27 #include <time.h>
    28 #include <zlib.h>
    29 #include <glib.h>
    30 #include <png.h>
    31 #include "dream.h"
    32 #include "display.h"
    33 #include "gui.h"
    34 #include "sh4/sh4core.h"
    36 char *msg_levels[] = { "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" };
    37 int global_msg_level = EMIT_WARN;
    39 static void report_crash( int signo, siginfo_t *info, void *ptr )
    40 {
    41     char buf[128];
    43     fprintf( stderr, "--- Aborting with signal %d ---\n", signo );
    44     // Get gdb to print a nice backtrace for us
    45     snprintf( buf, 128, "gdb -batch -f --quiet --pid=%d -ex bt", getpid() );
    46     system(buf);
    48     abort();
    49 }
    51 void install_crash_handler(void)
    52 {
    53     struct sigaction sa;
    55     sa.sa_sigaction = report_crash;
    56     sigemptyset(&sa.sa_mask);
    57     sa.sa_flags = SA_RESETHAND|SA_SIGINFO;
    58     sigaction( SIGSEGV, &sa, NULL );
    59 }
    62 void fwrite_string( const char *s, FILE *f )
    63 {
    64     uint32_t len = 0;
    65     if( s == NULL ) {
    66 	fwrite( &len, sizeof(len), 1, f );
    67     } else {
    68 	len = strlen(s)+1;
    69 	fwrite( &len, sizeof(len), 1, f );
    70 	fwrite( s, len, 1, f );
    71     }
    72 }
    74 int fread_string( char *s, int maxlen, FILE *f ) 
    75 {
    76     uint32_t len;
    77     fread( &len, sizeof(len), 1, f );
    78     if( len != 0 ) {
    79 	fread( s, len > maxlen ? maxlen : len, 1, f );
    80     }
    81     return len;
    82 }
    84 void fwrite_gzip( void *p, size_t sz, size_t count, FILE *f )
    85 {
    86     uLongf size = sz*count;
    87     uLongf csize = ((int)(size*1.001))+13;
    88     unsigned char *tmp = g_malloc0( csize );
    89     int status = compress( tmp, &csize, p, size );
    90     assert( status == Z_OK );
    91     fwrite( &csize, sizeof(csize), 1, f );
    92     fwrite( tmp, csize, 1, f );
    93     g_free(tmp);
    94 }
    96 int fread_gzip( void *p, size_t sz, size_t count, FILE *f )
    97 {
    98     uLongf size = sz*count;
    99     uLongf csize;
   100     unsigned char *tmp;
   102     fread( &csize, sizeof(csize), 1, f );
   103     assert( csize <= (size*2) );
   104     tmp = g_malloc0( csize );
   105     fread( tmp, csize, 1, f );
   106     int status = uncompress( p, &size, tmp, csize );
   107     g_free(tmp);
   108     if( status == Z_OK ) {
   109 	return count;
   110     } else {
   111 	fprintf( stderr, "Error reading compressed data\n" );
   112 	return 0;
   113     }
   114 }
   116 void fwrite_dump( unsigned char *data, unsigned int length, FILE *f ) 
   117 {
   118     unsigned int i, j;
   119     for( i =0; i<length; i+=16 ) {
   120 	fprintf( f, "%08X:", i);
   121 	for( j=i; j<i+16; j++ ) {
   122 	    if( (j % 4) == 0 )
   123 		fprintf( f, " " );
   124 	    if( j < length )
   125 		fprintf( f, " %02X", (unsigned int)(data[j]) );
   126 	    else
   127 		fprintf( f, "   " );
   128 	}
   129 	fprintf( f, "  " );
   130 	for( j=i; j<i+16 && j<length; j++ ) {
   131 	    fprintf( f, "%c", isprint(data[j]) ? data[j] : '.' );
   132 	}
   133 	fprintf( f, "\n" );
   134     }
   135 }
   137 void fwrite_dump32( unsigned int *data, unsigned int length, FILE *f ) 
   138 {
   139     fwrite_dump32v( data, length, 8, f );
   140 }
   142 void fwrite_dump32v( unsigned int *data, unsigned int length, int wordsPerLine, FILE *f ) 
   143 {
   144     unsigned int i, j;
   145     for( i =0; i<length>>2; i+=wordsPerLine ) {
   146 	fprintf( f, "%08X:", i);
   147 	for( j=i; j<i+wordsPerLine; j++ ) {
   148 	    if( j < length )
   149 		fprintf( f, " %08X", (unsigned int)(data[j]) );
   150 	    else
   151 		fprintf( f, "         " );
   152 	}
   153 	fprintf( f, "\n" );
   154     }
   155 }
   157 gboolean write_png_to_stream( FILE *f, frame_buffer_t buffer )
   158 {
   159     int coltype, i;
   160     png_bytep p;
   161     png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
   162     if (!png_ptr) {
   163 	return FALSE;
   164     }
   166     png_infop info_ptr = png_create_info_struct(png_ptr);
   167     if (!info_ptr) {
   168 	png_destroy_write_struct(&png_ptr, NULL);
   169 	return FALSE;
   170     }
   172     if( setjmp(png_jmpbuf(png_ptr)) ) {
   173 	png_destroy_write_struct(&png_ptr, &info_ptr);
   174 	return FALSE;
   175     }
   176     png_init_io( png_ptr, f );
   177     switch( buffer->colour_format ) {
   178     case COLFMT_BGR888:
   179 	coltype = PNG_COLOR_TYPE_RGB;
   180 	break;
   181     case COLFMT_BGRA8888:
   182 	coltype = PNG_COLOR_TYPE_RGB_ALPHA;
   183 	break;
   184     case COLFMT_BGR0888:
   185 	coltype = PNG_COLOR_TYPE_RGB;
   186 	break;
   187     default:
   188 	coltype = PNG_COLOR_TYPE_RGB;
   189     }
   190     png_set_IHDR(png_ptr, info_ptr, buffer->width, buffer->height,
   191 		 8, coltype, PNG_INTERLACE_NONE, 
   192 		 PNG_COMPRESSION_TYPE_DEFAULT, 
   193 		 PNG_FILTER_TYPE_DEFAULT );
   194     png_write_info(png_ptr, info_ptr);
   195     if( buffer->colour_format == COLFMT_BGR0888 ) {
   196 	png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
   197     }
   198     png_set_bgr(png_ptr);
   199     if( buffer->inverted ) {
   200 	p = (png_bytep)(buffer->data + (buffer->height*buffer->rowstride) - buffer->rowstride);
   201 	for(i=0; i<buffer->height; i++ ) {
   202 	    png_write_row(png_ptr, p);
   203 	    p-=buffer->rowstride;
   204 	}
   205     } else {
   206 	p = (png_bytep)buffer->data;
   207 	for(i=0; i<buffer->height; i++ ) {
   208 	    png_write_row(png_ptr, p);
   209 	    p+=buffer->rowstride;
   210 	}
   211     }
   212     png_write_end(png_ptr, info_ptr);
   213     png_destroy_write_struct(&png_ptr, &info_ptr);
   214     return TRUE;
   215 }
   217 frame_buffer_t read_png_from_stream( FILE *f )
   218 {
   219     png_bytep p;
   220     int i;
   221     png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 
   222 						 NULL, NULL, NULL);
   223     if (!png_ptr) {
   224 	return NULL;
   225     }
   227     png_infop info_ptr = png_create_info_struct(png_ptr);
   228     if (!info_ptr) {
   229 	png_destroy_read_struct(&png_ptr, NULL, NULL);
   230 	return NULL;
   231     }
   233     png_infop end_info = png_create_info_struct(png_ptr);
   234     if (!end_info) {
   235 	png_destroy_read_struct(&png_ptr, &info_ptr, NULL );
   236 	return NULL;
   237     }
   239     if( setjmp(png_jmpbuf(png_ptr)) ) {
   240 	png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
   241 	return NULL;
   242     }
   244     png_init_io(png_ptr, f);
   245     png_read_info(png_ptr, info_ptr);
   247     png_uint_32 width, height;
   248     int bit_depth, color_type, interlace_type,
   249 	compression_type, filter_method;
   250     png_get_IHDR(png_ptr, info_ptr, &width, &height,
   251 		 &bit_depth, &color_type, &interlace_type,
   252 		 &compression_type, &filter_method);
   253     assert( interlace_type == PNG_INTERLACE_NONE );
   254     int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
   255     int channels = png_get_channels(png_ptr, info_ptr);
   256     frame_buffer_t buffer = g_malloc( sizeof(struct frame_buffer) + rowbytes*height );
   257     buffer->data = (unsigned char *)(buffer+1);
   258     buffer->width = width;
   259     buffer->height = height;
   260     buffer->rowstride = rowbytes;
   261     buffer->address = -1;
   262     buffer->size = rowbytes*height;
   263     buffer->inverted = FALSE;
   264     if( channels == 4 ) {
   265 	buffer->colour_format = COLFMT_BGRA8888;
   266     } else if( channels == 3 ) {
   267 	buffer->colour_format = COLFMT_RGB888;
   268     }
   270     p = (png_bytep)buffer->data;
   271     for( i=0; i<height; i++ ) {
   272 	png_read_row(png_ptr, p, NULL );
   273 	p += rowbytes;
   274     }
   276     png_read_end(png_ptr, end_info);
   277     png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
   278     return buffer;
   279 }
   281 int get_log_level_from_string( const gchar *str )
   282 {
   283     switch( tolower(str[0]) ) {
   284     case 'd': return EMIT_DEBUG;
   285     case 'e': return EMIT_ERR;
   286     case 'f': return EMIT_FATAL;
   287     case 'i': return EMIT_INFO;
   288     case 't': return EMIT_TRACE;
   289     case 'w': return EMIT_WARN;
   290     default: return -1;
   291     }
   292 }
   294 gboolean set_global_log_level( const gchar *str ) 
   295 {
   296     int l = get_log_level_from_string(str);
   297     if( l == -1 ) {
   298 	return FALSE;
   299     } else {
   300 	global_msg_level = l;
   301 	return TRUE;
   302     }
   303 }
   305 void log_message( void *ptr, int level, const gchar *source, const char *msg, ... )
   306 {
   307     char buf[20];
   308     time_t tm = time(NULL);
   309     va_list ap;
   311     if( level > global_msg_level ) {
   312 	return; // ignored
   313     }
   315     va_start(ap, msg);
   316     gchar *text = g_strdup_vprintf( msg, ap );
   317     va_end(ap);
   319     if( level <= EMIT_ERR ) {
   320 	if( gui_error_dialog( text ) ) {
   321 	    g_free(text);
   322 	    return;
   323 	}
   324     }
   327     strftime( buf, sizeof(buf), "%H:%M:%S", localtime(&tm) );
   328     fprintf( stderr, "%s %08X %-5s %s\n", buf, sh4r.pc, msg_levels[level], text );
   329     g_free(text);
   330 }
.