Search
lxdream.org :: lxdream/src/util.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/util.c
changeset 768:b2a54f6864eb
prev736:a02d1475ccfd
next1042:0fd066956482
author nkeynes
date Sat Dec 27 02:59:35 2008 +0000 (15 years ago)
branchlxdream-mem
permissions -rw-r--r--
last change Replace fpscr_mask/fpscr flags in xlat_cache_block with a single xlat_sh4_mode,
which tracks the field of the same name in sh4r - actually a little faster this way.
Now depends on SR.MD, FPSCR.PR and FPSCR.SZ (although it doesn't benefit from the SR
flag yet).

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