Search
lxdream.org :: lxdream/src/util.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/util.c
changeset 674:377d987db8f2
prev586:2a3ba82cf243
next736:a02d1475ccfd
author nkeynes
date Sat Jun 14 11:54:15 2008 +0000 (15 years ago)
permissions -rw-r--r--
last change Change colour params to float
Convert background processing over to scene structure (fixes some depth issues as well)
Add color unclamp when supported
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@481
    33
#include "gui.h"
nkeynes@586
    34
#include "sh4/sh4.h"
nkeynes@437
    35
nkeynes@437
    36
char *msg_levels[] = { "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" };
nkeynes@502
    37
int global_msg_level = EMIT_WARN;
nkeynes@495
    38
nkeynes@495
    39
static void report_crash( int signo, siginfo_t *info, void *ptr )
nkeynes@495
    40
{
nkeynes@495
    41
    char buf[128];
nkeynes@495
    42
nkeynes@495
    43
    fprintf( stderr, "--- Aborting with signal %d ---\n", signo );
nkeynes@495
    44
    // Get gdb to print a nice backtrace for us
nkeynes@495
    45
    snprintf( buf, 128, "gdb -batch -f --quiet --pid=%d -ex bt", getpid() );
nkeynes@495
    46
    system(buf);
nkeynes@495
    47
nkeynes@495
    48
    abort();
nkeynes@495
    49
}
nkeynes@495
    50
nkeynes@495
    51
void install_crash_handler(void)
nkeynes@495
    52
{
nkeynes@495
    53
    struct sigaction sa;
nkeynes@495
    54
nkeynes@495
    55
    sa.sa_sigaction = report_crash;
nkeynes@495
    56
    sigemptyset(&sa.sa_mask);
nkeynes@495
    57
    sa.sa_flags = SA_RESETHAND|SA_SIGINFO;
nkeynes@495
    58
    sigaction( SIGSEGV, &sa, NULL );
nkeynes@495
    59
}
nkeynes@495
    60
nkeynes@17
    61
nkeynes@422
    62
void fwrite_string( const char *s, FILE *f )
nkeynes@17
    63
{
nkeynes@17
    64
    uint32_t len = 0;
nkeynes@17
    65
    if( s == NULL ) {
nkeynes@17
    66
	fwrite( &len, sizeof(len), 1, f );
nkeynes@17
    67
    } else {
nkeynes@17
    68
	len = strlen(s)+1;
nkeynes@17
    69
	fwrite( &len, sizeof(len), 1, f );
nkeynes@17
    70
	fwrite( s, len, 1, f );
nkeynes@17
    71
    }
nkeynes@17
    72
}
nkeynes@17
    73
nkeynes@17
    74
int fread_string( char *s, int maxlen, FILE *f ) 
nkeynes@17
    75
{
nkeynes@17
    76
    uint32_t len;
nkeynes@17
    77
    fread( &len, sizeof(len), 1, f );
nkeynes@17
    78
    if( len != 0 ) {
nkeynes@17
    79
	fread( s, len > maxlen ? maxlen : len, 1, f );
nkeynes@17
    80
    }
nkeynes@17
    81
    return len;
nkeynes@17
    82
}
nkeynes@117
    83
nkeynes@477
    84
void fwrite_gzip( void *p, size_t sz, size_t count, FILE *f )
nkeynes@477
    85
{
nkeynes@477
    86
    uLongf size = sz*count;
nkeynes@477
    87
    uLongf csize = ((int)(size*1.001))+13;
nkeynes@477
    88
    unsigned char *tmp = g_malloc0( csize );
nkeynes@477
    89
    int status = compress( tmp, &csize, p, size );
nkeynes@477
    90
    assert( status == Z_OK );
nkeynes@674
    91
    uint32_t wsize = (uint32_t)csize;
nkeynes@674
    92
    fwrite( &wsize, sizeof(wsize), 1, f );
nkeynes@477
    93
    fwrite( tmp, csize, 1, f );
nkeynes@477
    94
    g_free(tmp);
nkeynes@477
    95
}
nkeynes@477
    96
nkeynes@477
    97
