4 * Miscellaneous utility functions.
6 * Copyright (c) 2005 Nathan Keynes.
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.
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.
19 #define HAVE_EXECINFO_H 1
33 #include "dreamcast.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 )
44 fprintf( stderr, "--- Aborting with signal %d ---\n", signo );
46 // Get gdb to print a nice backtrace for us
48 snprintf( buf, 128, "echo bt | gdb --quiet --pid=%d", getpid() );
50 snprintf( buf, 128, "gdb -batch -f --quiet --pid=%d -ex bt", getpid() );
57 void install_crash_handler(void)
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 );
70 void fwrite_string( const char *s, FILE *f )
74 fwrite( &len, sizeof(len), 1, f );
77 fwrite( &len, sizeof(len), 1, f );
78 fwrite( s, len, 1, f );
82 int fread_string( char *s, int maxlen, FILE *f )
85 fread( &len, sizeof(len), 1, f );
87 fread( s, len > maxlen ? maxlen : len, 1, f );
92 int fwrite_gzip( void *p, size_t sz, size_t count, FILE *f )
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 );
104 /* Could be finer-grained, but this is enough to know it succeeded/failed */
112 int fread_gzip( void *p, size_t sz, size_t count, FILE *f )
114 uLongf size = sz*count;
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 );
124 if( status == Z_OK ) {
127 fprintf( stderr, "Error reading compressed data\n" );
132 void fwrite_dump( unsigned char *data, unsigned int length, FILE *f )
135 for( i =0; i<length; i+=16 ) {
136 fprintf( f, "%08X:", i);
137 for( j=i; j<i+16; j++ ) {
141 fprintf( f, " %02X", (unsigned int)(data[j]) );
146 for( j=i; j<i+16 && j<length; j++ ) {
147 fprintf( f, "%c", isprint(data[j]) ? data[j] : '.' );
153 void fwrite_dump32( unsigned int *data, unsigned int length, FILE *f )
155 fwrite_dump32v( data, length, 8, f );
158 void fwrite_dump32v( unsigned int *data, unsigned int length, int wordsPerLine, FILE *f )
161 for( i =0; i<length>>2; i+=wordsPerLine ) {
162 fprintf( f, "%08X:", i);
163 for( j=i; j<i+wordsPerLine; j++ ) {
165 fprintf( f, " %08X", (unsigned int)(data[j]) );
173 gboolean write_png_to_stream( FILE *f, frame_buffer_t buffer )
177 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
182 png_infop info_ptr = png_create_info_struct(png_ptr);
184 png_destroy_write_struct(&png_ptr, NULL);
188 if( setjmp(png_jmpbuf(png_ptr)) ) {
189 png_destroy_write_struct(&png_ptr, &info_ptr);
192 png_init_io( png_ptr, f );
193 switch( buffer->colour_format ) {
195 coltype = PNG_COLOR_TYPE_RGB;
197 case COLFMT_BGRA8888:
198 coltype = PNG_COLOR_TYPE_RGB_ALPHA;
201 coltype = PNG_COLOR_TYPE_RGB;
204 coltype = PNG_COLOR_TYPE_RGB;
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);
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;
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;
228 png_write_end(png_ptr, info_ptr);
229 png_destroy_write_struct(&png_ptr, &info_ptr);
233 frame_buffer_t read_png_from_stream( FILE *f )
237 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
243 png_infop info_ptr = png_create_info_struct(png_ptr);
245 png_destroy_read_struct(&png_ptr, NULL, NULL);
249 png_infop end_info = png_create_info_struct(png_ptr);
251 png_destroy_read_struct(&png_ptr, &info_ptr, NULL );
255 if( setjmp(png_jmpbuf(png_ptr)) ) {
256 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
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;
286 p = (png_bytep)buffer->data;
287 for( i=0; i<height; i++ ) {
288 png_read_row(png_ptr, p, NULL );
292 png_read_end(png_ptr, end_info);
293 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
297 int get_log_level_from_string( const gchar *str )
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;
310 gboolean set_global_log_level( const gchar *str )
312 int l = get_log_level_from_string(str);
316 global_msg_level = l;
321 void log_message( void *ptr, int level, const gchar *source, const char *msg, ... )
324 time_t tm = time(NULL);
327 if( level > global_msg_level ) {
332 gchar *text = g_strdup_vprintf( msg, ap );
335 if( level <= EMIT_ERR ) {
336 if( gui_error_dialog( text ) ) {
338 // If we're running, halt on error to avoid potentially flooding
339 // the user with error messages.
340 if( dreamcast_is_running() ) {
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 );
.