Search
lxdream.org :: lxdream/src/util.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/util.c
changeset 477:9a373f2ff009
prev447:3e095bfcb476
next481:3b2d6c5a19ad
author nkeynes
date Wed Oct 31 09:10:23 2007 +0000 (16 years ago)
permissions -rw-r--r--
last change Add save/restore of render buffers in save states
Gzip memory blocks in save states
Move front-buffer management back to pvr2
Add screenshot preview when loading save states
Various minor fixes and cleanups
file annotate diff log raw
nkeynes@31
     1
/**
nkeynes@477
     2
 * $Id: util.c,v 1.11 2007-10-31 09:10:23 nkeynes Exp $
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@477
    19
#include <assert.h>
nkeynes@425
    20
#include <ctype.h>
nkeynes@437
    21
#include <stdarg.h>
nkeynes@437
    22
#include <stdio.h>
nkeynes@437
    23
#include <stdlib.h>
nkeynes@437
    24
#include <time.h>
nkeynes@477
    25
#include <zlib.h>
nkeynes@477
    26
#include <glib.h>
nkeynes@477
    27
#include <png.h>
nkeynes@17
    28
#include "dream.h"
nkeynes@477
    29
#include "display.h"
nkeynes@437
    30
#include "sh4/sh4core.h"
nkeynes@437
    31
nkeynes@437
    32
char *msg_levels[] = { "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" };
nkeynes@437
    33
int global_msg_level = EMIT_WARN;
nkeynes@17
    34
nkeynes@422
    35
void fwrite_string( const char *s, FILE *f )
nkeynes@17
    36
{
nkeynes@17
    37
    uint32_t len = 0;
nkeynes@17
    38
    if( s == NULL ) {
nkeynes@17
    39
	fwrite( &len, sizeof(len), 1, f );
nkeynes@17
    40
    } else {
nkeynes@17
    41
	len = strlen(s)+1;
nkeynes@17
    42
	fwrite( &len, sizeof(len), 1, f );
nkeynes@17
    43
	fwrite( s, len, 1, f );
nkeynes@17
    44
    }
nkeynes@17
    45
}
nkeynes@17
    46
nkeynes@17
    47
int fread_string( char *s, int maxlen, FILE *f ) 
nkeynes@17
    48
{
nkeynes@17
    49
    uint32_t len;
nkeynes@17
    50
    fread( &len, sizeof(len), 1, f );
nkeynes@17
    51
    if( len != 0 ) {
nkeynes@17
    52
	fread( s, len > maxlen ? maxlen : len, 1, f );
nkeynes@17
    53
    }
nkeynes@17
    54
    return len;
nkeynes@17
    55
}
nkeynes@117
    56
nkeynes@477
    57
void fwrite_gzip( void *p, size_t sz, size_t count, FILE *f )
nkeynes@477
    58
{
nkeynes@477
    59
    uLongf size = sz*count;
nkeynes@477
    60
    uLongf csize = ((int)(size*1.001))+13;
nkeynes@477
    61
    unsigned char *tmp = g_malloc0( csize );
nkeynes@477
    62
    int status = compress( tmp, &csize, p, size );
nkeynes@477
    63
    assert( status == Z_OK );
nkeynes@477
    64
    fwrite( &csize, sizeof(csize), 1, f );
nkeynes@477
    65
    fwrite( tmp, csize, 1, f );
nkeynes@477
    66
    g_free(tmp);
nkeynes@477
    67
}
nkeynes@477
    68
nkeynes@477
    69
int fread_gzip( void *p, size_t sz, size_t count, FILE *f )
nkeynes@477
    70
{
nkeynes@477
    71
    uLongf size = sz*count;
nkeynes@477
    72
    uLongf csize;
nkeynes@477
    73
    unsigned char *tmp;
nkeynes@477
    74
nkeynes@477
    75
    fread( &csize, sizeof(csize), 1, f );
nkeynes@477
    76
    assert( csize <= (size*2) );
nkeynes@477
    77
    tmp = g_malloc0( csize );
nkeynes@477
    78
    fread( tmp, csize, 1, f );
nkeynes@477
    79
    int status = uncompress( p, &size, tmp, csize );
nkeynes@477
    80
    g_free(tmp);
nkeynes@477
    81
    if( status == Z_OK ) {
nkeynes@477
    82
	return count;
nkeynes@477
    83
    } else {
nkeynes@477
    84
	fprintf( stderr, "Error reading compressed data\n" );
nkeynes@477
    85
	return 0;
nkeynes@477
    86
    }
nkeynes@477
    87
}
nkeynes@477
    88
nkeynes@117
    89
void fwrite_dump( unsigned char *data, unsigned int length, FILE *f ) 
nkeynes@117
    90
{
nkeynes@117
    91
    unsigned int i, j;
nkeynes@117
    92
    for( i =0; i<length; i+=16 ) {
nkeynes@117
    93
	fprintf( f, "%08X:", i);
nkeynes@117
    94
	for( j=i; j<i+16; j++ ) {
nkeynes@117
    95
	    if( (j % 4) == 0 )
nkeynes@117
    96
		fprintf( f, " " );
nkeynes@117
    97
	    if( j < length )
nkeynes@117
    98
		fprintf( f, " %02X", (unsigned int)(data[j]) );
nkeynes@117
    99
	    else
nkeynes@117
   100
		fprintf( f, "   " );
nkeynes@117
   101
	}
nkeynes@117
   102
	fprintf( f, "  " );
nkeynes@117
   103
	for( j=i; j<i+16 && j<length; j++ ) {
nkeynes@117
   104
	    fprintf( f, "%c", isprint(data[j]) ? data[j] : '.' );
nkeynes@117
   105
	}
nkeynes@117
   106
	fprintf( f, "\n" );
nkeynes@117
   107
    }
nkeynes@117
   108
}
nkeynes@187
   109
nkeynes@187
   110
void fwrite_dump32( unsigned int *data, unsigned int length, FILE *f ) 
nkeynes@187
   111
{
nkeynes@220
   112
    fwrite_dump32v( data, length, 8, f );
nkeynes@220
   113
}
nkeynes@220
   114
nkeynes@220
   115
void fwrite_dump32v( unsigned int *data, unsigned int length, int wordsPerLine, FILE *f ) 
nkeynes@220
   116
{
nkeynes@187
   117
    unsigned int i, j;
nkeynes@220
   118
    for( i =0; i<length>>2; i+=wordsPerLine ) {
nkeynes@187
   119
	fprintf( f, "%08X:", i);
nkeynes@220
   120
	for( j=i; j<i+wordsPerLine; j++ ) {
nkeynes@187
   121
	    if( j < length )
nkeynes@187
   122
		fprintf( f, " %08X", (unsigned int)(data[j]) );
nkeynes@187
   123
	    else
nkeynes@187
   124
		fprintf( f, "         " );
nkeynes@187
   125
	}
nkeynes@187
   126
	fprintf( f, "\n" );
nkeynes@187
   127
    }
nkeynes@187
   128
}
nkeynes@437
   129
nkeynes@477
   130
gboolean write_png_to_stream( FILE *f, frame_buffer_t buffer )
nkeynes@477
   131
{
nkeynes@477
   132
    int coltype, i;
nkeynes@477
   133
    png_bytep p;
nkeynes@477
   134
    png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
nkeynes@477
   135
    if (!png_ptr) {
nkeynes@477
   136
	return FALSE;
nkeynes@477
   137
    }
nkeynes@477
   138
nkeynes@477
   139
    png_infop info_ptr = png_create_info_struct(png_ptr);
nkeynes@477
   140
    if (!info_ptr) {
nkeynes@477
   141
	png_destroy_write_struct(&png_ptr, NULL);
nkeynes@477
   142
	return FALSE;
nkeynes@477
   143
    }
nkeynes@477
   144
    
nkeynes@477
   145
    if( setjmp(png_jmpbuf(png_ptr)) ) {
nkeynes@477
   146
	png_destroy_write_struct(&png_ptr, &info_ptr);
nkeynes@477
   147
	return FALSE;
nkeynes@477
   148
    }
nkeynes@477
   149
    png_init_io( png_ptr, f );
nkeynes@477
   150
    switch( buffer->colour_format ) {
nkeynes@477
   151
    case COLFMT_BGR888:
nkeynes@477
   152
	coltype = PNG_COLOR_TYPE_RGB;
nkeynes@477
   153
	break;
nkeynes@477
   154
    case COLFMT_BGRA8888:
nkeynes@477
   155
	coltype = PNG_COLOR_TYPE_RGB_ALPHA;
nkeynes@477
   156
	break;
nkeynes@477
   157
    case COLFMT_BGR0888:
nkeynes@477
   158
	coltype = PNG_COLOR_TYPE_RGB;
nkeynes@477
   159
	break;
nkeynes@477
   160
    default:
nkeynes@477
   161
	coltype = PNG_COLOR_TYPE_RGB;
nkeynes@477
   162
    }
nkeynes@477
   163
    png_set_IHDR(png_ptr, info_ptr, buffer->width, buffer->height,
nkeynes@477
   164
		 8, coltype, PNG_INTERLACE_NONE, 
nkeynes@477
   165
		 PNG_COMPRESSION_TYPE_DEFAULT, 
nkeynes@477
   166
		 PNG_FILTER_TYPE_DEFAULT );
nkeynes@477
   167
    png_write_info(png_ptr, info_ptr);
nkeynes@477
   168
    if( buffer->colour_format == COLFMT_BGR0888 ) {
nkeynes@477
   169
	png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
nkeynes@477
   170
    }
nkeynes@477
   171
    png_set_bgr(png_ptr);
nkeynes@477
   172
    if( buffer->inverted ) {
nkeynes@477
   173
	p = buffer->data + (buffer->height*buffer->rowstride) - buffer->rowstride;
nkeynes@477
   174
	for(i=0; i<buffer->height; i++ ) {
nkeynes@477
   175
	    png_write_row(png_ptr, p);
nkeynes@477
   176
	    p-=buffer->rowstride;
nkeynes@477
   177
	}
nkeynes@477
   178
    } else {
nkeynes@477
   179
	p = buffer->data;
nkeynes@477
   180
	for(i=0; i<buffer->height; i++ ) {
nkeynes@477
   181
	    png_write_row(png_ptr, p);
nkeynes@477
   182
	    p+=buffer->rowstride;
nkeynes@477
   183
	}
nkeynes@477
   184
    }
nkeynes@477
   185
    png_write_end(png_ptr, info_ptr);
nkeynes@477
   186
    png_destroy_write_struct(&png_ptr, &info_ptr);
nkeynes@477
   187
    return TRUE;
nkeynes@477
   188
}
nkeynes@477
   189
nkeynes@477
   190
frame_buffer_t read_png_from_stream( FILE *f )
nkeynes@477
   191
{
nkeynes@477
   192
    png_bytep p;
nkeynes@477
   193
    int i;
nkeynes@477
   194
    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 
nkeynes@477
   195
						 NULL, NULL, NULL);
nkeynes@477
   196
    if (!png_ptr) {
nkeynes@477
   197
	return NULL;
nkeynes@477
   198
    }
nkeynes@477
   199
nkeynes@477
   200
    png_infop info_ptr = png_create_info_struct(png_ptr);
nkeynes@477
   201
    if (!info_ptr) {
nkeynes@477
   202
	png_destroy_read_struct(&png_ptr, NULL, NULL);
nkeynes@477
   203
	return NULL;
nkeynes@477
   204
    }
nkeynes@477
   205
    
nkeynes@477
   206
    png_infop end_info = png_create_info_struct(png_ptr);
nkeynes@477
   207
    if (!end_info) {
nkeynes@477
   208
	png_destroy_read_struct(&png_ptr, &info_ptr, NULL );
nkeynes@477
   209
	return NULL;
nkeynes@477
   210
    }
nkeynes@477
   211
nkeynes@477
   212
    if( setjmp(png_jmpbuf(png_ptr)) ) {
nkeynes@477
   213
	png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
nkeynes@477
   214
	return NULL;
nkeynes@477
   215
    }
nkeynes@477
   216
nkeynes@477
   217
    png_init_io(png_ptr, f);
nkeynes@477
   218
    png_read_info(png_ptr, info_ptr);
nkeynes@477
   219
    
nkeynes@477
   220
    png_uint_32 width, height;
nkeynes@477
   221
    int bit_depth, color_type, interlace_type,
nkeynes@477
   222
	compression_type, filter_method;
nkeynes@477
   223
    png_get_IHDR(png_ptr, info_ptr, &width, &height,
nkeynes@477
   224
		 &bit_depth, &color_type, &interlace_type,
nkeynes@477
   225
		 &compression_type, &filter_method);
nkeynes@477
   226
    assert( interlace_type == PNG_INTERLACE_NONE );
nkeynes@477
   227
    int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
nkeynes@477
   228
    int channels = png_get_channels(png_ptr, info_ptr);
nkeynes@477
   229
    frame_buffer_t buffer = g_malloc( sizeof(struct frame_buffer) + rowbytes*height );
nkeynes@477
   230
    buffer->data = (char *)(buffer+1);
nkeynes@477
   231
    buffer->width = width;
nkeynes@477
   232
    buffer->height = height;
nkeynes@477
   233
    buffer->rowstride = rowbytes;
nkeynes@477
   234
    buffer->address = -1;
nkeynes@477
   235
    buffer->size = rowbytes*height;
nkeynes@477
   236
    buffer->inverted = FALSE;
nkeynes@477
   237
    if( channels == 4 ) {
nkeynes@477
   238
	buffer->colour_format = COLFMT_BGRA8888;
nkeynes@477
   239
    } else if( channels == 3 ) {
nkeynes@477
   240
	buffer->colour_format = COLFMT_RGB888;
nkeynes@477
   241
    }
nkeynes@477
   242
    
nkeynes@477
   243
    p = buffer->data;
nkeynes@477
   244
    for( i=0; i<height; i++ ) {
nkeynes@477
   245
	png_read_row(png_ptr, p, NULL );
nkeynes@477
   246
	p += rowbytes;
nkeynes@477
   247
    }
nkeynes@477
   248
nkeynes@477
   249
    png_read_end(png_ptr, end_info);
nkeynes@477
   250
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
nkeynes@477
   251
    return buffer;
nkeynes@477
   252
}
nkeynes@437
   253
nkeynes@437
   254
void log_message( void *ptr, int level, const gchar *source, const char *msg, ... )
nkeynes@437
   255
{
nkeynes@437
   256
    char buf[20], addr[10] = "", *p;
nkeynes@437
   257
    const gchar *arr[4] = {buf, source, addr};
nkeynes@437
   258
    int posn;
nkeynes@437
   259
    time_t tm = time(NULL);
nkeynes@437
   260
    va_list ap;
nkeynes@437
   261
nkeynes@437
   262
    if( level > global_msg_level ) {
nkeynes@437
   263
	return; // ignored
nkeynes@437
   264
    }
nkeynes@447
   265
nkeynes@437
   266
    va_start(ap, msg);
nkeynes@437
   267
nkeynes@447
   268
    if( level <= EMIT_ERR ) {
nkeynes@447
   269
	gchar *text = g_strdup_vprintf( msg, ap );
nkeynes@447
   270
	if( gui_error_dialog( text ) ) {
nkeynes@447
   271
	    g_free(text);
nkeynes@447
   272
	    va_end(ap);
nkeynes@447
   273
	    return;
nkeynes@447
   274
	}
nkeynes@447
   275
	g_free(text);
nkeynes@447
   276
    }
nkeynes@447
   277
nkeynes@447
   278
nkeynes@437
   279
    strftime( buf, sizeof(buf), "%H:%M:%S", localtime(&tm) );
nkeynes@437
   280
    fprintf( stderr, "%s %08X %-5s ", buf, sh4r.pc, msg_levels[level] );
nkeynes@437
   281
    vfprintf( stderr, msg, ap );
nkeynes@447
   282
    va_end(ap);
nkeynes@437
   283
    fprintf( stderr, "\n" );
nkeynes@437
   284
}
.