int fread_gzip( void *p, size_t sz, size_t count, FILE *f )
nkeynes@477
    98
{
nkeynes@477
    99
    uLongf size = sz*count;
nkeynes@674
   100
    uint32_t csize;
nkeynes@477
   101
    unsigned char *tmp;
nkeynes@477
   102
nkeynes@477
   103
    fread( &csize, sizeof(csize), 1, f );
nkeynes@477
   104
    assert( csize <= (size*2) );
nkeynes@477
   105
    tmp = g_malloc0( csize );
nkeynes@477
   106
    fread( tmp, csize, 1, f );
nkeynes@477
   107
    int status = uncompress( p, &size, tmp, csize );
nkeynes@477
   108
    g_free(tmp);
nkeynes@477
   109
    if( status == Z_OK ) {
nkeynes@477
   110
	return count;
nkeynes@477
   111
    } else {
nkeynes@477
   112
	fprintf( stderr, "Error reading compressed data\n" );
nkeynes@477
   113
	return 0;
nkeynes@477
   114
    }
nkeynes@477
   115
}
nkeynes@477
   116
nkeynes@117
   117
void fwrite_dump( unsigned char *data, unsigned int length, FILE *f ) 
nkeynes@117
   118
{
nkeynes@117
   119
    unsigned int i, j;
nkeynes@117
   120
    for( i =0; i<length; i+=16 ) {
nkeynes@117
   121
	fprintf( f, "%08X:", i);
nkeynes@117
   122
	for( j=i; j<i+16; j++ ) {
nkeynes@117
   123
	    if( (j % 4) == 0 )
nkeynes@117
   124
		fprintf( f, " " );
nkeynes@117
   125
	    if( j < length )
nkeynes@117
   126
		fprintf( f, " %02X", (unsigned int)(data[j]) );
nkeynes@117
   127
	    else
nkeynes@117
   128
		fprintf( f, "   " );
nkeynes@117
   129
	}
nkeynes@117
   130
	fprintf( f, "  " );
nkeynes@117
   131
	for( j=i; j<i+16 && j<length; j++ ) {
nkeynes@117
   132
	    fprintf( f, "%c", isprint(data[j]) ? data[j] : '.' );
nkeynes@117
   133
	}
nkeynes@117
   134
	fprintf( f, "\n" );
nkeynes@117
   135
    }
nkeynes@117
   136
}
nkeynes@187
   137
nkeynes@187
   138
void fwrite_dump32( unsigned int *data, unsigned int length, FILE *f ) 
nkeynes@187
   139
{
nkeynes@220
   140
    fwrite_dump32v( data, length, 8, f );
nkeynes@220
   141
}
nkeynes@220
   142
nkeynes@220
   143
void fwrite_dump32v( unsigned int *data, unsigned int length, int wordsPerLine, FILE *f ) 
nkeynes@220
   144
{
nkeynes@187
   145
    unsigned int i, j;
nkeynes@220
   146
    for( i =0; i<length>>2; i+=wordsPerLine ) {
nkeynes@187
   147
	fprintf( f, "%08X:", i);
nkeynes@220
   148
	for( j=i; j<i+wordsPerLine; j++ ) {
nkeynes@187
   149
	    if( j < length )
nkeynes@187
   150
		fprintf( f, " %08X", (unsigned int)(data[j]) );
nkeynes@187
   151
	    else
nkeynes@187
   152
		fprintf( f, "         " );
nkeynes@187
   153
	}
nkeynes@187
   154
	fprintf( f, "\n" );
nkeynes@187
   155
    }
nkeynes@187
   156
}
nkeynes@437
   157
nkeynes@477
   158
