Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/yabause/src/libyabause/yui.cpp
2 views
1
//bizhawk
2
#define HEADLESS
3
4
#define WIN32_LEAN_AND_MEAN
5
#include <Windows.h>
6
#include <gl/GL.h>
7
#include "../windows/glext.h"
8
9
extern "C" {
10
#include "../cs0.h"
11
#include "../m68kcore.h"
12
#include "../peripheral.h"
13
#include "../vidsoft.h"
14
#include "../vdp2.h"
15
#include "../yui.h"
16
#include "../movie.h"
17
#include "../vidogl.h"
18
}
19
20
void (*inputcallback)(void) = NULL;
21
22
extern "C" __declspec(dllexport) void libyabause_setinputcallback(void (*cb)(void))
23
{
24
inputcallback = cb;
25
}
26
27
void (*tracecallback)(const char* dis, const char* regs) = NULL;
28
29
extern "C" __declspec(dllexport) void libyabause_settracecallback(void (*cb)(const char* dis, const char* regs))
30
{
31
tracecallback = cb;
32
}
33
34
CDInterface FECD =
35
{
36
2,
37
"FECD",
38
NULL,
39
NULL,
40
NULL,
41
NULL,
42
NULL,
43
NULL,
44
};
45
46
SoundInterface_struct FESND;
47
48
49
extern "C" SH2Interface_struct *SH2CoreList[] = {
50
&SH2Interpreter,
51
&SH2DebugInterpreter,
52
NULL
53
};
54
55
extern "C" PerInterface_struct *PERCoreList[] = {
56
&PERDummy,
57
NULL
58
};
59
60
extern "C" CDInterface *CDCoreList[] = {
61
&DummyCD,
62
&ISOCD,
63
&FECD,
64
NULL
65
};
66
67
extern "C" SoundInterface_struct *SNDCoreList[] = {
68
&SNDDummy,
69
&FESND,
70
NULL
71
};
72
73
extern "C" VideoInterface_struct *VIDCoreList[] = {
74
&VIDDummy,
75
&VIDOGL,
76
&VIDSoft,
77
NULL
78
};
79
80
extern "C" M68K_struct *M68KCoreList[] = {
81
&M68KDummy,
82
&M68KC68K,
83
#ifdef HAVE_Q68
84
&M68KQ68,
85
#endif
86
NULL
87
};
88
89
/* If Yabause encounters any fatal errors, it sends the error text to this function */
90
void YuiErrorMsg(const char *string)
91
{
92
MessageBoxA(NULL, string, "Yabooze dun goofed", 0);
93
}
94
95
96
int red_size;
97
int green_size;
98
int blue_size;
99
int depth_size;
100
101
PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
102
PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;
103
PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers;
104
PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers;
105
PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
106
PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
107
PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage;
108
PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
109
PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
110
111
int LoadExtensions()
112
{
113
glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)wglGetProcAddress("glBindRenderbufferEXT");
114
if( glBindRenderbuffer == NULL ) return 0;
115
glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)wglGetProcAddress("glDeleteRenderbuffersEXT");
116
if(glDeleteRenderbuffers==NULL) return 0;
117
glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)wglGetProcAddress("glGenRenderbuffersEXT");
118
if( glGenRenderbuffers == NULL ) return 0;
119
glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)wglGetProcAddress("glRenderbufferStorageEXT");
120
if( glRenderbufferStorage == NULL ) return 0;
121
glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)wglGetProcAddress("glBindFramebufferEXT");
122
if( glBindFramebuffer==NULL) return 0;
123
glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)wglGetProcAddress("glDeleteFramebuffersEXT");
124
if( glDeleteFramebuffers==NULL) return 0;
125
glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)wglGetProcAddress("glGenFramebuffersEXT");
126
if( glGenFramebuffers == NULL ) return 0;
127
glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)wglGetProcAddress("glCheckFramebufferStatusEXT");
128
if( glCheckFramebufferStatus == NULL ) return 0;
129
glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)wglGetProcAddress("glFramebufferRenderbufferEXT");
130
if( glFramebufferRenderbuffer == NULL ) return 0;
131
132
return 1;
133
}
134
135
/* Sets attribute for the Video display. The values passed to this function
136
depends on what Video core is being used at the time. This may end up
137
being moved to the Video Core. */
138
void YuiSetVideoAttribute(int type, int val)
139
{
140
// only called in GL mode
141
switch (type)
142
{
143
case RED_SIZE:
144
red_size = val;
145
break;
146
case GREEN_SIZE:
147
green_size = val;
148
break;
149
case BLUE_SIZE:
150
blue_size = val;
151
break;
152
case DEPTH_SIZE:
153
depth_size = val;
154
break;
155
case DOUBLEBUFFER:
156
break;
157
}
158
}
159
160
161
GLuint fbuff = 0;
162
GLuint color = 0;
163
GLuint depth = 0;
164
165
int glwidth, glheight;
166
167
u8 *glbuff = NULL;
168
169
/* Tells the yui it wants to setup the display to display the specified video
170
format. It's up to the yui to setup the actual display. This may end
171
up being moved to the Video Core. */
172
int YuiSetVideoMode(int width, int height, int bpp, int fullscreen)
173
{
174
// only called in GL mode
175
if (bpp != 32 || red_size != 8 || green_size != 8 || blue_size != 8 || depth_size != 24)
176
return -1; // failure
177
178
if (fbuff)
179
glDeleteFramebuffers(1, &fbuff);
180
if (color)
181
glDeleteRenderbuffers(1, &color);
182
if (depth)
183
glDeleteRenderbuffers(1, &depth);
184
glGenFramebuffers(1, &fbuff);
185
glGenRenderbuffers(1, &color);
186
glGenRenderbuffers(1, &depth);
187
188
glBindFramebuffer(GL_FRAMEBUFFER, fbuff);
189
190
glBindRenderbuffer(GL_RENDERBUFFER, depth);
191
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
192
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
193
194
glBindRenderbuffer(GL_RENDERBUFFER, color);
195
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8, width, height);
196
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color);
197
198
//glBindRenderbuffer(GL_RENDERBUFFER, 0);
199
200
if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
201
return -1;
202
203
glwidth = width;
204
glheight = height;
205
206
if (glbuff)
207
free(glbuff);
208
glbuff = (u8*) malloc(glwidth * glheight * 4);
209
210
return 0; // success
211
}
212
213
int usinggl = 0;
214
HWND glWND;
215
HDC glDC;
216
HGLRC glRC;
217
218
void KillGLContext()
219
{
220
wglMakeCurrent(NULL, NULL);
221
wglDeleteContext(glRC);
222
ReleaseDC(glWND, glDC);
223
DestroyWindow(glWND);
224
}
225
226
int StartGLContext()
227
{
228
PIXELFORMATDESCRIPTOR pfd;
229
memset(&pfd,0, sizeof(PIXELFORMATDESCRIPTOR));
230
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
231
pfd.nVersion = 1;
232
pfd.dwFlags = PFD_SUPPORT_OPENGL;
233
pfd.iPixelType = PFD_TYPE_RGBA;
234
pfd.cColorBits = 24;
235
pfd.cAlphaBits = 8;
236
pfd.cDepthBits = 24;
237
pfd.cStencilBits = 8;
238
pfd.iLayerType = PFD_MAIN_PLANE;
239
240
glWND = CreateWindow(L"EDIT", 0, 0, 0, 0, 512, 512, 0, 0, 0, 0);
241
if (!glWND)
242
return 0;
243
glDC = GetDC(glWND);
244
if (!glDC)
245
{
246
DestroyWindow(glWND);
247
return 0;
248
}
249
int PixelFormat = ChoosePixelFormat(glDC, &pfd);
250
if (!PixelFormat)
251
{
252
ReleaseDC(glWND, glDC);
253
DestroyWindow(glWND);
254
return 0;
255
}
256
if (!SetPixelFormat(glDC, PixelFormat, &pfd))
257
{
258
ReleaseDC(glWND, glDC);
259
DestroyWindow(glWND);
260
return 0;
261
}
262
glRC = wglCreateContext(glDC);
263
if (!glRC)
264
{
265
ReleaseDC(glWND, glDC);
266
DestroyWindow(glWND);
267
return 0;
268
}
269
if (!wglMakeCurrent(glDC, glRC))
270
{
271
wglDeleteContext(glRC);
272
ReleaseDC(glWND, glDC);
273
DestroyWindow(glWND);
274
return 0;
275
}
276
return 1;
277
}
278
279
280
281
s16 *sndbuff = NULL;
282
int sndbuffpos = 0;
283
u32 *vidbuff = NULL;
284
285
PerPad_struct *ctrl1;
286
PerPad_struct *ctrl2;
287
288
extern "C" int vdp2height;
289
extern "C" int vdp2width;
290
extern "C" GLuint FboTexture;
291
292
/* Tells the yui to exchange front and back video buffers. This may end
293
up being moved to the Video Core. */
294
void YuiSwapBuffers(void)
295
{
296
if (vidbuff)
297
{
298
if (!usinggl)
299
{
300
u8 *src = (u8*)dispbuffer;
301
u8 *dst = (u8*)vidbuff;
302
303
for (int j = 0; j < vdp2height; j++)
304
for (int i = 0; i < vdp2width; i++)
305
{
306
dst[0] = src[2];
307
dst[1] = src[1];
308
dst[2] = src[0];
309
dst[3] = 0xff;
310
src += 4;
311
dst += 4;
312
}
313
}
314
else
315
{
316
#ifdef CAN_RETURN_TEXTURE_IDS
317
//simply write the FboTexture into the videobuffer for later magic detection in frontend
318
memcpy(vidbuff,&FboTexture,4);
319
#else
320
glReadPixels(0, 0, glwidth, glheight, GL_BGRA, GL_UNSIGNED_BYTE, glbuff);
321
322
u32 *src = (u32*)glbuff;
323
u32 *dst = (u32*)vidbuff;
324
325
dst += glwidth * (glheight - 1);
326
327
for (int j = 0; j < glheight; j++)
328
{
329
memcpy(dst, src, glwidth * 4);
330
src += glwidth;
331
dst -= glwidth;
332
}
333
#endif
334
}
335
}
336
}
337
338
static void FESNDUpdateAudio(UNUSED u32 *leftchanbuffer, UNUSED u32 *rightchanbuffer, UNUSED u32 num_samples)
339
{
340
/*
341
static s16 stereodata16[44100 / 50];
342
ScspConvert32uto16s((s32 *)leftchanbuffer, (s32 *)rightchanbuffer, (s16 *)stereodata16, num_samples);
343
*/
344
}
345
346
static u32 FESNDGetAudioSpace(void)
347
{
348
return 44100;
349
}
350
// some garbage from the sound system, we'll have to fix this all up
351
extern "C" void DRV_AviSoundUpdate(void* soundData, int soundLen)
352
{
353
// soundLen should be number of sample pairs (4 byte units)
354
if (sndbuff)
355
{
356
s16 *src = (s16*)soundData;
357
s16 *dst = sndbuff;
358
dst += sndbuffpos * 2;
359
memcpy (dst, src, soundLen * 4);
360
sndbuffpos += soundLen;
361
}
362
}
363
364
// must hold at least 704x512 pixels
365
extern "C" __declspec(dllexport) void libyabause_setvidbuff(u32 *buff)
366
{
367
vidbuff = buff;
368
}
369
370
extern "C" __declspec(dllexport) void libyabause_setsndbuff(s16 *buff)
371
{
372
sndbuff = buff;
373
}
374
375
extern "C" __declspec(dllexport) void libyabause_softreset()
376
{
377
YabauseResetButton();
378
}
379
380
extern "C" __declspec(dllexport) void libyabause_hardreset()
381
{
382
YabauseReset();
383
}
384
385
extern "C" __declspec(dllexport) int libyabause_loadstate(const char *fn)
386
{
387
return !YabLoadState(fn);
388
}
389
390
extern "C" __declspec(dllexport) int libyabause_savestate(const char *fn)
391
{
392
return !YabSaveState(fn);
393
}
394
395
extern "C" __declspec(dllexport) int libyabause_savesaveram(const char *fn)
396
{
397
return !T123Save(BupRam, 0x10000, 1, fn);
398
}
399
400
extern "C" __declspec(dllexport) int libyabause_loadsaveram(const char *fn)
401
{
402
return !T123Load(BupRam, 0x10000, 1, fn);
403
}
404
405
extern "C" __declspec(dllexport) int libyabause_saveramodified()
406
{
407
return BupRamWritten;
408
}
409
410
extern "C" __declspec(dllexport) void libyabause_clearsaveram()
411
{
412
FormatBackupRam(BupRam, 0x10000);
413
}
414
415
typedef struct
416
{
417
void *data;
418
const char *name;
419
int length;
420
} memoryarea;
421
422
memoryarea normmemareas[] =
423
{
424
{NULL, "Boot Rom", 512 * 1024},
425
{NULL, "Backup Ram", 64 * 1024},
426
{NULL, "Work Ram Low", 1024 * 1024},
427
{NULL, "Sound Ram", 512 * 1024},
428
{NULL, "VDP1 Ram", 512 * 1024},
429
{NULL, "VDP1 Framebuffer", 512 * 1024},
430
{NULL, "VDP2 Ram", 512 * 1024},
431
{NULL, "VDP2 CRam", 4 * 1024},
432
{NULL, "Work Ram High", 1024 * 1024},
433
{NULL, NULL, 0}
434
};
435
436
extern "C" __declspec(dllexport) memoryarea *libyabause_getmemoryareas()
437
{
438
normmemareas[0].data = BiosRom;
439
normmemareas[1].data = BupRam;
440
normmemareas[2].data = LowWram;
441
normmemareas[3].data = SoundRam;
442
normmemareas[4].data = Vdp1Ram;
443
normmemareas[5].data = Vdp1FrameBuffer;
444
normmemareas[6].data = Vdp2Ram;
445
normmemareas[7].data = Vdp2ColorRam;
446
normmemareas[8].data = HighWram;
447
return &normmemareas[0];
448
}
449
450
extern "C" __declspec(dllexport) int libyabause_frameadvance(int *w, int *h, int *nsamp)
451
{
452
LagFrameFlag = 1;
453
sndbuffpos = 0;
454
YabauseEmulate();
455
if (usinggl)
456
{
457
*w = glwidth;
458
*h = glheight;
459
}
460
else
461
{
462
*w = vdp2width;
463
*h = vdp2height;
464
}
465
*nsamp = sndbuffpos;
466
return LagFrameFlag;
467
}
468
469
extern "C" __declspec(dllexport) void libyabause_deinit()
470
{
471
PerPortReset();
472
YabauseDeInit();
473
if (usinggl)
474
{
475
KillGLContext();
476
usinggl = 0;
477
}
478
if (glbuff)
479
{
480
free(glbuff);
481
glbuff = NULL;
482
}
483
}
484
485
extern "C" __declspec(dllexport) void libyabause_setpads(u8 p11, u8 p12, u8 p21, u8 p22)
486
{
487
ctrl1->padbits[0] = p11;
488
ctrl1->padbits[1] = p12;
489
ctrl2->padbits[0] = p21;
490
ctrl2->padbits[1] = p22;
491
}
492
493
int glnativefactor = 0;
494
495
extern "C" __declspec(dllexport) void libyabause_glresize(int w, int h)
496
{
497
if (usinggl && !glnativefactor)
498
VIDCore->Resize(w, h, 0);
499
}
500
501
extern "C" __declspec(dllexport) void libyabause_glsetnativefactor(int n)
502
{
503
if (!usinggl)
504
return;
505
if (n > 4)
506
n = 4;
507
if (n < 0)
508
n = 0;
509
glnativefactor = n;
510
if (n)
511
VIDCore->Resize(vdp2width_gl * n, vdp2height_gl * n, 0);
512
}
513
514
void (*vdp2hookfcn)(u16 v) = NULL;
515
516
void vdp2newhook(u16 v)
517
{
518
vdp2hookfcn(v);
519
if (glnativefactor)
520
{
521
if (glwidth != vdp2width_gl * glnativefactor || glheight != vdp2height_gl * glnativefactor)
522
VIDCore->Resize(vdp2width_gl * glnativefactor, vdp2height_gl * glnativefactor, 0);
523
}
524
}
525
526
extern "C" __declspec(dllexport) int libyabause_init
527
(
528
CDInterface *_CD,
529
const char *biosfn,
530
int usegl,
531
int carttype,
532
int quickload,
533
int clocksync,
534
int clockbase
535
)
536
{
537
usinggl = usegl;
538
539
if (usegl)
540
{
541
//headless cores should not create GL contexts, but use the one from the invoking frontend
542
#ifndef HEADLESS
543
if(!StartGLContext())
544
return 0;
545
#endif
546
if(!LoadExtensions())
547
return 0;
548
}
549
550
FECD.DeInit = _CD->DeInit;
551
FECD.GetStatus = _CD->GetStatus;
552
FECD.Init = _CD->Init;
553
FECD.ReadAheadFAD = _CD->ReadAheadFAD;
554
FECD.ReadSectorFAD = _CD->ReadSectorFAD;
555
FECD.ReadTOC = _CD->ReadTOC;
556
557
// only overwrite a few SNDDummy functions
558
memcpy(&FESND, &SNDDummy, sizeof(FESND));
559
FESND.id = 2;
560
FESND.Name = "FESND";
561
FESND.GetAudioSpace = FESNDGetAudioSpace;
562
FESND.UpdateAudio = FESNDUpdateAudio;
563
564
yabauseinit_struct yinit;
565
memset(&yinit, 0, sizeof(yabauseinit_struct));
566
yinit.percoretype = PERCORE_DUMMY;
567
yinit.sh2coretype = SH2CORE_INTERPRETER;
568
if (usegl)
569
yinit.vidcoretype = VIDCORE_OGL;
570
else
571
yinit.vidcoretype = VIDCORE_SOFT;
572
yinit.sndcoretype = 2; //SNDCORE_DUMMY;
573
yinit.cdcoretype = 2; // CDCORE_ISO; //CDCORE_DUMMY;
574
yinit.m68kcoretype = M68KCORE_C68K;
575
yinit.cartpath = CART_NONE;
576
yinit.regionid = REGION_AUTODETECT;
577
yinit.biospath = biosfn;
578
yinit.cdpath = "Saturnus"; //NULL;
579
yinit.buppath = NULL;
580
yinit.mpegpath = NULL;
581
yinit.carttype = carttype;
582
yinit.netlinksetting = NULL;
583
yinit.videoformattype = VIDEOFORMATTYPE_NTSC;
584
yabsys.usequickload = quickload;
585
yinit.usethreads = 0;
586
yinit.frameskip = 0;
587
yinit.clocksync = clocksync;
588
yinit.basetime = clockbase; // same format as return from time(); 0 to use time()
589
590
if (usegl && !vdp2hookfcn)
591
{
592
// hook vdp2setresolution
593
vdp2hookfcn = VIDOGL.Vdp2SetResolution;
594
VIDOGL.Vdp2SetResolution = vdp2newhook;
595
}
596
597
if (YabauseInit(&yinit) != 0)
598
return 0;
599
600
SpeedThrottleDisable();
601
DisableAutoFrameSkip();
602
ScspSetFrameAccurate(1);
603
604
OSDChangeCore(OSDCORE_DUMMY);
605
606
ctrl1 = PerPadAdd(&PORTDATA1);
607
ctrl2 = PerPadAdd(&PORTDATA2);
608
609
return 1;
610
}
611
612