#define HEADLESS
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <gl/GL.h>
#include "../windows/glext.h"
extern "C" {
#include "../cs0.h"
#include "../m68kcore.h"
#include "../peripheral.h"
#include "../vidsoft.h"
#include "../vdp2.h"
#include "../yui.h"
#include "../movie.h"
#include "../vidogl.h"
}
void (*inputcallback)(void) = NULL;
extern "C" __declspec(dllexport) void libyabause_setinputcallback(void (*cb)(void))
{
inputcallback = cb;
}
void (*tracecallback)(const char* dis, const char* regs) = NULL;
extern "C" __declspec(dllexport) void libyabause_settracecallback(void (*cb)(const char* dis, const char* regs))
{
tracecallback = cb;
}
CDInterface FECD =
{
2,
"FECD",
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
};
SoundInterface_struct FESND;
extern "C" SH2Interface_struct *SH2CoreList[] = {
&SH2Interpreter,
&SH2DebugInterpreter,
NULL
};
extern "C" PerInterface_struct *PERCoreList[] = {
&PERDummy,
NULL
};
extern "C" CDInterface *CDCoreList[] = {
&DummyCD,
&ISOCD,
&FECD,
NULL
};
extern "C" SoundInterface_struct *SNDCoreList[] = {
&SNDDummy,
&FESND,
NULL
};
extern "C" VideoInterface_struct *VIDCoreList[] = {
&VIDDummy,
&VIDOGL,
&VIDSoft,
NULL
};
extern "C" M68K_struct *M68KCoreList[] = {
&M68KDummy,
&M68KC68K,
#ifdef HAVE_Q68
&M68KQ68,
#endif
NULL
};
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;
}
void YuiSetVideoAttribute(int type, int val)
{
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;
int YuiSetVideoMode(int width, int height, int bpp, int fullscreen)
{
if (bpp != 32 || red_size != 8 || green_size != 8 || blue_size != 8 || depth_size != 24)
return -1;
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);
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;
}
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;
u32 *vidbuff = NULL;
PerPad_struct *ctrl1;
PerPad_struct *ctrl2;
extern "C" int vdp2height;
extern "C" int vdp2width;
extern "C" GLuint FboTexture;
void YuiSwapBuffers(void)
{
if (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++)
{
dst[0] = src[2];
dst[1] = src[1];
dst[2] = src[0];
dst[3] = 0xff;
src += 4;
dst += 4;
}
}
else
{
#ifdef CAN_RETURN_TEXTURE_IDS
memcpy(vidbuff,&FboTexture,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++)
{
memcpy(dst, src, glwidth * 4);
src += glwidth;
dst -= glwidth;
}
#endif
}
}
}
static void FESNDUpdateAudio(UNUSED u32 *leftchanbuffer, UNUSED u32 *rightchanbuffer, UNUSED u32 num_samples)
{
}
static u32 FESNDGetAudioSpace(void)
{
return 44100;
}
extern "C" void DRV_AviSoundUpdate(void* soundData, int soundLen)
{
if (sndbuff)
{
s16 *src = (s16*)soundData;
s16 *dst = sndbuff;
dst += sndbuffpos * 2;
memcpy (dst, src, soundLen * 4);
sndbuffpos += soundLen;
}
}
extern "C" __declspec(dllexport) void libyabause_setvidbuff(u32 *buff)
{
vidbuff = buff;
}
extern "C" __declspec(dllexport) void libyabause_setsndbuff(s16 *buff)
{
sndbuff = buff;
}
extern "C" __declspec(dllexport) void libyabause_softreset()
{
YabauseResetButton();
}
extern "C" __declspec(dllexport) void libyabause_hardreset()
{
YabauseReset();
}
extern "C" __declspec(dllexport) int libyabause_loadstate(const char *fn)
{
return !YabLoadState(fn);
}
extern "C" __declspec(dllexport) int libyabause_savestate(const char *fn)
{
return !YabSaveState(fn);
}
extern "C" __declspec(dllexport) int libyabause_savesaveram(const char *fn)
{
return !T123Save(BupRam, 0x10000, 1, fn);
}
extern "C" __declspec(dllexport) int libyabause_loadsaveram(const char *fn)
{
return !T123Load(BupRam, 0x10000, 1, fn);
}
extern "C" __declspec(dllexport) int libyabause_saveramodified()
{
return BupRamWritten;
}
extern "C" __declspec(dllexport) void libyabause_clearsaveram()
{
FormatBackupRam(BupRam, 0x10000);
}
typedef struct
{
void *data;
const char *name;
int length;
} memoryarea;
memoryarea normmemareas[] =
{
{NULL, "Boot Rom", 512 * 1024},
{NULL, "Backup Ram", 64 * 1024},
{NULL, "Work Ram Low", 1024 * 1024},
{NULL, "Sound Ram", 512 * 1024},
{NULL, "VDP1 Ram", 512 * 1024},
{NULL, "VDP1 Framebuffer", 512 * 1024},
{NULL, "VDP2 Ram", 512 * 1024},
{NULL, "VDP2 CRam", 4 * 1024},
{NULL, "Work Ram High", 1024 * 1024},
{NULL, NULL, 0}
};
extern "C" __declspec(dllexport) memoryarea *libyabause_getmemoryareas()
{
normmemareas[0].data = BiosRom;
normmemareas[1].data = BupRam;
normmemareas[2].data = LowWram;
normmemareas[3].data = SoundRam;
normmemareas[4].data = Vdp1Ram;
normmemareas[5].data = Vdp1FrameBuffer;
normmemareas[6].data = Vdp2Ram;
normmemareas[7].data = Vdp2ColorRam;
normmemareas[8].data = HighWram;
return &normmemareas[0];
}
extern "C" __declspec(dllexport) int libyabause_frameadvance(int *w, int *h, int *nsamp)
{
LagFrameFlag = 1;
sndbuffpos = 0;
YabauseEmulate();
if (usinggl)
{
*w = glwidth;
*h = glheight;
}
else
{
*w = vdp2width;
*h = vdp2height;
}
*nsamp = sndbuffpos;
return LagFrameFlag;
}
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)
{
ctrl1->padbits[0] = p11;
ctrl1->padbits[1] = p12;
ctrl2->padbits[0] = p21;
ctrl2->padbits[1] = p22;
}
int glnativefactor = 0;
extern "C" __declspec(dllexport) void libyabause_glresize(int w, int h)
{
if (usinggl && !glnativefactor)
VIDCore->Resize(w, h, 0);
}
extern "C" __declspec(dllexport) void libyabause_glsetnativefactor(int n)
{
if (!usinggl)
return;
if (n > 4)
n = 4;
if (n < 0)
n = 0;
glnativefactor = n;
if (n)
VIDCore->Resize(vdp2width_gl * n, vdp2height_gl * n, 0);
}
void (*vdp2hookfcn)(u16 v) = NULL;
void vdp2newhook(u16 v)
{
vdp2hookfcn(v);
if (glnativefactor)
{
if (glwidth != vdp2width_gl * glnativefactor || glheight != vdp2height_gl * glnativefactor)
VIDCore->Resize(vdp2width_gl * glnativefactor, vdp2height_gl * glnativefactor, 0);
}
}
extern "C" __declspec(dllexport) int libyabause_init
(
CDInterface *_CD,
const char *biosfn,
int usegl,
int carttype,
int quickload,
int clocksync,
int clockbase
)
{
usinggl = usegl;
if (usegl)
{
#ifndef HEADLESS
if(!StartGLContext())
return 0;
#endif
if(!LoadExtensions())
return 0;
}
FECD.DeInit = _CD->DeInit;
FECD.GetStatus = _CD->GetStatus;
FECD.Init = _CD->Init;
FECD.ReadAheadFAD = _CD->ReadAheadFAD;
FECD.ReadSectorFAD = _CD->ReadSectorFAD;
FECD.ReadTOC = _CD->ReadTOC;
memcpy(&FESND, &SNDDummy, sizeof(FESND));
FESND.id = 2;
FESND.Name = "FESND";
FESND.GetAudioSpace = FESNDGetAudioSpace;
FESND.UpdateAudio = FESNDUpdateAudio;
yabauseinit_struct yinit;
memset(&yinit, 0, sizeof(yabauseinit_struct));
yinit.percoretype = PERCORE_DUMMY;
yinit.sh2coretype = SH2CORE_INTERPRETER;
if (usegl)
yinit.vidcoretype = VIDCORE_OGL;
else
yinit.vidcoretype = VIDCORE_SOFT;
yinit.sndcoretype = 2;
yinit.cdcoretype = 2;
yinit.m68kcoretype = M68KCORE_C68K;
yinit.cartpath = CART_NONE;
yinit.regionid = REGION_AUTODETECT;
yinit.biospath = biosfn;
yinit.cdpath = "Saturnus";
yinit.buppath = NULL;
yinit.mpegpath = NULL;
yinit.carttype = carttype;
yinit.netlinksetting = NULL;
yinit.videoformattype = VIDEOFORMATTYPE_NTSC;
yabsys.usequickload = quickload;
yinit.usethreads = 0;
yinit.frameskip = 0;
yinit.clocksync = clocksync;
yinit.basetime = clockbase;
if (usegl && !vdp2hookfcn)
{
vdp2hookfcn = VIDOGL.Vdp2SetResolution;
VIDOGL.Vdp2SetResolution = vdp2newhook;
}
if (YabauseInit(&yinit) != 0)
return 0;
SpeedThrottleDisable();
DisableAutoFrameSkip();
ScspSetFrameAccurate(1);
OSDChangeCore(OSDCORE_DUMMY);
ctrl1 = PerPadAdd(&PORTDATA1);
ctrl2 = PerPadAdd(&PORTDATA2);
return 1;
}