gboolean write_png_to_stream( FILE *f, frame_buffer_t buffer )
nkeynes@477
   159
{
nkeynes@477
   160
    int coltype, i;
nkeynes@477
   161
    png_bytep p;
nkeynes@477
   162
    png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
nkeynes@477
   163
    if (!png_ptr) {
nkeynes@477
   164
	return FALSE;
nkeynes@477
   165
    }
nkeynes@477
   166
nkeynes@477
   167
    png_infop info_ptr = png_create_info_struct(png_ptr);
nkeynes@477
   168
    if (!info_ptr) {
nkeynes@477
   169
	png_destroy_write_struct(&png_ptr, NULL);
nkeynes@477
   170
	return FALSE;
nkeynes@477
   171
    }
nkeynes@477
   172
    
nkeynes@477
   173
    if( setjmp(png_jmpbuf(png_ptr)) ) {
nkeynes@477
   174
	png_destroy_write_struct(&png_ptr, &info_ptr);
nkeynes@477
   175
	return FALSE;
nkeynes@477
   176
    }
nkeynes@477
   177
    png_init_io( png_ptr, f );
nkeynes@477
   178
    switch( buffer->colour_format ) {
nkeynes@477
   179
    case COLFMT_BGR888:
nkeynes@477
   180
	coltype = PNG_COLOR_TYPE_RGB;
nkeynes@477
   181
	break;
nkeynes@477
   182
    case COLFMT_BGRA8888:
nkeynes@477
   183
	coltype = PNG_COLOR_TYPE_RGB_ALPHA;
nkeynes@477
   184
	break;
nkeynes@477
   185
    case COLFMT_BGR0888:
nkeynes@477
   186
	coltype = PNG_COLOR_TYPE_RGB;
nkeynes@477
   187
	break;
nkeynes@477
   188
    default:
nkeynes@477
   189
	coltype = PNG_COLOR_TYPE_RGB;
nkeynes@477
   190
    }
nkeynes@477
   191
    png_set_IHDR(png_ptr, info_ptr, buffer->width, buffer->height,
nkeynes@477
   192
		 8, coltype, PNG_INTERLACE_NONE, 
nkeynes@477
   193
		 PNG_COMPRESSION_TYPE_DEFAULT, 
nkeynes@477
   194
		 PNG_FILTER_TYPE_DEFAULT );
nkeynes@477
   195
    png_write_info(png_ptr, info_ptr);
nkeynes@477
   196
    if( buffer->colour_format == COLFMT_BGR0888 ) {
nkeynes@477
   197
	png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
nkeynes@477
   198
    }
nkeynes@477
   199
    png_set_bgr(png_ptr);
nkeynes@477
   200
    if( buffer->inverted ) {
nkeynes@481
   201
	p = (png_bytep)(buffer->data + (buffer->height*buffer->rowstride) - buffer->rowstride);
nkeynes@477
   202
	for(i=0; i<buffer->height; i++ ) {
nkeynes@477
   203
	    png_write_row(png_ptr, p);
nkeynes@477
   204
	    p-=buffer->rowstride;
nkeynes@477
   205
	}
nkeynes@477
   206
    } else {
nkeynes@481
   207
	p = (png_bytep)buffer->data;
nkeynes@477
   208
	for(i=0; i<buffer->height; i++ ) {
nkeynes@477
   209
	    png_write_row(png_ptr, p);
nkeynes@477
   210
	    p+=buffer->rowstride;
nkeynes@477
   211
	}
nkeynes@477
   212
    }
nkeynes@477
   213
    png_write_end(png_ptr, info_ptr);
nkeynes@477
   214
    png_destroy_write_struct(&png_ptr, &info_ptr);
nkeynes@477
   215
    return TRUE;
nkeynes@477
   216
}
nkeynes@477
   217
nkeynes@477
   218
frame_buffer_t read_png_from_stream( FILE *f )
nkeynes@477
   219
{
nkeynes@477
   220
    png_bytep p;
nkeynes@477
   221
    int i;
nkeynes@477
   222
    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 
nkeynes@477
   223
						 NULL, NULL, NULL);
nkeynes@477
   224
    if (!png_ptr) {
nkeynes@477
   225
	return NULL;
nkeynes@477
   226
    }
nkeynes@477
   227
nkeynes@477
   228
    png_infop info_ptr = png_create_info_struct(png_ptr);
nkeynes@477
   229
    if (!info_ptr) {
nkeynes@477
   230
	png_destroy_read_struct(&png_ptr, NULL, NULL);
nkeynes@477
   231
	return NULL;
nkeynes@477
   232
    }
nkeynes@477
   233
    
nkeynes@477
   234
    png_infop end_info = png_create_info_struct(png_ptr);
nkeynes@477
   235
    if (!end_info) {
nkeynes@477
   236
	png_destroy_read_struct(&png_ptr, &info_ptr, NULL );
nkeynes@477
   237
	return NULL;
nkeynes@477
   238
    }
nkeynes@477
   239
nkeynes@477
   240
    if( setjmp(png_jmpbuf(png_ptr)) ) {
nkeynes@477
   241
	png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
nkeynes@477
   242
	return NULL;
nkeynes@477
   243
    }
nkeynes@477
   244
nkeynes@477
   245
    png_init_io(png_ptr, f);
nkeynes@477
   246
    png_read_info(png_ptr, info_ptr);
nkeynes@477
   247
    
nkeynes@477
   248
    png_uint_32 width, height;
nkeynes@477
   249
    int bit_depth, color_type, interlace_type,
nkeynes@477
   250
	compression_type, filter_method;
nkeynes@477
   251
    png_get_IHDR(png_ptr, info_ptr, &width, &height,
nkeynes@477
   252
		 &bit_depth, &color_type, &interlace_type,
nkeynes@477
   253
		 &compression_type, &filter_method);
