Search
lxdream.org :: lxdream/src/util.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/util.c
changeset 1091:186558374345
prev1065:bc1cc0c54917
next1092:7c4ffe27e7b5
author nkeynes
date Tue Dec 15 08:46:37 2009 +1000 (12 years ago)
permissions -rw-r--r--
last change Add side-by-side x86+sh4 disassembly output
Print SH4 state information and disassembly of the current block when
crashing.
Fix delay slot instruction in conditional branch not being marked as a
delay-slot instruction in the branch-not-taken path.
Rename REG_* defines in cpu.h to avoid conflict with translation defs
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     snprintf( buf, 128, "gdb -batch -f --quiet --pid=%d -ex bt", getpid() );
    48     system(buf);
    50     abort();
    51 }
    53 void install_crash_handler(void)
    54 {
    55     struct sigaction sa;
    57     sa.sa_sigaction = report_crash;
    58     sigemptyset(&sa.sa_mask);
    59     sa.sa_flags = SA_RESETHAND|SA_SIGINFO;
    60     sigaction( SIGSEGV, &sa, NULL );
    61 }
    64 void fwrite_string( const char *s, FILE *f )
    65 {
    66     uint32_t len = 0;
    67     if( s == NULL ) {
    68         fwrite( &len, sizeof(len), 1, f );
    69     } else {
    70         len = strlen(s)+1;
    71         fwrite( &len, sizeof(len), 1, f );
    72         fwrite( s, len, 1, f );
    73     }
    74 }
    76 int fread_string( char *s, int maxlen, FILE *f ) 
    77 {
    78     uint32_t len;
    79     fread( &len, sizeof(len), 1, f );
    80     if( len != 0 ) {
    81         fread( s, len > maxlen ? maxlen : len, 1, f );
    82     }
    83     return len;
    84 }
    86 int fwrite_gzip( void *p, size_t sz, size_t count, FILE *f )
    87 {
    88     uLongf size = sz*count;
    89     uLongf csize = ((int)(size*1.001))+13;
    90     unsigned char *tmp = g_malloc0( csize );
    91     int status = compress( tmp, &csize, p, size );
    92     assert( status == Z_OK );
    93     uint32_t wsize = (uint32_t)csize;
    94     fwrite( &wsize, sizeof(wsize), 1, f );
    95     int written = fwrite( tmp, csize, 1, f );
    96     g_free(tmp);
    98     /* Could be finer-grained, but this is enough to know it succeeded/failed */
    99     if( written == 1 ) {
   100         return count;
   101     } else {
   102         return 0;
   103     }
   104 }
   106 int fread_gzip( void *p, size_t sz, size_t count, FILE *f )
   107 {
   108     uLongf size = sz*count;
   109     uint32_t csize;
   110     unsigned char *tmp;
   112     fread( &csize, sizeof(csize), 1, f );
   113     assert( csize <= (size*2) );
   114     tmp = g_malloc0( csize );
   115     fread( tmp, csize, 1, f );
   116     int status = uncompress( p, &size, tmp, csize );
   117     g_free(tmp);
   118     if( status == Z_OK ) {
   119         return count;
   120     } else {
   121         fprintf( stderr, "Error reading compressed data\n" );
   122         return 0;
   123     }
   124 }
   126 void fwrite_dump( unsigned char *data, unsigned int length, FILE *f ) 
   127 {
   128     unsigned int i, j;
   129     for( i =0; i<length; i+=16 ) {
   130         fprintf( f, "%08X:", i);
   131         for( j=i; j<i+16; j++ ) {
   132             if( (j % 4) == 0 )
   133                 fprintf( f, " " );
   134             if( j < length )
   135                 fprintf( f, " %02X", (unsigned int)(data[j]) );
   136             else
   137                 fprintf( f, "   " );
   138         }
   139         fprintf( f, "  " );
   140         for( j=i; j<i+16 && j<length; j++ ) {
   141             fprintf( f, "%c", isprint(data[j]) ? data[j] : '.' );
   142         }
   143         fprintf( f, "\n" );
   144     }
   145 }
   147 void fwrite_dump32( unsigned int *data, unsigned int length, FILE *f ) 
   148 {
   149     fwrite_dump32v( data, length, 8, f );
   150 }
   152 void fwrite_dump32v( unsigned int *data, unsigned int length, int wordsPerLine, FILE *f ) 
   153 {
   154     unsigned int i, j;
   155     for( i =0; i<length>>2; i+=wordsPerLine ) {
   156         fprintf( f, "%08X:", i);
   157         for( j=i; j<i+wordsPerLine; j++ ) {
   158             if( j < length )
   159                 fprintf( f, " %08X", (unsigned int)(data[j]) );
   160             else
   161                 fprintf( f, "         " );
   162         }
   163         fprintf( f, "\n" );
   164     }
   165 }
   167 gboolean write_png_to_stream( FILE *f, frame_buffer_t buffer )
   168 {
   169     int coltype, i;
   170     png_bytep p;
   171     png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
   172     if (!png_ptr) {
   173         return FALSE;
   174     }
   176     png_infop info_ptr = png_create_info_struct(png_ptr);
   177     if (!info_ptr) {
   178         png_destroy_write_struct(&png_ptr, NULL);
   179         return FALSE;
   180     }
   182     if( setjmp(png_jmpbuf(png_ptr)) ) {
   183         png_destroy_write_struct(&png_ptr, &info_ptr);
   184         return FALSE;
   185     }
   186     png_init_io( png_ptr, f );
   187     switch( buffer->colour_format ) {
   188     case COLFMT_BGR888:
   189         coltype = PNG_COLOR_TYPE_RGB;
   190         break;
   191     case COLFMT_BGRA8888:
   192         coltype = PNG_COLOR_TYPE_RGB_ALPHA;
   193         break;
   194     case COLFMT_BGR0888:
   195         coltype = PNG_COLOR_TYPE_RGB;
   196         break;
   197     default:
   198         coltype = PNG_COLOR_TYPE_RGB;
   199     }
   200     png_set_IHDR(png_ptr, info_ptr, buffer->width, buffer->height,
   201                  8, coltype, PNG_INTERLACE_NONE, 
   202                  PNG_COMPRESSION_TYPE_DEFAULT, 
   203                  PNG_FILTER_TYPE_DEFAULT );
   204     png_write_info(png_ptr, info_ptr);
   205     if( buffer->colour_format == COLFMT_BGR0888 ) {
   206         png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
   207     }
   208     png_set_bgr(png_ptr);
   209     if( buffer->inverted ) {
   210         p = (png_bytep)(buffer->data + (buffer->height*buffer->rowstride) - buffer->rowstride);
   211         for(i=0; i<buffer->height; i++ ) {
   212             png_write_row(png_ptr, p);
   213             p-=buffer->rowstride;
   214         }
   215     } else {
   216         p = (png_bytep)buffer->data;
   217         for(i=0; i<buffer->height; i++ ) {
   218             png_write_row(png_ptr, p);
   219             p+=buffer->rowstride;
   220         }
   221     }
   222     png_write_end(png_ptr, info_ptr);
   223     png_destroy_write_struct(&png_ptr, &info_ptr);
   224     return TRUE;
   225 }
   227 frame_buffer_t read_png_from_stream( FILE *f )
   228 {
   229     png_bytep p;
   230     int i;
   231     png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 
   232             NULL, NULL, NULL);
   233     if (!png_ptr) {
   234         return NULL;
   235     }
   237     png_infop info_ptr = png_create_info_struct(png_ptr);
   238     if (!info_ptr) {
   239         png_destroy_read_struct(&png_ptr, NULL, NULL);
   240         return NULL;
   241     }
   243     png_infop end_info = png_create_info_struct(png_ptr);
   244     if (!end_info) {
   245         png_destroy_read_struct(&png_ptr, &info_ptr, NULL );
   246         return NULL;
   247     }
   249     if( setjmp(png_jmpbuf(png_ptr)) ) {
   250         png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
   251         return NULL;
   252     }
   254     png_init_io(png_ptr, f);
   255     png_read_info(png_ptr, info_ptr);
   257     png_uint_32 width, height;
   258     int bit_depth, color_type, interlace_type,
   259     compression_type, filter_method;
   260     png_get_IHDR(png_ptr, info_ptr, &width, &height,
   261                  &bit_depth, &color_type, &interlace_type,
   262                  &compression_type, &filter_method);
   263     assert( interlace_type == PNG_INTERLACE_NONE );
   264     int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
   265     int channels = png_get_channels(png_ptr, info_ptr);
   266     frame_buffer_t buffer = g_malloc( sizeof(struct frame_buffer) + rowbytes*height );
   267     buffer->data = (unsigned char *)(buffer+1);
   268     buffer->width = width;
   269     buffer->height = height;
   270     buffer->rowstride = rowbytes;
   271     buffer->address = -1;
   272     buffer->size = rowbytes*height;
   273     buffer->inverted = FALSE;
   274     if( channels == 4 ) {
   275         buffer->colour_format = COLFMT_BGRA8888;
   276     } else if( channels == 3 ) {
   277         buffer->colour_format = COLFMT_RGB888;
   278     }
   280     p = (png_bytep)buffer->data;
   281     for( i=0; i<height; i++ ) {
   282         png_read_row(png_ptr, p, NULL );
   283         p += rowbytes;
   284     }
   286     png_read_end(png_ptr, end_info);
   287     png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
   288     return buffer;
   289 }
   291 int get_log_level_from_string( const gchar *str )
   292 {
   293     switch( tolower(str[0]) ) {
   294     case 'd': return EMIT_DEBUG;
   295     case 'e': return EMIT_ERR;
   296     case 'f': return EMIT_FATAL;
   297     case 'i': return EMIT_INFO;
   298     case 't': return EMIT_TRACE;
   299     case 'w': return EMIT_WARN;
   300     default: return -1;
   301     }
   302 }
   304 gboolean set_global_log_level( const gchar *str ) 
   305 {
   306     int l = get_log_level_from_string(str);
   307     if( l == -1 ) {
   308         return FALSE;
   309     } else {
   310         global_msg_level = l;
   311         return TRUE;
   312     }
   313 }
   315 void log_message( void *ptr, int level, const gchar *source, const char *msg, ... )
   316 {
   317     char buf[20];
   318     time_t tm = time(NULL);
   319     va_list ap;
   321     if( level > global_msg_level ) {
   322         return; // ignored
   323     }
   325     va_start(ap, msg);
   326     gchar *text = g_strdup_vprintf( msg, ap );
   327     va_end(ap);
   329     if( level <= EMIT_ERR ) {
   330         if( gui_error_dialog( text ) ) {
   331             g_free(text);
   332             // If we're running, halt on error to avoid potentially flooding
   333             // the user with error messages.
   334             if( dreamcast_is_running() ) {
   335                 dreamcast_stop();
   336             }
   337             return;
   338         }
   339     }
   342     strftime( buf, sizeof(buf), "%H:%M:%S", localtime(&tm) );
   343     fprintf( stderr, "%s %08X %-5s %s\n", buf, sh4r.pc, msg_levels[level], text );
   344     g_free(text);
   345 }
.