- Fixed build

- Use the current desktop color depth instead of 16 BPP
- Fixed the OpenGL renderer when in 16 BPP color mode
- Changed the default filter to Stretch2x
- Fixed interframe blending
- A few optimizations
- We need fex.h and fex_mini.cpp for the SDL version, and using files from dependancies is not a option
This commit is contained in:
mudlord 2008-01-11 21:46:41 +00:00
parent a1a3766a19
commit f4091dfbf4
3 changed files with 423 additions and 76 deletions

140
src/fex.h Normal file
View File

@ -0,0 +1,140 @@
/* Compressed file archive C interface (also usable from C++) */
/* File_Extractor 0.4.3 */
#ifndef FEX_H
#define FEX_H
#ifdef __cplusplus
extern "C" {
#endif
/* Error string returned by library functions, or NULL if no error (success).
If function takes fex_err_t* err_out, it sets *err_out to NULL on success,
otherwise error string, or you can pass NULL if you don't care about exact
cause of error (these functions still report error by returning NULL). */
typedef const char* fex_err_t;
/* First parameter of most extractor_ functions is a pointer to the
File_Extractor being acted on. */
typedef struct File_Extractor File_Extractor;
/**** Basics ****/
/* Opens archive and returns pointer to it, or NULL if error. */
File_Extractor* fex_open( const char* path, fex_err_t* err_out );
/* True if at end of archive. */
int fex_done( File_Extractor const* );
/* Name of current file. */
const char* fex_name( File_Extractor* );
/* Size of current file. */
long fex_size( File_Extractor const* );
/* Extracts n bytes and writes them to *out. Returns error if all n
bytes couldn't be extracted (due to end of file or read error). */
fex_err_t fex_read( File_Extractor*, void* out, long n );
/* Goes to next file in archive (skips directories). */
fex_err_t fex_next( File_Extractor* );
/* Closes archive and frees memory. */
void fex_close( File_Extractor* );
/**** Advanced ****/
/* Goes back to first file in archive. */
fex_err_t fex_rewind( File_Extractor* );
/* Hints to fex_next() that no file extraction will occur, speeding scanning
of some archive types. */
void fex_scan_only( File_Extractor* );
/* Modification date of current file (MS-DOS format). */
unsigned long fex_dos_date( File_Extractor const* );
/* Number of bytes remaining to be read from current file. */
long fex_remain( File_Extractor const* );
/* Reads at most n bytes and returns number actually read, or negative if error. */
long fex_read_avail( File_Extractor*, void* out, long n );
/* Extracts first n bytes and ignores rest. Faster than a normal read since it
doesn't need to read any more data. Must not be called twice in a row. */
fex_err_t fex_read_once( File_Extractor*, void* out, long n );
/* Loads file data into memory (if not already) and returns pointer to it, or
NULL if error. Pointer is valid until fex_next(), fex_rewind(), or fex_close() are
called. Will return same pointer if called more than once. */
const unsigned char* fex_data( File_Extractor*, fex_err_t* err_out );
/**** Archive types ****/
/* fex_type_t is a pointer to this structure. For example, fex_zip_type->extension is
"ZIP" and ex_zip_type->new_fex() is equilvant to 'new Zip_Extractor' (in C++). */
struct fex_type_t_
{
const char* extension; /* file extension/type */
File_Extractor* (*new_fex)();
};
/* Archive type constants for each supported file type */
extern struct fex_type_t_ const
fex_7z_type [1], /* .7z (7-zip) */
fex_gz_type [1], /* .gz (gzip) */
/*fex_rar_type [1],*/ /* .rar */
fex_zip_type [1], /* .zip */
fex_bin_type [1]; /* binary file, possibly gzipped */
typedef struct fex_type_t_ const* fex_type_t;
/* Array of supported archive types, with NULL entry at end. */
fex_type_t const* fex_type_list();
/* Type of archive this extractor handles. */
fex_type_t fex_type( File_Extractor const* );
/******** Advanced opening ********/
/* Error returned if file is wrong type */
extern const char fex_wrong_file_type [29];
/* Determines likely archive type based on first four bytes of file. Returns string
containing proper file suffix (i.e. "ZIP", "GZ", etc.) or "" (empty string) if file
header is not recognized. */
const char* fex_identify_header( void const* header );
/* Gets corresponding archive type for file path or extension passed in. Returns NULL
if type isn't recognized. */
fex_type_t fex_identify_extension( const char* path_or_extension );
/* Determines file type based on filename extension, or file header (if extension
isn't recognized). Returns NULL if unrecognized or error. */
fex_type_t fex_identify_file( const char* path, fex_err_t* err_out );
/* Opens archive of specific type and returns pointer to it, or NULL if error. */
File_Extractor* fex_open_type( fex_type_t, const char* path, fex_err_t* err_out );
/******** User data ********/
/* Sets/gets pointer to data you want to associate with this extractor.
You can use this for whatever you want. */
void fex_set_user_data( File_Extractor*, void* new_user_data );
void* fex_user_data( File_Extractor const* );
/* Registers cleanup function to be called when closing extractor, or NULL to
clear it. Passes user_data (see above) to cleanup function. */
typedef void (*fex_user_cleanup_t)( void* user_data );
void fex_set_user_cleanup( File_Extractor*, fex_user_cleanup_t func );
#ifdef __cplusplus
}
#endif
#endif