nkeynes@477
   254
    assert( interlace_type == PNG_INTERLACE_NONE );
nkeynes@477
   255
    int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
nkeynes@477
   256
    int channels = png_get_channels(png_ptr, info_ptr);
nkeynes@477
   257
    frame_buffer_t buffer = g_malloc( sizeof(struct frame_buffer) + rowbytes*height );
nkeynes@502
   258
    buffer->data = (unsigned char *)(buffer+1);
nkeynes@477
   259
    buffer->width = width;
nkeynes@477
   260
    buffer->height = height;
nkeynes@477
   261
    buffer->rowstride = rowbytes;
nkeynes@477
   262
    buffer->address = -1;
nkeynes@477
   263
    buffer->size = rowbytes*height;
nkeynes@477
   264
    buffer->inverted = FALSE;
nkeynes@477
   265
    if( channels == 4 ) {
nkeynes@477
   266
	buffer->colour_format = COLFMT_BGRA8888;
nkeynes@477
   267
    } else if( channels == 3 ) {
nkeynes@477
   268
	buffer->colour_format = COLFMT_RGB888;
nkeynes@477
   269
    }
nkeynes@477
   270
    
nkeynes@481
   271
    p = (png_bytep)buffer->data;
nkeynes@477
   272
    for( i=0; i<height; i++ ) {
nkeynes@477
   273
	png_read_row(png_ptr, p, NULL );
nkeynes@477
   274
	p += rowbytes;
nkeynes@477
   275
    }
nkeynes@477
   276
nkeynes@477
   277
    png_read_end(png_ptr, end_info);
nkeynes@477
   278
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
nkeynes@477
   279
    return buffer;
nkeynes@477
   280
}
nkeynes@437
   281
nkeynes@586
   282
int get_log_level_from_string( const gchar *str )
nkeynes@586
   283
{
nkeynes@586
   284
    switch( tolower(str[0]) ) {
nkeynes@586
   285
    case 'd': return EMIT_DEBUG;
nkeynes@586
   286
    case 'e': return EMIT_ERR;
nkeynes@586
   287
    case 'f': return EMIT_FATAL;
nkeynes@586
   288
    case 'i': return EMIT_INFO;
nkeynes@586
   289
    case 't': return EMIT_TRACE;
nkeynes@586
   290
    case 'w': return EMIT_WARN;
nkeynes@586
   291
    default: return -1;
nkeynes@586
   292
    }
nkeynes@586
   293
}
nkeynes@586
   294
nkeynes@586
   295
gboolean set_global_log_level( const gchar *str ) 
nkeynes@586
   296
{
nkeynes@586
   297
    int l = get_log_level_from_string(str);
nkeynes@586
   298
    if( l == -1 ) {
nkeynes@586
   299
	return FALSE;
nkeynes@586
   300
    } else {
nkeynes@586
   301
	global_msg_level = l;
nkeynes@586
   302
	return TRUE;
nkeynes@586
   303
    }
nkeynes@586
   304
}
nkeynes@586
   305
nkeynes@437
   306
void log_message( void *ptr, int level, const gchar *source, const char *msg, ... )
nkeynes@437
   307
{
nkeynes@481
   308
    char buf[20];
nkeynes@437
   309
    time_t tm = time(NULL);
nkeynes@437
   310
    va_list ap;
nkeynes@437
   311
nkeynes@437
   312
    if( level > global_msg_level ) {
nkeynes@437
   313
	return; // ignored
nkeynes@437
   314
    }
nkeynes@447
   315
nkeynes@437
   316
    va_start(ap, msg);
nkeynes@535
   317
    gchar *text = g_strdup_vprintf( msg, ap );
nkeynes@535
   318
    va_end(ap);
nkeynes@535
   319
    
nkeynes@447
   320
    if( level <= EMIT_ERR ) {
nkeynes@447
   321
	if( gui_error_dialog( text ) ) {
nkeynes@447
   322
	    g_free(text);
nkeynes@447
   323
	    return;
nkeynes@447
   324
	}
nkeynes@447
   325
    }
nkeynes@447
   326
nkeynes@447
   327
nkeynes@437
   328
    strftime( buf, sizeof(buf), "%H:%M:%S", localtime(&tm) );
nkeynes@535
   329
    fprintf( stderr, "%s %08X %-5s %s\n", buf, sh4r.pc, msg_levels[level], text );
nkeynes@535
   330
    g_free(text);
nkeynes@437
   331
}
.