Search
lxdream.org :: lxdream/src/util.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/util.c
changeset 1148:8e75fab17be8
prev1092:7c4ffe27e7b5
next1239:be3121267597
author nkeynes
date Wed Nov 10 08:37:42 2010 +1000 (13 years ago)
permissions -rw-r--r--
last change Add chain pointer to the xlat cache, so that we can maintain multiple blocks
for the same address. This prevents thrashing in cases where we would other
keep retranslating the same blocks over and over again due to varying
xlat_sh4_mode values
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 "dreamcast.h"
    34 #include "gui.h"
    35 #include "sh4/sh4.h"
    37 char *msg_levels[] = { "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" };
    38 int global_msg_level = EMIT_WARN;
    40 static void report_crash( int signo, siginfo_t *info, void *ptr )
    41 {
    42     char buf[128];
    44     fprintf( stderr, "--- Aborting with signal %d ---\n", signo );
    45     sh4_crashdump();
    46     // Get gdb to print a nice backtrace for us
    47 #ifdef APPLE_BUILD
    48     snprintf( buf, 128, "echo bt | gdb --quiet --pid=%d", getpid() );
    49 #else
    50     snprintf( buf, 128, "gdb -batch -f --quiet --pid=%d -ex bt", getpid() );
    51 #endif
    52     system(buf);
    54     abort();
    55 }
    57 void install_crash_handler(void)
    58 {
    59     struct sigaction sa;
    61     sa.sa_sigaction = report_crash;
    62     sigemptyset(&sa.sa_mask);
    63     sa.sa_flags = SA_RESETHAND|SA_SIGINFO;
    64     sigaction( SIGSEGV, &sa, NULL );
    65     sigaction( SIGILL, &sa, NULL );
    66     sigaction( SIGBUS, &sa, NULL );
    67 }
    70 void fwrite_string( const char *s, FILE *f )
    71 {
    72     uint32_t len = 0;
    73     if( s == NULL ) {
    74         fwrite( &len, sizeof(len), 1, f );
    75     } else {
    76         len = strlen(s)+1;
    77         fwrite( &len, sizeof(len), 1, f );
    78         fwrite( s, len, 1, f );
    79     }
    80 }
    82 int fread_string( char *s, int maxlen, FILE *f ) 
    83 {
    84     uint32_t len;
    85     fread( &len, sizeof(len), 1, f );
    86     if( len != 0 ) {
    87         fread( s, len > maxlen ? maxlen : len, 1, f );
    88     }
    89     return len;
    90 }
    92 int fwrite_gzip( void *p, size_t sz, size_t count, FILE *f )
    93 {
    94     uLongf size = sz*count;
    95     uLongf csize = ((int)(size*1.001))+13;
    96     unsigned char *tmp = g_malloc0( csize );
    97     int status = compress( tmp, &csize, p, size );
    98     assert( status == Z_OK );
    99     uint32_t wsize = (uint32_t)csize;
   100     fwrite( &wsize, sizeof(wsize), 1, f );
   101     int written = fwrite( tmp, csize, 1, f );
   102     g_free(tmp);
   104     /* Could be finer-grained, but this is enough to know it succeeded/failed */
   105     if( written == 1 ) {
   106         return count;
   107     } else {
   108         return 0;
   109     }
   110 }
   112 int fread_gzip( void *p, size_t sz, size_t count, FILE *f )
   113 {
   114     uLongf size = sz*count;
   115     uint32_t csize;
   116     unsigned char *tmp;
   118     fread( &csize, sizeof(csize), 1, f );
   119     assert( csize <= (size*2) );
   120     tmp = g_malloc0( csize );
   121     fread( tmp, csize, 1, f );
   122     int status = uncompress( p, &size, tmp, csize );
   123     g_free(tmp);
   124     if( status == Z_OK ) {
   125         return count;
   126     } else {
   127         fprintf( stderr, "Error reading compressed data\n" );
   128         return 0;
   129     }
   130 }
   132 void fwrite_dump( unsigned char *data, unsigned int length, FILE *f ) 
   133 {
   134     unsigned int i, j;
   135     for( i =0; i<length; i+=16 ) {
   136         fprintf( f, "%08X:", i);
   137         for( j=i; j<i+16; j++ ) {
   138             if( (j % 4) == 0 )
   139                 fprintf( f, " " );
   140             if( j < length )
   141                 fprintf( f, " %02X", (unsigned int)(data[j]) );
   142             else
   143                 fprintf( f, "   " );
   144         }
   145         fprintf( f, "  " );
   146         for( j=i; j<i+16 && j<length; j++ ) {
   147             fprintf( f, "%c", isprint(data[j]) ? data[j] : '.' );
   148         }
   149         fprintf( f, "\n" );
   150     }
   151 }
   153 void fwrite_dump32( unsigned int *data, unsigned int length, FILE *f ) 
   154 {
   155     fwrite_dump32v( data, length, 8, f );
   156 }
   158 void fwrite_dump32v( unsigned int *data, unsigned int length, int wordsPerLine, FILE *f ) 
   159 {
   160     unsigned int i, j;
   161     for( i =0; i<length>>2; i+=wordsPerLine ) {
   162         fprintf( f, "%08X:", i);
   163         for( j=i; j<i+wordsPerLine; j++ ) {
   164             if( j < length )
   165                 fprintf( f, " %08X", (unsigned int)(data[j]) );
   166             else
   167                 fprintf( f, "         " );
   168         }
   169         fprintf( f, "\n" );
   170     }
   171 }
   173 gboolean write_png_to_stream( FILE *f, frame_buffer_t buffer )
   174 {
   175     int coltype, i;
   176     png_bytep p;
   177     png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
   178     if (!png_ptr) {
   179         return FALSE;
   180     }
   182     png_infop info_ptr = png_create_info_struct(png_ptr);
   183     if (!info_ptr) {
   184         png_destroy_write_struct(&png_ptr, NULL);
   185         return FALSE;
   186     }
   188     if( setjmp(png_jmpbuf(png_ptr)) ) {
   189         png_destroy_write_struct(&png_ptr, &info_ptr);
   190         return FALSE;
   191     }
   192     png_init_io( png_ptr, f );
   193     switch( buffer->colour_format ) {
   194     case COLFMT_BGR888:
   195         coltype = PNG_COLOR_TYPE_RGB;
   196         break;
   197     case COLFMT_BGRA8888:
   198         coltype = PNG_COLOR_TYPE_RGB_ALPHA;
   199         break;
   200     case COLFMT_BGR0888:
   201         coltype = PNG_COLOR_TYPE_RGB;
   202         break;
   203     default:
   204         coltype = PNG_COLOR_TYPE_RGB;
   205     }
   206     png_set_IHDR(png_ptr, info_ptr, buffer->width, buffer->height,
   207                  8, coltype, PNG_INTERLACE_NONE, 
   208                  PNG_COMPRESSION_TYPE_DEFAULT, 
   209                  PNG_FILTER_TYPE_DEFAULT );
   210     png_write_info(png_ptr, info_ptr);
   211     if( buffer->colour_format == COLFMT_BGR0888 ) {
   212         png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
   213     }
   214     png_set_bgr(png_ptr);
   215     if( buffer->inverted ) {
   216         p = (png_bytep)(buffer->data + (buffer->height*buffer->rowstride) - buffer->rowstride);
   217         for(i=0; i<buffer->height; i++ ) {
   218             png_write_row(png_ptr, p);
   219             p-=buffer->rowstride;
   220         }
   221     } else {
   222         p = (png_bytep)buffer->data;
   223         for(i=0; i<buffer->height; i++ ) {
   224             png_write_row(png_ptr, p);
   225             p+=buffer->rowstride;
   226         }
   227     }
   228     png_write_end(png_ptr, info_ptr);
   229     png_destroy_write_struct(&png_ptr, &info_ptr);
   230     return TRUE;
   231 }
   233 frame_buffer_t read_png_from_stream( FILE *f )
   234 {
   235     png_bytep p;
   236     int i;
   237     png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 
   238             NULL, NULL, NULL);
   239     if (!png_ptr) {
   240         return NULL;
   241     }
   243     png_infop info_ptr = png_create_info_struct(png_ptr);
   244     if (!info_ptr) {
   245         png_destroy_read_struct(&png_ptr, NULL, NULL);
   246         return NULL;
   247     }
   249     png_infop end_info = png_create_info_struct(png_ptr);
   250     if (!end_info) {
   251         png_destroy_read_struct(&png_ptr, &info_ptr, NULL );
   252         return NULL;
   253     }
   255     if( setjmp(png_jmpbuf(png_ptr)) ) {
   256         png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
   257         return NULL;
   258     }
   260     png_init_io(png_ptr, f);
   261     png_read_info(png_ptr, info_ptr);
   263     png_uint_32 width, height;
   264     int bit_depth, color_type, interlace_type,
   265     compression_type, filter_method;
   266     png_get_IHDR(png_ptr, info_ptr, &width, &height,
   267                  &bit_depth, &color_type, &interlace_type,
   268                  &compression_type, &filter_method);
   269     assert( interlace_type == PNG_INTERLACE_NONE );
   270     int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
   271     int channels = png_get_channels(png_ptr, info_ptr);
   272     frame_buffer_t buffer = g_malloc( sizeof(struct frame_buffer) + rowbytes*height );
   273     buffer->data = (unsigned char *)(buffer+1);
   274     buffer->width = width;
   275     buffer->height = height;
   276     buffer->rowstride = rowbytes;
   277     buffer->address = -1;
   278     buffer->size = rowbytes*height;
   279     buffer->inverted = FALSE;
   280     if( channels == 4 ) {
   281         buffer->colour_format = COLFMT_BGRA8888;
   282     } else if( channels == 3 ) {
   283         buffer->colour_format = COLFMT_RGB888;
   284     }
   286     p = (png_bytep)buffer->data;
   287     for( i=0; i<height; i++ ) {
   288         png_read_row(png_ptr, p, NULL );
   289         p += rowbytes;
   290     }
   292     png_read_end(png_ptr, end_info);
   293     png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
   294     return buffer;
   295 }
   297 int get_log_level_from_string( const gchar *str )
   298 {
   299     switch( tolower(str[0]) ) {
   300     case 'd': return EMIT_DEBUG;
   301     case 'e': return EMIT_ERR;
   302     case 'f': return EMIT_FATAL;
   303     case 'i': return EMIT_INFO;
   304     case 't': return EMIT_TRACE;
   305     case 'w': return EMIT_WARN;
   306     default: return -1;
   307     }
   308 }
   310 gboolean set_global_log_level( const gchar *str ) 
   311 {
   312     int l = get_log_level_from_string(str);
   313     if( l == -1 ) {
   314         return FALSE;
   315     } else {
   316         global_msg_level = l;
   317         return TRUE;
   318     }
   319 }
   321 void log_message( void *ptr, int level, const gchar *source, const char *msg, ... )
   322 {
   323     char buf[20];
   324     time_t tm = time(NULL);
   325     va_list ap;
   327     if( level > global_msg_level ) {
   328         return; // ignored
   329     }
   331     va_start(ap, msg);
   332     gchar *text = g_strdup_vprintf( msg, ap );
   333     va_end(ap);
   335     if( level <= EMIT_ERR ) {
   336         if( gui_error_dialog( text ) ) {
   337             g_free(text);
   338             // If we're running, halt on error to avoid potentially flooding
   339             // the user with error messages.
   340             if( dreamcast_is_running() ) {
   341                 dreamcast_stop();
   342             }
   343             return;
   344         }
   345     }
   348     strftime( buf, sizeof(buf), "%H:%M:%S", localtime(&tm) );
   349     fprintf( stderr, "%s %08X %-5s %s\n", buf, sh4r.pc, msg_levels[level], text );
   350     g_free(text);
   351 }
.