222
src/fex_mini.cpp Normal file
View File

@ -0,0 +1,222 @@
// Minimal implementation of fex.h. Supports gzipped files if you have zlib
// available and HAVE_ZLIB_H is defined.
// File_Extractor 0.4.3. http://www.slack.net/~ant/
#include "fex.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* Copyright (C) 2007 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#ifndef HAVE_ZLIB_H
#define FILE_GZ( norm, gz ) norm
#define FILE_READ( ptr, size, file ) fread( ptr, 1, size, file )
#else
#define FILE_GZ( norm, gz ) gz
#define FILE_READ( ptr, size, file ) gzread( file, ptr, size )
#include "zlib.h"
static const char* get_gzip_size( const char* path, long* eof )
{
FILE* file = fopen( path, "rb" );
if ( !file )
return "Couldn't open file";
unsigned char buf [4];
if ( fread( buf, 2, 1, file ) > 0 && buf [0] == 0x1F && buf [1] == 0x8B )
{
fseek( file, -4, SEEK_END );
fread( buf, 4, 1, file );
*eof = buf [3] * 0x1000000 + buf [2] * 0x10000 + buf [1] * 0x100 + buf [0];
}
else
{
fseek( file, 0, SEEK_END );
*eof = ftell( file );
}
const char* err = (ferror( file ) || feof( file )) ? "Couldn't get file size" : 0;
fclose( file );
return err;
}
#endif
const char fex_wrong_file_type [] = "Archive format not supported";
struct File_Extractor
{
FILE_GZ(FILE*,gzFile) file;
int done;
long size;
void* data; // file data read into memory, ot 0 if not read
void* user_data;
fex_user_cleanup_t user_cleanup;
char* name() const { return (char*) (this + 1); }
};
// Always identify as single file extractor
fex_type_t_ const fex_bin_type [1] = {{ "" , 0 }};
const char* fex_identify_header ( void const* ) { return ""; }
fex_type_t fex_identify_extension( const char* ) { return fex_bin_type; }
fex_type_t fex_identify_file ( const char*, fex_err_t* e ) { if ( e ) *e = 0; return fex_bin_type; }
static fex_err_t fex_open_( const char* path, File_Extractor** fe_out )
{
*fe_out = 0;
// name
const char* name = strrchr( path, '\\' ); // DOS
if ( !name )
name = strrchr( path, '/' ); // UNIX
if ( !name )
name = strrchr( path, ':' ); // Mac
if ( !name )
name = path;
// allocate space for struct and name
long name_size = strlen( name ) + 1;
File_Extractor* fe = (File_Extractor*) malloc( sizeof (File_Extractor) + name_size );
if ( !fe ) return "Out of memory";
fe->done = 0;
fe->data = 0;
fe->user_data = 0;
fe->user_cleanup = 0;
memcpy( fe->name(), name, name_size );
#ifdef HAVE_ZLIB_H
// get gzip size BEFORE opening file
const char* err = get_gzip_size( path, &fe->size );
if ( err )
{
free( fe );
return err;
}
#endif
// open file
fe->file = FILE_GZ(fopen,gzopen)( path, "rb" );
if ( !fe->file )
{
free( fe );
return "Couldn't open file";
}
// get normal size
#ifndef HAVE_ZLIB_H
fseek( fe->file, 0, SEEK_END );
fe->size = ftell( fe->file );
rewind( fe->file );
#endif
*fe_out = fe;
return 0;
}
File_Extractor* fex_open( const char* path, fex_err_t* err_out )
{
File_Extractor* fe;
fex_err_t err = fex_open_( path, &fe );
if ( err_out )
*err_out = err;
return fe;
}
File_Extractor* fex_open_type( fex_type_t, const char* path, fex_err_t* err_out )
{
return fex_open( path, err_out );
}
void* fex_user_data ( File_Extractor const* fe ) { return fe->user_data; }
void fex_set_user_data ( File_Extractor* fe, void* new_user_data ) { fe->user_data = new_user_data; }
void fex_set_user_cleanup ( File_Extractor* fe, fex_user_cleanup_t func ) { fe->user_cleanup = func; }
fex_type_t fex_type ( File_Extractor const* ) { return fex_bin_type; }
int fex_done ( File_Extractor const* fe ) { return fe->done; }
const char* fex_name ( File_Extractor* fe ) { return fe->name(); }
unsigned long fex_dos_date ( File_Extractor const* ) { return 0; }
long fex_size ( File_Extractor const* fe ) { return fe->size; }
long fex_remain ( File_Extractor const* fe ) { return fe->size - FILE_GZ(ftell,gztell)( fe->file ); }
void fex_scan_only ( File_Extractor* ) { }
fex_err_t fex_read_once ( File_Extractor* fe, void* out, long count ) { return fex_read( fe, out, count ); }
long fex_read_avail ( File_Extractor* fe, void* out, long count ) { return FILE_READ( out, count, fe->file ); }
fex_err_t fex_read( File_Extractor* fe, void* out, long count )
{
if ( count == (long) FILE_READ( out, count, fe->file ) )
return 0;
if ( FILE_GZ(feof,gzeof)( fe->file ) )
return "Unexpected end of file";
return "Couldn't read from file";
}
fex_err_t fex_next( File_Extractor* fe )
{
fe->done = 1;
return 0;
}
fex_err_t fex_rewind( File_Extractor* fe )
{
fe->done = 0;
FILE_GZ(rewind,gzrewind)( fe->file );
return 0;
}
static fex_err_t fex_data_( File_Extractor* fe )
{
if ( !fe->data )
{
fe->data = malloc( fe->size );
if ( !fe->data ) return "Out of memory";
fex_err_t err = fex_read( fe, fe->data, fe->size );
if ( err )
{
free( fe->data );
return err;
}
}
return 0;
}
const unsigned char* fex_data( File_Extractor* fe, fex_err_t* err_out )
{
fex_err_t err = fex_data_( fe );
if ( err_out )
*err_out = err;
return (const unsigned char*) fe->data;
}
void fex_close( File_Extractor* fe )
{
if ( fe )
{
free( fe->data );
FILE_GZ(fclose,gzclose)( fe->file );
if ( fe->user_cleanup )
fe->user_cleanup( fe->user_data );
free( fe );
}
}

