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:
mudlord 2007-12-13 03:45:51 +00:00
parent 98079e809a
commit 4fff47a824
12 changed files with 590 additions and 466 deletions

View File

@ -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} \

View File

@ -28,7 +28,7 @@ File_Extractor* fex_open( const char* path, fex_err_t* err_out );
int fex_done( File_Extractor const* );
/* Name of current file. */
const char* fex_name( File_Extractor const* );
const char* fex_name( File_Extractor* );
/* Size of current file. */
long fex_size( File_Extractor const* );

View File

@ -150,7 +150,7 @@ void fex_set_user_cleanup ( File_Extractor* fe, fex_user_cleanup_t 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(); }
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 ); }

View File

@ -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)
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);
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;
}
else {
SDL_SemWait (sdlBufferLock);
memcpy (sdlBuffer + sdlSoundLen, soundFinalWave, soundBufferLen);
sdlSoundLen += soundBufferLen;
SDL_SemPost (sdlBufferLock);
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()

View File

@ -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)

View File

@ -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);

View File

@ -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();

View File

@ -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,7 +271,7 @@ bool OpenGLDisplay::initialize()
glEnable( GL_TEXTURE_2D );
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glewInit();
initializeMatrices( theApp.surfaceSizeX, theApp.surfaceSizeY );
@ -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,8 +429,26 @@ 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

View File

@ -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);

View File

@ -163,6 +163,7 @@ class VBA : public CWinApp
bool ddrawUseVideoMemory;
int d3dFilter;
int glFilter;
int GLSLShaders;
int glType;
bool dinputKeyFocus;
CSkin *skin;

View File

@ -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

View File

@ -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