saturn: connect the openGL rendering core. has some graphical glitches of its own, but can be a good deal faster than the soft core. not hooked up in options yet (so without code editing, you'll get soft core every time)

This commit is contained in:
goyuken 2013-05-13 16:49:02 +00:00
parent 52161e9cc0
commit 656e7a3862
9 changed files with 260 additions and 33 deletions

View File

@ -134,14 +134,23 @@ namespace BizHawk.Emulation.Consoles.Sega.Saturn
}
}
/// <summary>
/// only works in GL mode
/// </summary>
/// <param name="w">width</param>
/// <param name="h">height</param>
[DllImport("libyabause.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void libyabause_glresize(int w, int h);
/// <summary>
///
/// </summary>
/// <param name="intf">cd interface. struct need not persist after call, but the function pointers better</param>
/// <param name="biosfn">path to bios, pass null to use built in bios emulation</param>
/// <param name="usegl">true for opengl</param>
/// <returns></returns>
[DllImport("libyabause.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool libyabause_init(ref CDInterface intf, string biosfn);
public static extern bool libyabause_init(ref CDInterface intf, string biosfn, bool usegl);
public struct CDInterface
{

View File

@ -66,7 +66,7 @@ namespace BizHawk.Emulation.Consoles.Sega.Saturn
string BiosPipe = fp.GetPipeNameNative();
fp.Offer(bios);
if (!LibYabause.libyabause_init(ref CDInt, BiosPipe))
if (!LibYabause.libyabause_init(ref CDInt, BiosPipe, false))
throw new Exception("libyabause_init() failed!");
var e = fp.GetResults();
@ -77,6 +77,7 @@ namespace BizHawk.Emulation.Consoles.Sega.Saturn
LibYabause.libyabause_setsndbuff(SoundHandle.AddrOfPinnedObject());
AttachedCore = this;
// with or without GL, this is the guaranteed frame -1 size.
BufferWidth = 320;
BufferHeight = 224;

View File

@ -49,12 +49,13 @@
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBYABAUSE_EXPORTS;HAVE_C99_VARIADIC_MACROS;VERSION="LIB";C68K_NO_JUMP_TABLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBYABAUSE_EXPORTS;HAVE_C99_VARIADIC_MACROS;VERSION="LIB";C68K_NO_JUMP_TABLE;HAVE_LIBGL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4244;4996;4018;4146</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -65,7 +66,7 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBYABAUSE_EXPORTS;HAVE_C99_VARIADIC_MACROS;VERSION="LIB";C68K_NO_JUMP_TABLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBYABAUSE_EXPORTS;HAVE_C99_VARIADIC_MACROS;VERSION="LIB";C68K_NO_JUMP_TABLE;HAVE_LIBGL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4244;4996;4018;4146</DisableSpecificWarnings>
</ClCompile>
<Link>
@ -73,6 +74,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>

View File

@ -1,5 +1,7 @@
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <gl/GL.h>
#include "../windows/glext.h"
extern "C" {
#include "../cs0.h"
@ -9,6 +11,7 @@ extern "C" {
#include "../vdp2.h"
#include "../yui.h"
#include "../movie.h"
#include "../vidogl.h"
}
CDInterface FECD =
@ -52,6 +55,7 @@ NULL
extern "C" VideoInterface_struct *VIDCoreList[] = {
&VIDDummy,
&VIDOGL,
&VIDSoft,
NULL
};
@ -71,37 +75,191 @@ void YuiErrorMsg(const char *string)
MessageBoxA(NULL, string, "Yabooze dun goofed", 0);
}
int red_size;
int green_size;
int blue_size;
int depth_size;
PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;
PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers;
PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers;
PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage;
PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
int LoadExtensions()
{
glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)wglGetProcAddress("glBindRenderbufferEXT");
if( glBindRenderbuffer == NULL ) return 0;
glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)wglGetProcAddress("glDeleteRenderbuffersEXT");
if(glDeleteRenderbuffers==NULL) return 0;
glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)wglGetProcAddress("glGenRenderbuffersEXT");
if( glGenRenderbuffers == NULL ) return 0;
glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)wglGetProcAddress("glRenderbufferStorageEXT");
if( glRenderbufferStorage == NULL ) return 0;
glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)wglGetProcAddress("glBindFramebufferEXT");
if( glBindFramebuffer==NULL) return 0;
glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)wglGetProcAddress("glDeleteFramebuffersEXT");
if( glDeleteFramebuffers==NULL) return 0;
glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)wglGetProcAddress("glGenFramebuffersEXT");
if( glGenFramebuffers == NULL ) return 0;
glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)wglGetProcAddress("glCheckFramebufferStatusEXT");
if( glCheckFramebufferStatus == NULL ) return 0;
glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)wglGetProcAddress("glFramebufferRenderbufferEXT");
if( glFramebufferRenderbuffer == NULL ) return 0;
return 1;
}
/* Sets attribute for the Video display. The values passed to this function
depends on what Video core is being used at the time. This may end up
being moved to the Video Core. */
void YuiSetVideoAttribute(int type, int val)
{
// only called in GL mode?
// only called in GL mode
switch (type)
{
case RED_SIZE:
red_size = val;
break;
case GREEN_SIZE:
green_size = val;
break;
case BLUE_SIZE:
blue_size = val;
break;
case DEPTH_SIZE:
depth_size = val;
break;
case DOUBLEBUFFER:
break;
}
}
GLuint fbuff = 0;
GLuint color = 0;
GLuint depth = 0;
int glwidth, glheight;
u8 *glbuff = NULL;
/* Tells the yui it wants to setup the display to display the specified video
format. It's up to the yui to setup the actual display. This may end
up being moved to the Video Core. */
int YuiSetVideoMode(int width, int height, int bpp, int fullscreen)
{
// only called in GL mode?
// return -1; // failure
// only called in GL mode
if (bpp != 32 || red_size != 8 || green_size != 8 || blue_size != 8 || depth_size != 24)
return -1; // failure
if (fbuff)
glDeleteFramebuffers(1, &fbuff);
if (color)
glDeleteRenderbuffers(1, &color);
if (depth)
glDeleteRenderbuffers(1, &depth);
glGenFramebuffers(1, &fbuff);
glGenRenderbuffers(1, &color);
glGenRenderbuffers(1, &depth);
glBindFramebuffer(GL_FRAMEBUFFER, fbuff);
glBindRenderbuffer(GL_RENDERBUFFER, depth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
glBindRenderbuffer(GL_RENDERBUFFER, color);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8, width, height);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color);
//glBindRenderbuffer(GL_RENDERBUFFER, 0);
if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
return -1;
glwidth = width;
glheight = height;
if (glbuff)
free(glbuff);
glbuff = (u8*) malloc(glwidth * glheight * 4);
return 0; // success
}
int usinggl = 0;
HWND glWND;
HDC glDC;
HGLRC glRC;
void KillGLContext()
{
wglMakeCurrent(NULL, NULL);
wglDeleteContext(glRC);
ReleaseDC(glWND, glDC);
DestroyWindow(glWND);
}
int StartGLContext()
{
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd,0, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_SUPPORT_OPENGL;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cAlphaBits = 8;
pfd.cDepthBits = 24;
pfd.cStencilBits = 8;
pfd.iLayerType = PFD_MAIN_PLANE;
glWND = CreateWindow(L"EDIT", 0, 0, 0, 0, 512, 512, 0, 0, 0, 0);
if (!glWND)
return 0;
glDC = GetDC(glWND);
if (!glDC)
{
DestroyWindow(glWND);
return 0;
}
int PixelFormat = ChoosePixelFormat(glDC, &pfd);
if (!PixelFormat)
{
ReleaseDC(glWND, glDC);
DestroyWindow(glWND);
return 0;
}
if (!SetPixelFormat(glDC, PixelFormat, &pfd))
{
ReleaseDC(glWND, glDC);
DestroyWindow(glWND);
return 0;
}
glRC = wglCreateContext(glDC);
if (!glRC)
{
ReleaseDC(glWND, glDC);
DestroyWindow(glWND);
return 0;
}
if (!wglMakeCurrent(glDC, glRC))
{
wglDeleteContext(glRC);
ReleaseDC(glWND, glDC);
DestroyWindow(glWND);
return 0;
}
return 1;
}
s16 *sndbuff = NULL;
int sndbuffpos = 0;
@ -119,19 +277,38 @@ void YuiSwapBuffers(void)
{
if (vidbuff)
{
u8 *src = (u8*)dispbuffer;
u8 *dst = (u8*)vidbuff;
if (!usinggl)
{
u8 *src = (u8*)dispbuffer;
u8 *dst = (u8*)vidbuff;
for (int j = 0; j < vdp2height; j++)
for (int i = 0; i < vdp2width; i++)
for (int j = 0; j < vdp2height; j++)
for (int i = 0; i < vdp2width; i++)
{
dst[0] = src[2];
dst[1] = src[1];
dst[2] = src[0];
dst[3] = 0xff;
src += 4;
dst += 4;
}
}
else
{
glReadPixels(0, 0, glwidth, glheight, GL_BGRA, GL_UNSIGNED_BYTE, glbuff);
u32 *src = (u32*)glbuff;
u32 *dst = (u32*)vidbuff;
dst += glwidth * (glheight - 1);
for (int j = 0; j < glheight; j++)
{
dst[0] = src[2];
dst[1] = src[1];
dst[2] = src[0];
dst[3] = 0xff;
src += 4;
dst += 4;
}
memcpy(dst, src, glwidth * 4);
src += glwidth;
dst -= glwidth;
}
}
}
}
@ -252,8 +429,16 @@ extern "C" __declspec(dllexport) int libyabause_frameadvance(int *w, int *h, int
LagFrameFlag = 1;
sndbuffpos = 0;
YabauseEmulate();
*w = vdp2width;
*h = vdp2height;
if (usinggl)
{
*w = glwidth;
*h = glheight;
}
else
{
*w = vdp2width;
*h = vdp2height;
}
*nsamp = sndbuffpos;
return LagFrameFlag;
}
@ -262,6 +447,16 @@ extern "C" __declspec(dllexport) void libyabause_deinit()
{
PerPortReset();
YabauseDeInit();
if (usinggl)
{
KillGLContext();
usinggl = 0;
}
if (glbuff)
{
free(glbuff);
glbuff = NULL;
}
}
extern "C" __declspec(dllexport) void libyabause_setpads(u8 p11, u8 p12, u8 p21, u8 p22)
@ -272,8 +467,18 @@ extern "C" __declspec(dllexport) void libyabause_setpads(u8 p11, u8 p12, u8 p21,
ctrl2->padbits[1] = p22;
}
extern "C" __declspec(dllexport) int libyabause_init(CDInterface *_CD, const char *biosfn)
extern "C" __declspec(dllexport) void libyabause_glresize(int w, int h)
{
if (usinggl)
VIDCore->Resize(w, h, 0);
}
extern "C" __declspec(dllexport) int libyabause_init(CDInterface *_CD, const char *biosfn, int usegl)
{
usinggl = usegl;
if (usegl && (!StartGLContext() || !LoadExtensions()))
return 0;
FECD.DeInit = _CD->DeInit;
FECD.GetStatus = _CD->GetStatus;
FECD.Init = _CD->Init;
@ -292,7 +497,10 @@ extern "C" __declspec(dllexport) int libyabause_init(CDInterface *_CD, const cha
memset(&yinit, 0, sizeof(yabauseinit_struct));
yinit.percoretype = PERCORE_DUMMY;
yinit.sh2coretype = SH2CORE_INTERPRETER;
yinit.vidcoretype = VIDCORE_SOFT;
if (usegl)
yinit.vidcoretype = VIDCORE_OGL;
else
yinit.vidcoretype = VIDCORE_SOFT;
yinit.sndcoretype = 2; //SNDCORE_DUMMY;
yinit.cdcoretype = 2; // CDCORE_ISO; //CDCORE_DUMMY;
yinit.m68kcoretype = M68KCORE_C68K;

View File

@ -1305,6 +1305,7 @@ int YabLoadState(const char *filename)
//YabauseChangeTiming(yabsys.CurSH2FreqType);
//yabsys.UsecFrac = (temp32 << YABSYS_TIMING_BITS) * temp / 10;
/*
if (headerversion > 1) {
yread(&check, (void *)&outputwidth, sizeof(outputwidth), 1, fp);
@ -1338,7 +1339,7 @@ int YabLoadState(const char *filename)
fseek(fp, movieposition, SEEK_SET);
MovieReadState(fp, filename);
}
*/
fclose(fp);
ScspUnMuteAudio(SCSP_MUTE_SYSTEM);

View File

@ -2176,6 +2176,8 @@ static void SetSaturnResolution(int width, int height)
int VIDOGLInit(void)
{
GlWidth = 320;
GlHeight = 224;
if (YglInit(2048, 1024, 8) != 0)
return -1;

View File

@ -158,7 +158,7 @@ static int nbg1priority=0;
static int nbg2priority=0;
static int nbg3priority=0;
static int rbg0priority=0;
#ifdef USE_OPENGL
#if 0 //def USE_OPENGL
static int outputwidth;
static int outputheight;
#endif
@ -1659,7 +1659,7 @@ int VIDSoftInit(void)
vdp2width = 320;
vdp2height = 224;
#ifdef USE_OPENGL
#if 0 //def USE_OPENGL
YuiSetVideoAttribute(DOUBLEBUFFER, 1);
if (!YglScreenInit(8, 8, 8, 24))
@ -1714,7 +1714,7 @@ static int IsFullscreen = 0;
void VIDSoftResize(unsigned int w, unsigned int h, int on)
{
#ifdef USE_OPENGL
#if 0 //def USE_OPENGL
IsFullscreen = on;
if (on)
@ -3017,8 +3017,8 @@ void VIDSoftVdp2DrawEnd(void)
if (OSDUseBuffer())
OSDDisplayMessages(dispbuffer, vdp2width, vdp2height);
#ifdef USE_OPENGL
#if 0 // def USE_OPENGL
glRasterPos2i(0, 0);
glPixelZoom((float)outputwidth / (float)vdp2width, 0 - ((float)outputheight / (float)vdp2height));
glDrawPixels(vdp2width, vdp2height, GL_RGBA, GL_UNSIGNED_BYTE, dispbuffer);
@ -3259,7 +3259,7 @@ void VIDSoftVdp1EraseFrameBuffer(void)
void VIDSoftGetGlSize(int *width, int *height)
{
#ifdef USE_OPENGL
#if 0 // def USE_OPENGL
*width = outputwidth;
*height = outputheight;
#else

View File

@ -56,7 +56,7 @@ extern int vdp1cor;
extern int vdp1cog;
extern int vdp1cob;
GLuint DefaultFrameBuffer;
#ifdef HAVE_GLXGETPROCADDRESS
void STDCALL * (*yglGetProcAddress)(const char *szProcName) = (void STDCALL *(*)(const char *))glXGetProcAddress;
@ -467,6 +467,8 @@ void YglTMAllocate(YglTexture * output, unsigned int w, unsigned int h, unsigned
int YglGLInit(int width, int height) {
int status;
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &DefaultFrameBuffer);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
@ -558,7 +560,7 @@ int YglGLInit(int width, int height) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindFramebuffer(GL_FRAMEBUFFER, 0 );
glBindFramebuffer(GL_FRAMEBUFFER, DefaultFrameBuffer);
glBindTexture(GL_TEXTURE_2D,_Ygl->texture);
return 0;
@ -635,6 +637,8 @@ int YglInit(int width, int height, unsigned int depth) {
}
YglGLInit(width, height);
glViewport(0, 0, GlWidth, GlHeight);
YglNeedToUpdateWindow();
// Set up Extention
/* would be much better to test the opengl api */
@ -768,7 +772,7 @@ int YglInit(int width, int height, unsigned int depth) {
return -1;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0 );
glBindFramebuffer(GL_FRAMEBUFFER, DefaultFrameBuffer);
_Ygl->st = 0;
_Ygl->msglength = 0;
@ -1473,7 +1477,7 @@ void YglRenderVDP1(void) {
_Ygl->drawframe=(_Ygl->drawframe^0x01)&0x01;
// glFlush(); need??
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER, DefaultFrameBuffer);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);