View File

@ -119,10 +119,10 @@ int destHeight = 0;
int sensorX = 2047;
int sensorY = 2047;
int filter = (int)kStretch1x;
int filter = (int)kStretch2x;
u8 *delta = NULL;
int filter_enlarge = 1;
int filter_enlarge = 2;
int sdlPrintUsage = 0;
int disableMMX = 0;
@ -1007,7 +1007,7 @@ void sdlInitVideo() {
} else
flags |= SDL_HWSURFACE | SDL_DOUBLEBUF;
surface = SDL_SetVideoMode(destWidth, destHeight, 16, flags);
surface = SDL_SetVideoMode(destWidth, destHeight, 0, flags);
if(surface == NULL) {
systemMessage(0, "Failed to set video mode");
@ -1290,7 +1290,7 @@ void sdlPollEvents()
case SDL_VIDEORESIZE:
if (openGL)
{
SDL_SetVideoMode(event.resize.w, event.resize.h, 16,
SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
SDL_OPENGL | SDL_RESIZABLE |
(fullscreen ? SDL_FULLSCREEN : 0));
sdlOpenGLInit(event.resize.w, event.resize.h);
@ -1790,7 +1790,7 @@ int main(int argc, char **argv)
exit(-1);
}
utilGetBaseName(szFile, filename);
utilStripDoubleExtension(szFile, filename);
char *p = strrchr(filename, '.');
if(p)
@ -1936,7 +1936,7 @@ int main(int argc, char **argv)
filterFunction = initFilter((Filter)filter, systemColorDepth, srcWidth);
if (!filterFunction) {
fprintf(stderr,"Unable to init filter\n");
fprintf(stderr,"Unable to init filter '%s'\n", getFilterName((Filter)filter));
exit(-1);
}
@ -2077,99 +2077,89 @@ void systemMessage(int num, const char *msg, ...)
va_end(valist);
}
void systemDrawScreen()
void drawScreenMessage(u8 *screen, int pitch, int x, int y, unsigned int duration)
{
renderedFrames++;
if(!openGL)
SDL_LockSurface(surface);
if(screenMessage) {
if(cartridgeType == 1 && gbBorderOn) {
gbSgbRenderBorder();
}
if(((systemGetClock() - screenMessageTime) < 3000) &&
if(((systemGetClock() - screenMessageTime) < duration) &&
!disableStatusMessages) {
drawText(pix, srcPitch, 10, srcHeight - 20,
drawText(screen, pitch, x, y,
screenMessageBuffer);
} else {
screenMessage = false;
}
}
}
if(ifbFunction) {
if(systemColorDepth == 16)
ifbFunction(pix+destWidth+4, destWidth+4, srcWidth, srcHeight);
else
ifbFunction(pix+destWidth*2+4, destWidth*2+4, srcWidth, srcHeight);
void drawSpeed(u8 *screen, int pitch, int x, int y)
{
char buffer[50];
if(showSpeed == 1)
sprintf(buffer, "%d%%", systemSpeed);
else
sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed,
systemFrameSkip,
showRenderedFrames);
if(showSpeedTransparent)
drawTextTransp(screen, pitch, x, y, buffer);
else
drawText(screen, pitch, x, y, buffer);
}
void systemDrawScreen()
{
unsigned int destPitch = destWidth * (systemColorDepth >> 3);
u8 *screen;
renderedFrames++;
if (openGL)
screen = filterPix;
else {
screen = (u8*)surface->pixels;
SDL_LockSurface(surface);
}
if (ifbFunction)
ifbFunction(pix + srcPitch, srcPitch, srcWidth, srcHeight);
filterFunction(pix + srcPitch, srcPitch, delta, screen,
destPitch, srcWidth, srcHeight);
drawScreenMessage(screen, destPitch, 10, destHeight - 20, 3000);
if (showSpeed && fullscreen)
drawSpeed(screen, destPitch, 10, 20);
if (openGL) {
int pitch = srcWidth * 4 + 4;
filterFunction(pix + pitch,
pitch,
delta,
(u8*)filterPix,
srcWidth * 4 * filter_enlarge,
srcWidth,
srcHeight);
glPixelStorei(GL_UNPACK_ROW_LENGTH, destWidth);
glPixelStorei(GL_UNPACK_ROW_LENGTH, destWidth);
if (systemColorDepth == 16)
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, destWidth, destHeight,
GL_BGRA, GL_UNSIGNED_BYTE, filterPix);
GL_RGB, GL_UNSIGNED_SHORT_5_6_5, screen);
else
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, destWidth, destHeight,
GL_BGRA, GL_UNSIGNED_BYTE, screen);
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(0.0f, 0.0f);
glVertex3i(0, 0, 0);
glTexCoord2f(filter_enlarge * srcWidth / (GLfloat) textureSize, 0.0f);
glTexCoord2f(destWidth / (GLfloat) textureSize, 0.0f);
glVertex3i(1, 0, 0);
glTexCoord2f(0.0f, filter_enlarge * srcHeight / (GLfloat) textureSize);
glTexCoord2f(0.0f, destHeight / (GLfloat) textureSize);
glVertex3i(0, 1, 0);
glTexCoord2f(filter_enlarge * srcWidth / (GLfloat) textureSize,
filter_enlarge * srcHeight / (GLfloat) textureSize);
glTexCoord2f(destWidth / (GLfloat) textureSize,
destHeight / (GLfloat) textureSize);
glVertex3i(1, 1, 0);
glEnd();
SDL_GL_SwapBuffers();
SDL_GL_SwapBuffers();
} else {
unsigned int destw = destWidth*((systemColorDepth == 16) ? 2 : 4) / filter_enlarge + 4;
filterFunction(pix+destw,
destw,
delta,
(u8*)surface->pixels,
surface->pitch,
srcWidth,
srcHeight);
if(showSpeed && fullscreen) {
char buffer[50];
if(showSpeed == 1)
sprintf(buffer, "%d%%", systemSpeed);
else
sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed,
systemFrameSkip,
showRenderedFrames);
if(showSpeedTransparent)
drawTextTransp((u8*)surface->pixels,
surface->pitch,
10,
surface->h-20,
buffer);
else
drawText((u8*)surface->pixels,
surface->pitch,
10,
surface->h-20,
buffer);
SDL_UnlockSurface(surface);
SDL_Flip(surface);
}
SDL_UnlockSurface(surface);
// SDL_UpdateRect(surface, 0, 0, destWidth, destHeight);
SDL_Flip(surface);
}
}
bool systemReadJoypads()
@ -2600,7 +2590,6 @@ void systemGbBorderOn()
(((i & 0x7c00) >> 10) << systemBlueShift);
}
}
srcPitch = srcWidth * 2+4;
} else {
RGB_LOW_BITS_MASK = 0x010101;
for(int i = 0; i < 0x10000; i++) {
@ -2608,9 +2597,5 @@ void systemGbBorderOn()
(((i & 0x3e0) >> 5) << systemGreenShift) |
(((i & 0x7c00) >> 10) << systemBlueShift);
}
if(systemColorDepth == 32)
srcPitch = srcWidth*4 + 4;
else
srcPitch = srcWidth*3;
}
}