Fixed sound thread issues in Subversion
Updated SDL port so that it now compiles with fex_mini.cpp Added custom GLSL shader support to Win32 OGL renderer (requires GLEW) Updated code in OpenGL renderer to be more tidy
This commit is contained in:
parent
98079e809a
commit
4fff47a824
4
Makefile
4
Makefile
|
@ -50,9 +50,9 @@ ${MAINDIR}/hq2x${OE} ${MAINDIR}/GBA-thumb${OE} ${MAINDIR}/GBA-arm${OE} ${MAINDIR
|
|||
${MAINDIR}/Mode1${OE} ${MAINDIR}/Mode2${OE} ${MAINDIR}/Mode3${OE} ${MAINDIR}/Mode4${OE} \
|
||||
${MAINDIR}/Mode5${OE} ${MAINDIR}/motionblur${OE} ${MAINDIR}/pixel${OE} ${MAINDIR}/portable${OE} \
|
||||
${MAINDIR}/remote${OE} ${MAINDIR}/RTC${OE} ${MAINDIR}/scanline${OE} ${MAINDIR}/simpleFilter${OE} \
|
||||
${MAINDIR}/snd_interp${OE} ${MAINDIR}/Sound${OE} ${MAINDIR}/Sram${OE} ${MAINDIR}/Text${OE} \
|
||||
${MAINDIR}/fex_mini${OE} ${MAINDIR}/Sound${OE} ${MAINDIR}/Sram${OE} ${MAINDIR}/Text${OE} \
|
||||
${MAINDIR}/unzip${OE} ${MAINDIR}/Util${OE} ${MAINDIR}/exprNode${OE} ${MAINDIR}/getopt${OE} \
|
||||
${MAINDIR}/getopt1${OE} ${MAINDIR}/memgzio${OE} ${MAINDIR}/expr-lex${OE} ${MAINDIR}/expr${OE}
|
||||
${MAINDIR}/getopt1${OE} ${MAINDIR}/memgzio${OE} ${MAINDIR}/expr-lex${OE} ${MAINDIR}/expr${OE} \
|
||||
|
||||
DMGOBJ=${DMGDIR}/GB${OE} ${DMGDIR}/gbCheats${OE} ${DMGDIR}/gbDis${OE} ${DMGDIR}/gbGfx${OE} \
|
||||
${DMGDIR}/gbGlobals${OE} ${DMGDIR}/gbMemory${OE} ${DMGDIR}/gbPrinter${OE} ${DMGDIR}/gbSGB${OE} \
|
||||
|
|
280
src/fex.h
280
src/fex.h
|
@ -1,140 +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 const* );
|
||||
|
||||
/* 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
|
||||
/* 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
|
||||
|
|
444
src/fex_mini.cpp
444
src/fex_mini.cpp
|
@ -1,222 +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() { 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 const* 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 );
|
||||
}
|
||||
}
|
||||
// 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() { 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 );
|
||||
}
|
||||
}
|
||||
|
|
187
src/sdl/SDL.cpp
187
src/sdl/SDL.cpp
|
@ -285,11 +285,32 @@ char screenMessageBuffer[21];
|
|||
u32 screenMessageTime = 0;
|
||||
|
||||
// Patch #1382692 by deathpudding.
|
||||
SDL_sem *sdlBufferLock = NULL;
|
||||
SDL_sem *sdlBufferFull = NULL;
|
||||
SDL_sem *sdlBufferEmpty = NULL;
|
||||
u8 sdlBuffer[4096];
|
||||
int sdlSoundLen = 0;
|
||||
const int sdlSoundSamples = 2048;
|
||||
const int sdlSoundAlign = 4;
|
||||
const int sdlSoundCapacity = sdlSoundSamples * 2;
|
||||
const int sdlSoundTotalLen = sdlSoundCapacity + sdlSoundAlign;
|
||||
static u8 sdlSoundBuffer[sdlSoundTotalLen];
|
||||
static int sdlSoundRPos;
|
||||
static int sdlSoundWPos;
|
||||
static SDL_cond *sdlSoundCond;
|
||||
static SDL_mutex *sdlSoundMutex;
|
||||
|
||||
static inline int soundBufferFree()
|
||||
{
|
||||
int ret = sdlSoundRPos - sdlSoundWPos - sdlSoundAlign;
|
||||
if (ret < 0)
|
||||
ret += sdlSoundTotalLen;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int soundBufferUsed()
|
||||
{
|
||||
int ret = sdlSoundWPos - sdlSoundRPos;
|
||||
if (ret < 0)
|
||||
ret += sdlSoundTotalLen;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
char *arg0;
|
||||
|
||||
|
@ -2078,6 +2099,8 @@ int main(int argc, char **argv)
|
|||
"FNO:T:Y:G:D:b:c:df:hi:p::s:t:v:1234",
|
||||
sdlOptions,
|
||||
NULL)) != -1) {
|
||||
if (optarg)
|
||||
optarg++;
|
||||
switch(op) {
|
||||
case 0:
|
||||
// long option already processed by getopt_long
|
||||
|
@ -3139,73 +3162,71 @@ void systemScreenCapture(int a)
|
|||
systemScreenMessage("Screen capture");
|
||||
}
|
||||
|
||||
void soundCallback(void *,u8 *stream,int len)
|
||||
static void soundCallback(void *,u8 *stream,int len)
|
||||
{
|
||||
if (!emulating)
|
||||
return;
|
||||
if (len <= 0 || !emulating)
|
||||
return;
|
||||
|
||||
// Patch #1382692 by deathpudding.
|
||||
/* since this is running in a different thread, speedup and
|
||||
* throttle can change at any time; save the value so locks
|
||||
* stay in sync */
|
||||
bool lock = (!speedup && !throttle) ? true : false;
|
||||
|
||||
if (lock)
|
||||
SDL_SemWait (sdlBufferFull);
|
||||
|
||||
SDL_SemWait (sdlBufferLock);
|
||||
memcpy (stream, sdlBuffer, len);
|
||||
sdlSoundLen = 0;
|
||||
SDL_SemPost (sdlBufferLock);
|
||||
|
||||
if (lock)
|
||||
SDL_SemPost (sdlBufferEmpty);
|
||||
SDL_mutexP(sdlSoundMutex);
|
||||
const int nAvail = soundBufferUsed();
|
||||
if (len > nAvail)
|
||||
len = nAvail;
|
||||
const int nAvail2 = ((sdlSoundTotalLen - sdlSoundRPos) + sdlSoundTotalLen) % sdlSoundTotalLen;
|
||||
if (len >= nAvail2) {
|
||||
memcpy(stream, &sdlSoundBuffer[sdlSoundRPos], nAvail2);
|
||||
sdlSoundRPos = 0;
|
||||
stream += nAvail2;
|
||||
len -= nAvail2;
|
||||
}
|
||||
if (len > 0) {
|
||||
memcpy(stream, &sdlSoundBuffer[sdlSoundRPos], len);
|
||||
sdlSoundRPos = (sdlSoundRPos + len) % sdlSoundTotalLen;
|
||||
stream += len;
|
||||
}
|
||||
SDL_CondSignal(sdlSoundCond);
|
||||
SDL_mutexV(sdlSoundMutex);
|
||||
}
|
||||
|
||||
void systemWriteDataToSoundBuffer()
|
||||
{
|
||||
// Patch #1382692 by deathpudding.
|
||||
if (SDL_GetAudioStatus () != SDL_AUDIO_PLAYING)
|
||||
SDL_PauseAudio (0);
|
||||
|
||||
if ((sdlSoundLen + soundBufferLen) >= 2048*2) {
|
||||
bool lock = (!speedup && !throttle) ? true : false;
|
||||
|
||||
if (lock)
|
||||
SDL_SemWait (sdlBufferEmpty);
|
||||
|
||||
SDL_SemWait (sdlBufferLock);
|
||||
int copied = 2048*2 - sdlSoundLen;
|
||||
memcpy (sdlBuffer + sdlSoundLen, soundFinalWave, copied);
|
||||
sdlSoundLen = 2048*2;
|
||||
SDL_SemPost (sdlBufferLock);
|
||||
|
||||
if (lock) {
|
||||
SDL_SemPost (sdlBufferFull);
|
||||
|
||||
/* wait for buffer to be dumped by soundCallback() */
|
||||
SDL_SemWait (sdlBufferEmpty);
|
||||
SDL_SemPost (sdlBufferEmpty);
|
||||
|
||||
SDL_SemWait (sdlBufferLock);
|
||||
memcpy (sdlBuffer, ((u8 *)soundFinalWave) + copied,
|
||||
soundBufferLen - copied);
|
||||
sdlSoundLen = soundBufferLen - copied;
|
||||
SDL_SemPost (sdlBufferLock);
|
||||
}
|
||||
else {
|
||||
SDL_SemWait (sdlBufferLock);
|
||||
memcpy (sdlBuffer, ((u8 *) soundFinalWave) + copied, soundBufferLen);
|
||||
SDL_SemPost (sdlBufferLock);
|
||||
}
|
||||
if (SDL_GetAudioStatus() != SDL_AUDIO_PLAYING)
|
||||
{
|
||||
SDL_PauseAudio(0);
|
||||
}
|
||||
else {
|
||||
SDL_SemWait (sdlBufferLock);
|
||||
memcpy (sdlBuffer + sdlSoundLen, soundFinalWave, soundBufferLen);
|
||||
sdlSoundLen += soundBufferLen;
|
||||
SDL_SemPost (sdlBufferLock);
|
||||
int remain = soundBufferLen;
|
||||
const u8 *wave = reinterpret_cast<const u8 *>(soundFinalWave);
|
||||
if (remain <= 0)
|
||||
return;
|
||||
SDL_mutexP(sdlSoundMutex);
|
||||
int n;
|
||||
while (remain >= (n = soundBufferFree())) {
|
||||
const int nAvail = ((sdlSoundTotalLen - sdlSoundWPos) + sdlSoundTotalLen) % sdlSoundTotalLen;
|
||||
if (n >= nAvail) {
|
||||
memcpy(&sdlSoundBuffer[sdlSoundWPos], wave, nAvail);
|
||||
sdlSoundWPos = 0;
|
||||
wave += nAvail;
|
||||
remain -= nAvail;
|
||||
n -= nAvail;
|
||||
}
|
||||
if (!emulating || speedup || throttle) {
|
||||
SDL_mutexV(sdlSoundMutex);
|
||||
return;
|
||||
}
|
||||
SDL_CondWait(sdlSoundCond, sdlSoundMutex);
|
||||
}
|
||||
const int nAvail = ((sdlSoundTotalLen - sdlSoundWPos) + sdlSoundTotalLen) % sdlSoundTotalLen;
|
||||
if (remain >= nAvail) {
|
||||
memcpy(&sdlSoundBuffer[sdlSoundWPos], wave, nAvail);
|
||||
sdlSoundWPos = 0;
|
||||
wave += nAvail;
|
||||
remain -= nAvail;
|
||||
}
|
||||
if (remain > 0) {
|
||||
memcpy(&sdlSoundBuffer[sdlSoundWPos], wave, remain);
|
||||
sdlSoundWPos = (sdlSoundWPos + remain) % sdlSoundTotalLen;
|
||||
}
|
||||
}
|
||||
SDL_mutexV(sdlSoundMutex);
|
||||
}
|
||||
|
||||
|
||||
bool systemSoundInit()
|
||||
{
|
||||
|
@ -3234,26 +3255,34 @@ bool systemSoundInit()
|
|||
fprintf(stderr,"Failed to open audio: %s\n", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
soundBufferTotalLen = soundBufferLen*10;
|
||||
// Patch #1382692 by deathpudding.
|
||||
sdlBufferLock = SDL_CreateSemaphore (1);
|
||||
sdlBufferFull = SDL_CreateSemaphore (0);
|
||||
sdlBufferEmpty = SDL_CreateSemaphore (1);
|
||||
sdlSoundLen = 0;
|
||||
|
||||
sdlSoundCond = SDL_CreateCond();
|
||||
sdlSoundMutex = SDL_CreateMutex();
|
||||
|
||||
sdlSoundRPos = sdlSoundWPos = 0;
|
||||
systemSoundOn = true;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
void systemSoundShutdown()
|
||||
{
|
||||
// Patch #1382692 by deathpudding.
|
||||
SDL_CloseAudio (); //TODO: fix freeze
|
||||
SDL_DestroySemaphore (sdlBufferLock);
|
||||
SDL_DestroySemaphore (sdlBufferFull);
|
||||
SDL_DestroySemaphore (sdlBufferEmpty);
|
||||
sdlBufferLock = NULL;
|
||||
sdlBufferFull = NULL;
|
||||
sdlBufferEmpty = NULL;
|
||||
SDL_mutexP(sdlSoundMutex);
|
||||
int iSave = emulating;
|
||||
emulating = 0;
|
||||
SDL_CondSignal(sdlSoundCond);
|
||||
SDL_mutexV(sdlSoundMutex);
|
||||
|
||||
SDL_DestroyCond(sdlSoundCond);
|
||||
sdlSoundCond = NULL;
|
||||
|
||||
SDL_DestroyMutex(sdlSoundMutex);
|
||||
sdlSoundMutex = NULL;
|
||||
|
||||
SDL_CloseAudio();
|
||||
|
||||
emulating = iSave;
|
||||
systemSoundOn = false;
|
||||
}
|
||||
|
||||
void systemSoundPause()
|
||||
|
|
|
@ -180,6 +180,8 @@ BEGIN_MESSAGE_MAP(MainWnd, CWnd)
|
|||
ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDEROPTIONS_GLQUADS, OnUpdateOptionsVideoRenderoptionsGlquads)
|
||||
ON_COMMAND(ID_OPTIONS_VIDEO_RENDEROPTIONS_GLPOLYGONS, OnOptionsVideoRenderoptionsGlpolygons)
|
||||
ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDEROPTIONS_GLPOLYGONS, OnUpdateOptionsVideoRenderoptionsGlpolygons)
|
||||
ON_COMMAND(ID_OPTIONS_VIDEO_RENDEROPTIONS_GLSLSHADERS, OnOptionsVideoRenderingoptionsGLSLShaders)
|
||||
ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDEROPTIONS_GLSLSHADERS, OnUpdateOptionsVideoRenderingoptionsGLSLShaders)
|
||||
|
||||
ON_WM_CONTEXTMENU()
|
||||
ON_COMMAND(ID_OPTIONS_EMULATOR_ASSOCIATE, OnOptionsEmulatorAssociate)
|
||||
|
|
|
@ -200,8 +200,8 @@ class MainWnd : public CWnd
|
|||
afx_msg void OnUpdateOptionsVideoRenderoptionsGlnearest(CCmdUI* pCmdUI);
|
||||
afx_msg void OnOptionsVideoRenderoptionsGlbilinear();
|
||||
afx_msg void OnUpdateOptionsVideoRenderoptionsGlbilinear(CCmdUI* pCmdUI);
|
||||
afx_msg void OnUpdateOptionsVideoRenderoptionsGlanisotropic(CCmdUI* pCmdUI);
|
||||
afx_msg void OnOptionsVideoRenderoptionsGlanisotropic();
|
||||
afx_msg void OnOptionsVideoRenderingoptionsGLSLShaders();
|
||||
afx_msg void OnUpdateOptionsVideoRenderingoptionsGLSLShaders(CCmdUI* pCmdUI);
|
||||
|
||||
afx_msg void OnOptionsVideoRenderoptionsGltriangle();
|
||||
afx_msg void OnUpdateOptionsVideoRenderoptionsGltriangle(CCmdUI* pCmdUI);
|
||||
|
|
|
@ -625,6 +625,19 @@ void MainWnd::OnUpdateOptionsVideoRenderoptionsGlpolygons(CCmdUI* pCmdUI)
|
|||
pCmdUI->SetCheck(theApp.glType == 2);
|
||||
}
|
||||
|
||||
void MainWnd::OnUpdateOptionsVideoRenderingoptionsGLSLShaders(CCmdUI* pCmdUI)
|
||||
{
|
||||
pCmdUI->SetCheck(theApp.GLSLShaders);
|
||||
}
|
||||
|
||||
void MainWnd::OnOptionsVideoRenderingoptionsGLSLShaders()
|
||||
{
|
||||
theApp.GLSLShaders = !theApp.GLSLShaders;
|
||||
if( theApp.GLSLShaders ) {
|
||||
theApp.display->setOption( _T("GLSLShaders"), theApp.GLSLShaders );
|
||||
}
|
||||
}
|
||||
|
||||
void MainWnd::OnOptionsEmulatorAssociate()
|
||||
{
|
||||
theApp.winCheckFullscreen();
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include <cmath>
|
||||
#include "glFont.h"
|
||||
|
||||
#pragma comment(lib,"glew32.lib")
|
||||
#include <GL/glew.h>
|
||||
// OpenGL
|
||||
#include <gl/GL.h> // main include file
|
||||
#ifdef HAS_GLEXT
|
||||
|
@ -68,6 +70,9 @@ private:
|
|||
RECT destRect;
|
||||
bool failed;
|
||||
GLFONT font;
|
||||
char *VertexShaderSource,*FragmentShaderSource;
|
||||
int VertexShader,FragmentShader;
|
||||
int ShaderProgram;
|
||||
|
||||
void initializeMatrices( int w, int h );
|
||||
bool initializeTexture( int w, int h );
|
||||
|
@ -75,6 +80,10 @@ private:
|
|||
void setVSync( int interval = 1 );
|
||||
void calculateDestRect( int w, int h );
|
||||
void initializeFont();
|
||||
void InitShader();
|
||||
void DeInitShader();
|
||||
void rasterise();
|
||||
|
||||
|
||||
public:
|
||||
OpenGLDisplay();
|
||||
|
@ -93,8 +102,10 @@ public:
|
|||
virtual int selectFullScreenMode( GUID ** );
|
||||
};
|
||||
|
||||
#include "gzglfont.h"
|
||||
|
||||
|
||||
#include "gzglfont.h"
|
||||
char *readShaderFile(char *FileName);
|
||||
void OpenGLDisplay::initializeFont()
|
||||
{
|
||||
int ret;
|
||||
|
@ -126,7 +137,61 @@ void OpenGLDisplay::initializeFont()
|
|||
(void)inflateEnd(&strm);
|
||||
}
|
||||
|
||||
char *readShaderFile(char *FileName) {
|
||||
FILE *fp;
|
||||
char *DATA = NULL;
|
||||
|
||||
int flength = 0;
|
||||
|
||||
fp = fopen(FileName,"rt");
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
flength = ftell(fp);
|
||||
rewind(fp);
|
||||
|
||||
DATA = (char *)malloc(sizeof(char) * (flength+1));
|
||||
flength = fread(DATA, sizeof(char), flength, fp);
|
||||
DATA[flength] = '\0';
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return DATA;
|
||||
}
|
||||
|
||||
void OpenGLDisplay::DeInitShader () {
|
||||
glDetachObjectARB(ShaderProgram,VertexShader);
|
||||
glDetachObjectARB(ShaderProgram,FragmentShader);
|
||||
glDeleteObjectARB(ShaderProgram);
|
||||
}
|
||||
|
||||
void OpenGLDisplay::InitShader () {
|
||||
GLEW_ARB_vertex_shader;
|
||||
GLEW_ARB_fragment_shader;
|
||||
|
||||
VertexShader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
|
||||
FragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
|
||||
|
||||
VertexShaderSource = readShaderFile("vertex_shader.vert");
|
||||
FragmentShaderSource = readShaderFile("fragment_shader.frag");
|
||||
|
||||
const char * VS = VertexShaderSource;
|
||||
const char * FS = FragmentShaderSource;
|
||||
|
||||
glShaderSourceARB(VertexShader, 1, &VS,NULL);
|
||||
glShaderSourceARB(FragmentShader, 1, &FS,NULL);
|
||||
|
||||
free(VertexShaderSource);free(FragmentShaderSource);
|
||||
|
||||
glCompileShaderARB(VertexShader);
|
||||
glCompileShaderARB(FragmentShader);
|
||||
|
||||
ShaderProgram = glCreateProgramObjectARB();
|
||||
|
||||
glAttachObjectARB(ShaderProgram,VertexShader);
|
||||
glAttachObjectARB(ShaderProgram,FragmentShader);
|
||||
|
||||
glLinkProgramARB(ShaderProgram);
|
||||
}
|
||||
|
||||
OpenGLDisplay::OpenGLDisplay()
|
||||
{
|
||||
|
@ -143,6 +208,7 @@ OpenGLDisplay::OpenGLDisplay()
|
|||
|
||||
OpenGLDisplay::~OpenGLDisplay()
|
||||
{
|
||||
DeInitShader();
|
||||
cleanup();
|
||||
}
|
||||
|
||||
|
@ -205,8 +271,8 @@ bool OpenGLDisplay::initialize()
|
|||
glEnable( GL_TEXTURE_2D );
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
|
||||
glewInit();
|
||||
|
||||
initializeMatrices( theApp.surfaceSizeX, theApp.surfaceSizeY );
|
||||
|
||||
setVSync( theApp.vsync );
|
||||
|
@ -243,12 +309,8 @@ void OpenGLDisplay::clear()
|
|||
glClear( GL_COLOR_BUFFER_BIT );
|
||||
}
|
||||
|
||||
|
||||
void OpenGLDisplay::render()
|
||||
void OpenGLDisplay::rasterise()
|
||||
{
|
||||
clear();
|
||||
|
||||
|
||||
int pitch = theApp.filterWidth * (systemColorDepth>>3) + 4;
|
||||
u8 *data = pix + ( theApp.sizeX + 1 ) * 4;
|
||||
|
||||
|
@ -273,17 +335,7 @@ void OpenGLDisplay::render()
|
|||
} else {
|
||||
glPixelStorei( GL_UNPACK_ROW_LENGTH, theApp.sizeX + 1 );
|
||||
}
|
||||
|
||||
glTexSubImage2D(
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
width,
|
||||
height,
|
||||
GL_RGBA,
|
||||
GL_UNSIGNED_BYTE,
|
||||
data );
|
||||
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,width,height,GL_RGBA,GL_UNSIGNED_BYTE,data );
|
||||
|
||||
if( theApp.glType == 0 ) {
|
||||
glBegin( GL_TRIANGLE_STRIP );
|
||||
|
@ -377,12 +429,30 @@ void OpenGLDisplay::render()
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void OpenGLDisplay::render()
|
||||
{
|
||||
clear();
|
||||
if (theApp.GLSLShaders){
|
||||
InitShader();
|
||||
glUseProgramObjectARB(ShaderProgram);
|
||||
int texture_location = glGetUniformLocationARB(ShaderProgram, "ShaderTexture");
|
||||
glUniform1iARB(texture_location, 0);
|
||||
}
|
||||
else{
|
||||
glUseProgramObjectARB(NULL);
|
||||
DeInitShader();
|
||||
}
|
||||
rasterise();
|
||||
|
||||
glFlush();
|
||||
|
||||
|
||||
SwapBuffers( hDC );
|
||||
// since OpenGL draws on the back buffer,
|
||||
// we have to swap it to the front buffer to see it
|
||||
|
||||
|
||||
// draw informations with GDI on the front buffer
|
||||
}
|
||||
|
||||
|
|
|
@ -288,6 +288,7 @@ VBA::VBA()
|
|||
ddrawUseVideoMemory = false;
|
||||
d3dFilter = 0;
|
||||
glFilter = 0;
|
||||
GLSLShaders = 0;
|
||||
glType = 0;
|
||||
skin = NULL;
|
||||
skinName = "";
|
||||
|
@ -1489,6 +1490,10 @@ void VBA::loadSettings()
|
|||
if(glFilter < 0 || glFilter > 1)
|
||||
glFilter = 1;
|
||||
|
||||
GLSLShaders = regQueryDwordValue("GLSLShaders", 0);
|
||||
if(GLSLShaders < 0 || GLSLShaders > 1)
|
||||
GLSLShaders = 0;
|
||||
|
||||
glType = regQueryDwordValue("glType", 0);
|
||||
if(glType < 0 || glType > 2)
|
||||
glType = 0;
|
||||
|
@ -2571,6 +2576,7 @@ void VBA::saveSettings()
|
|||
|
||||
regSetDwordValue("d3dFilter", d3dFilter);
|
||||
regSetDwordValue("glFilter", glFilter);
|
||||
regSetDwordValue("GLSLShaders", GLSLShaders);
|
||||
regSetDwordValue("glType", glType);
|
||||
|
||||
regSetDwordValue("filter", filterType);
|
||||
|
|
|
@ -163,6 +163,7 @@ class VBA : public CWinApp
|
|||
bool ddrawUseVideoMemory;
|
||||
int d3dFilter;
|
||||
int glFilter;
|
||||
int GLSLShaders;
|
||||
int glType;
|
||||
bool dinputKeyFocus;
|
||||
CSkin *skin;
|
||||
|
|
|
@ -1595,6 +1595,7 @@ BEGIN
|
|||
MENUITEM " Vertex: Triangle", ID_OPTIONS_VIDEO_RENDEROPTIONS_GLTRIANGLE
|
||||
MENUITEM " Vertex: Quads", ID_OPTIONS_VIDEO_RENDEROPTIONS_GLQUADS
|
||||
MENUITEM " Vertex: Polygons", ID_OPTIONS_VIDEO_RENDEROPTIONS_GLPOLYGONS
|
||||
MENUITEM " GLSL Shaders", ID_OPTIONS_VIDEO_RENDEROPTIONS_GLSLSHADERS
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "&VSync", ID_OPTIONS_VIDEO_VSYNC
|
||||
MENUITEM "Triple Buffering", ID_OPTIONS_VIDEO_TRIPLEBUFFERING
|
||||
|
|
|
@ -813,13 +813,15 @@
|
|||
#define ID_OUTPUTAPI_SOFTWAREMIXING 40348
|
||||
#define ID_OUTPUTAPI_CONFIGURATION 40349
|
||||
#define ID_OUTPUTAPI_OALCONFIGURATION 40350
|
||||
#define ID_RENDERAPI_FILTER 40351
|
||||
#define ID_OPTIONS_VIDEO_RENDEROPTIONS_GLSLSHADERS 40352
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 161
|
||||
#define _APS_NEXT_COMMAND_VALUE 40351
|
||||
#define _APS_NEXT_COMMAND_VALUE 40353
|
||||
#define _APS_NEXT_CONTROL_VALUE 1270
|
||||
#define _APS_NEXT_SYMED_VALUE 103
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue