Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/yabause/src/carbon/main.c
2 views
1
/* Copyright 2006 Guillaume Duhamel
2
Copyright 2006 Anders Montonen
3
Copyright 2010 Alex Marshall
4
5
This file is part of Yabause.
6
7
Yabause is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2 of the License, or
10
(at your option) any later version.
11
12
Yabause is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
16
17
You should have received a copy of the GNU General Public License
18
along with Yabause; if not, write to the Free Software
19
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
*/
21
22
#include <unistd.h>
23
#include <Carbon/Carbon.h>
24
#include <AGL/agl.h>
25
26
#include "../core.h"
27
#include "../memory.h"
28
#include "settings.h"
29
#include "cpustatus.h"
30
#include "../yabause.h"
31
32
#define YUI_MENU_EMULATION 1
33
#define YUI_MENU_DEBUG 2
34
35
#define YUI_COMMAND_RESET 1
36
#define YUI_COMMAND_PAUSE 2
37
#define YUI_COMMAND_RESUME 3
38
#define YUI_COMMAND_SHOW_CPU 4
39
#define YUI_COMMAND_HIDE_CPU 5
40
#define YUI_COMMAND_TOGGLE_NBG0 6
41
#define YUI_COMMAND_TOGGLE_NBG1 7
42
#define YUI_COMMAND_TOGGLE_NBG2 8
43
#define YUI_COMMAND_TOGGLE_NBG3 9
44
#define YUI_COMMAND_TOGGLE_RBG0 10
45
#define YUI_COMMAND_TOGGLE_VDP1 11
46
#define YUI_COMMAND_TOGGLE_FULLSCREEN 12
47
#define YUI_COMMAND_LOAD_BINARY 13
48
#define YUI_COMMAND_LOAD_AND_EXECUTE 14
49
#define YUI_COMMAND_SAVE_BINARY 15
50
51
AGLContext myAGLContext = NULL;
52
WindowRef myWindow = NULL;
53
yabauseinit_struct yinit;
54
55
M68K_struct * M68KCoreList[] = {
56
&M68KDummy,
57
#ifdef HAVE_C68K
58
&M68KC68K,
59
#endif
60
#ifdef HAVE_Q68
61
&M68KQ68,
62
#endif
63
NULL
64
};
65
66
SH2Interface_struct *SH2CoreList[] = {
67
&SH2Interpreter,
68
&SH2DebugInterpreter,
69
NULL
70
};
71
72
PerInterface_struct *PERCoreList[] = {
73
&PERDummy,
74
NULL
75
};
76
77
CDInterface *CDCoreList[] = {
78
&DummyCD,
79
&ISOCD,
80
&ArchCD,
81
NULL
82
};
83
84
SoundInterface_struct *SNDCoreList[] = {
85
&SNDDummy,
86
#ifdef HAVE_LIBSDL
87
&SNDSDL,
88
#endif
89
NULL
90
};
91
92
VideoInterface_struct *VIDCoreList[] = {
93
&VIDDummy,
94
&VIDOGL,
95
&VIDSoft,
96
NULL
97
};
98
99
static EventLoopTimerRef EventTimer;
100
int load_file_core(char* file, char* addr, int type);
101
102
void YuiIdle(EventLoopTimerRef a, void * b)
103
{
104
PERCore->HandleEvents();
105
}
106
107
void read_settings(void) {
108
PerPad_struct * pad;
109
int i;
110
CFStringRef s;
111
yinit.percoretype = PERCORE_DUMMY;
112
yinit.sh2coretype = SH2CORE_INTERPRETER;
113
yinit.vidcoretype = VIDCORE_OGL;
114
yinit.m68kcoretype = M68KCORE_C68K;
115
s = CFPreferencesCopyAppValue(CFSTR("VideoCore"),
116
kCFPreferencesCurrentApplication);
117
if (s)
118
yinit.vidcoretype = CFStringGetIntValue(s) - 1;
119
yinit.sndcoretype = SNDCORE_DUMMY;
120
s = CFPreferencesCopyAppValue(CFSTR("SoundCore"),
121
kCFPreferencesCurrentApplication);
122
if (s)
123
yinit.sndcoretype = CFStringGetIntValue(s) - 1;
124
yinit.cdcoretype = CDCORE_ARCH;
125
s = CFPreferencesCopyAppValue(CFSTR("CDROMCore"),
126
kCFPreferencesCurrentApplication);
127
if (s)
128
yinit.cdcoretype = CFStringGetIntValue(s) - 1;
129
yinit.carttype = CART_NONE;
130
s = CFPreferencesCopyAppValue(CFSTR("CartType"),
131
kCFPreferencesCurrentApplication);
132
if (s)
133
yinit.carttype = CFStringGetIntValue(s) - 1;
134
yinit.regionid = 0;
135
s = CFPreferencesCopyAppValue(CFSTR("Region"),
136
kCFPreferencesCurrentApplication);
137
if (s)
138
yinit.regionid = CFStringGetIntValue(s) - 1;
139
140
yinit.biospath = 0;
141
s = CFPreferencesCopyAppValue(CFSTR("BiosPath"),
142
kCFPreferencesCurrentApplication);
143
if (s)
144
yinit.biospath = strdup(CFStringGetCStringPtr(s, 0));
145
yinit.cdpath = 0;
146
s = CFPreferencesCopyAppValue(CFSTR("CDROMDrive"),
147
kCFPreferencesCurrentApplication);
148
if (s)
149
yinit.cdpath = strdup(CFStringGetCStringPtr(s, 0));
150
yinit.buppath = 0;
151
s = CFPreferencesCopyAppValue(CFSTR("BackupRamPath"),
152
kCFPreferencesCurrentApplication);
153
if (s)
154
yinit.buppath = strdup(CFStringGetCStringPtr(s, 0));
155
yinit.mpegpath = 0;
156
s = CFPreferencesCopyAppValue(CFSTR("MpegRomPath"),
157
kCFPreferencesCurrentApplication);
158
if (s)
159
yinit.mpegpath = strdup(CFStringGetCStringPtr(s, 0));
160
yinit.cartpath = 0;
161
s = CFPreferencesCopyAppValue(CFSTR("CartPath"),
162
kCFPreferencesCurrentApplication);
163
if (s)
164
yinit.cartpath = strdup(CFStringGetCStringPtr(s, 0));
165
166
yinit.videoformattype = VIDEOFORMATTYPE_NTSC;
167
168
s = CFPreferencesCopyAppValue(CFSTR("AutoFrameSkip"),
169
kCFPreferencesCurrentApplication);
170
if (s)
171
yinit.frameskip = CFStringGetIntValue(s);
172
173
PerPortReset();
174
pad = PerPadAdd(&PORTDATA1);
175
176
i = 0;
177
while(PerPadNames[i]) {
178
s = CFPreferencesCopyAppValue(
179
CFStringCreateWithCString(0, PerPadNames[i], 0),
180
kCFPreferencesCurrentApplication);
181
if (s)
182
PerSetKey(CFStringGetIntValue(s), i, pad);
183
i++;
184
}
185
}
186
187
static void YuiPause(const int Pause)
188
{
189
EventTimerInterval Interval;
190
191
if(Pause)
192
{
193
Interval = kEventDurationForever;
194
ScspMuteAudio(SCSP_MUTE_SYSTEM);
195
}
196
else
197
{
198
Interval = 16*kEventDurationMillisecond;
199
ScspUnMuteAudio(SCSP_MUTE_SYSTEM);
200
}
201
202
SetEventLoopTimerNextFireTime(EventTimer, Interval);
203
}
204
205
void YuiRun(void) {
206
static int FirstRun = 1;
207
EventLoopTimerUPP myFrameUPP;
208
209
if(FirstRun)
210
{
211
myFrameUPP = NewEventLoopTimerUPP(YuiIdle);
212
InstallEventLoopTimer(GetCurrentEventLoop(), kEventDurationNoWait,
213
16*kEventDurationMillisecond, myFrameUPP, NULL, &EventTimer);
214
FirstRun = 0;
215
}
216
else
217
{
218
YuiPause(0);
219
YabauseDeInit();
220
}
221
222
read_settings();
223
YabauseInit(&yinit);
224
}
225
226
static void TogglePairedMenuItems(MenuRef menu, MenuItemIndex BaseItemIndex)
227
{
228
MenuItemAttributes ItemAttributes;
229
230
GetMenuItemAttributes(menu, BaseItemIndex, &ItemAttributes);
231
232
if(ItemAttributes & kMenuItemAttrHidden)
233
{
234
ChangeMenuItemAttributes(menu, BaseItemIndex, 0, kMenuItemAttrHidden);
235
ChangeMenuItemAttributes(menu, BaseItemIndex+1, kMenuItemAttrHidden, 0);
236
}
237
else
238
{
239
ChangeMenuItemAttributes(menu, BaseItemIndex, kMenuItemAttrHidden, 0);
240
ChangeMenuItemAttributes(menu, BaseItemIndex+1, 0, kMenuItemAttrHidden);
241
}
242
}
243
244
OSStatus MyWindowEventHandler (EventHandlerCallRef myHandler, EventRef theEvent, void* userData)
245
{
246
OSStatus ret = noErr;
247
MenuRef menu;
248
249
switch(GetEventClass(theEvent)) {
250
case kEventClassWindow:
251
switch (GetEventKind (theEvent)) {
252
case kEventWindowClose:
253
254
YabauseDeInit();
255
QuitApplicationEventLoop();
256
break;
257
258
case kEventWindowBoundsChanged:
259
aglUpdateContext(myAGLContext);
260
{
261
Rect bounds;
262
GetEventParameter(theEvent, kEventParamCurrentBounds,
263
typeQDRectangle, NULL, sizeof(Rect), NULL, &bounds);
264
glViewport(0, 0, bounds.right - bounds.left,
265
bounds.bottom - bounds.top);
266
}
267
break;
268
}
269
break;
270
case kEventClassCommand:
271
{
272
HICommand command;
273
GetEventParameter(theEvent, kEventParamDirectObject,
274
typeHICommand, NULL, sizeof(HICommand), NULL, &command);
275
switch(command.commandID) {
276
case kHICommandPreferences:
277
CreateSettingsWindow();
278
break;
279
case kHICommandQuit:
280
YabauseDeInit();
281
QuitApplicationEventLoop();
282
break;
283
case YUI_COMMAND_RESET:
284
YabauseReset();
285
break;
286
case YUI_COMMAND_PAUSE:
287
YuiPause(1);
288
menu = GetMenuRef(YUI_MENU_EMULATION);
289
TogglePairedMenuItems(menu, 2);
290
UpdateCPUStatusWindow();
291
break;
292
case YUI_COMMAND_RESUME:
293
YuiPause(0);
294
menu = GetMenuRef(YUI_MENU_EMULATION);
295
TogglePairedMenuItems(menu, 2);
296
break;
297
case YUI_COMMAND_SHOW_CPU:
298
ShowCPUStatusWindow();
299
menu = GetMenuRef(YUI_MENU_DEBUG);
300
TogglePairedMenuItems(menu, 1);
301
break;
302
case YUI_COMMAND_HIDE_CPU:
303
HideCPUStatusWindow();
304
menu = GetMenuRef(YUI_MENU_DEBUG);
305
TogglePairedMenuItems(menu, 1);
306
break;
307
case YUI_COMMAND_TOGGLE_NBG0:
308
if(VIDCore)
309
{
310
menu = GetMenuRef(YUI_MENU_DEBUG);
311
TogglePairedMenuItems(menu, 4);
312
ToggleNBG0();
313
}
314
break;
315
case YUI_COMMAND_TOGGLE_NBG1:
316
if(VIDCore)
317
{
318
menu = GetMenuRef(YUI_MENU_DEBUG);
319
TogglePairedMenuItems(menu, 6);
320
ToggleNBG1();
321
}
322
break;
323
case YUI_COMMAND_TOGGLE_NBG2:
324
if(VIDCore)
325
{
326
menu = GetMenuRef(YUI_MENU_DEBUG);
327
TogglePairedMenuItems(menu, 8);
328
ToggleNBG2();
329
}
330
break;
331
case YUI_COMMAND_TOGGLE_NBG3:
332
if(VIDCore)
333
{
334
menu = GetMenuRef(YUI_MENU_DEBUG);
335
TogglePairedMenuItems(menu, 10);
336
ToggleNBG3();
337
}
338
break;
339
case YUI_COMMAND_TOGGLE_RBG0:
340
if(VIDCore)
341
{
342
menu = GetMenuRef(YUI_MENU_DEBUG);
343
TogglePairedMenuItems(menu, 12);
344
ToggleRBG0();
345
}
346
break;
347
case YUI_COMMAND_TOGGLE_VDP1:
348
if(VIDCore)
349
{
350
menu = GetMenuRef(YUI_MENU_DEBUG);
351
TogglePairedMenuItems(menu, 14);
352
ToggleVDP1();
353
}
354
break;
355
case YUI_COMMAND_TOGGLE_FULLSCREEN:
356
if(VIDCore)
357
{
358
menu = GetMenuRef(YUI_MENU_EMULATION);
359
TogglePairedMenuItems(menu, 5);
360
ToggleFullScreen();
361
}
362
break;
363
case YUI_COMMAND_LOAD_BINARY:
364
CreateLoadWindow(0);
365
break;
366
case YUI_COMMAND_LOAD_AND_EXECUTE:
367
CreateLoadWindow(1);
368
break;
369
case YUI_COMMAND_SAVE_BINARY:
370
// MappedMemorySave(file, address, size);
371
break;
372
default:
373
ret = eventNotHandledErr;
374
printf("unhandled command\n");
375
break;
376
}
377
}
378
break;
379
380
case kEventClassKeyboard:
381
switch(GetEventKind(theEvent)) {
382
int i;
383
UInt32 key;
384
case kEventRawKeyDown:
385
GetEventParameter(theEvent, kEventParamKeyCode,
386
typeUInt32, NULL, sizeof(UInt32), NULL, &key);
387
PerKeyDown(key);
388
break;
389
case kEventRawKeyUp:
390
GetEventParameter(theEvent, kEventParamKeyCode,
391
typeUInt32, NULL, sizeof(UInt32), NULL, &key);
392
PerKeyUp(key);
393
break;
394
}
395
break;
396
}
397
398
return ret;
399
}
400
401
static WindowRef CreateMyWindow() {
402
403
WindowRef myWindow;
404
Rect contentBounds;
405
406
CFStringRef windowTitle = CFSTR("Yabause");
407
WindowClass windowClass = kDocumentWindowClass;
408
WindowAttributes attributes =
409
kWindowStandardDocumentAttributes |
410
kWindowStandardHandlerAttribute |
411
kWindowLiveResizeAttribute;
412
413
EventTypeSpec eventList[] = {
414
{ kEventClassWindow, kEventWindowClose },
415
{ kEventClassWindow, kEventWindowBoundsChanged },
416
{ kEventClassCommand, kEventCommandProcess },
417
{ kEventClassKeyboard, kEventRawKeyDown },
418
{ kEventClassKeyboard, kEventRawKeyUp }
419
};
420
421
SetRect(&contentBounds, 200, 200, 520, 424);
422
423
CreateNewWindow (windowClass,
424
attributes,
425
&contentBounds,
426
&myWindow);
427
428
SetWindowTitleWithCFString (myWindow, windowTitle);
429
CFRelease(windowTitle);
430
ShowWindow(myWindow);
431
432
InstallWindowEventHandler(myWindow,
433
NewEventHandlerUPP (MyWindowEventHandler),
434
GetEventTypeCount(eventList),
435
eventList, myWindow, NULL);
436
return myWindow;
437
}
438
439
static OSStatus MyAGLReportError (void) {
440
GLenum err = aglGetError();
441
442
if (err == AGL_NO_ERROR)
443
return noErr;
444
else
445
return (OSStatus) err;
446
}
447
448
static OSStatus MySetWindowAsDrawableObject (WindowRef window)
449
{
450
OSStatus err = noErr;
451
452
GLint attributes[] = { AGL_RGBA,
453
AGL_DOUBLEBUFFER,
454
AGL_DEPTH_SIZE, 24,
455
AGL_NONE };
456
457
AGLPixelFormat myAGLPixelFormat;
458
459
myAGLPixelFormat = aglChoosePixelFormat (NULL, 0, attributes);
460
461
err = MyAGLReportError ();
462
463
if (myAGLPixelFormat) {
464
myAGLContext = aglCreateContext (myAGLPixelFormat, NULL);
465
466
err = MyAGLReportError ();
467
aglDestroyPixelFormat(myAGLPixelFormat);
468
}
469
470
if (! aglSetDrawable (myAGLContext, GetWindowPort (window)))
471
err = MyAGLReportError ();
472
473
if (!aglSetCurrentContext (myAGLContext))
474
err = MyAGLReportError ();
475
476
return err;
477
478
}
479
480
int main(int argc, char* argv[]) {
481
MenuRef menu;
482
EventLoopTimerRef nextFrameTimer;
483
IBNibRef menuNib;
484
485
myWindow = CreateMyWindow();
486
MySetWindowAsDrawableObject(myWindow);
487
488
CreateNibReference(CFSTR("menu"), &menuNib);
489
SetMenuBarFromNib(menuNib, CFSTR("MenuBar"));
490
491
EnableMenuCommand(NULL, kHICommandPreferences);
492
493
read_settings();
494
495
YuiRun();
496
if(argc >= 2)
497
load_file_core(argv[1], (argc >= 3) ? argv[2] : NULL, 1);
498
499
RunApplicationEventLoop();
500
501
return 0;
502
}
503
504
void YuiErrorMsg(const char * string) {
505
printf("%s\n", string);
506
}
507
508
void YuiSetVideoAttribute(int type, int val) {
509
}
510
511
int YuiSetVideoMode(int width, int height, int bpp, int fullscreen)
512
{
513
static CFDictionaryRef oldDisplayMode = 0;
514
static int oldDisplayModeValid = 0;
515
516
AGLPixelFormat myAGLPixelFormat;
517
AGLDrawable myDrawable = aglGetDrawable(myAGLContext);
518
OSStatus err = noErr;
519
GLint attributesFullscreen[] = { AGL_RGBA,
520
AGL_FULLSCREEN,
521
AGL_DOUBLEBUFFER,
522
AGL_DEPTH_SIZE, 24,
523
AGL_NONE };
524
CGDirectDisplayID displayId = kCGDirectMainDisplay;
525
526
if(myDrawable)
527
{
528
if(fullscreen)
529
{
530
Rect bounds;
531
CGPoint point;
532
CGDisplayCount displayCount;
533
534
GetWindowBounds(myWindow, kWindowGlobalPortRgn, &bounds);
535
point.x = (float)bounds.left;
536
point.y = (float)bounds.top;
537
538
CGGetDisplaysWithPoint(point, 1, &displayId, &displayCount);
539
540
CFDictionaryRef refDisplayMode = CGDisplayBestModeForParameters(displayId,
541
bpp, width, height, NULL);
542
if(refDisplayMode)
543
{
544
GDHandle gdhDisplay;
545
oldDisplayMode = CGDisplayCurrentMode(displayId);
546
oldDisplayModeValid = 1;
547
548
aglSetDrawable(myAGLContext, NULL);
549
aglSetCurrentContext(NULL);
550
aglDestroyContext(myAGLContext);
551
myAGLContext = NULL;
552
553
CGCaptureAllDisplays();
554
CGDisplaySwitchToMode(displayId, refDisplayMode);
555
CGDisplayHideCursor(displayId);
556
557
DMGetGDeviceByDisplayID((DisplayIDType)displayId, &gdhDisplay, 0);
558
559
myAGLPixelFormat = aglChoosePixelFormat(&gdhDisplay, 1, attributesFullscreen);
560
if(myAGLPixelFormat)
561
{
562
myAGLContext = aglCreateContext(myAGLPixelFormat, NULL);
563
if(myAGLContext)
564
{
565
aglSetCurrentContext(myAGLContext);
566
aglSetFullScreen(myAGLContext, width, height, 0, 0);
567
}
568
569
err = MyAGLReportError();
570
aglDestroyPixelFormat(myAGLPixelFormat);
571
}
572
else
573
{
574
err = MyAGLReportError();
575
CGReleaseAllDisplays();
576
CGDisplayShowCursor(displayId);
577
}
578
}
579
else
580
{
581
err = MyAGLReportError();
582
}
583
}
584
else
585
{
586
if(oldDisplayModeValid)
587
{
588
oldDisplayModeValid = 0;
589
590
aglSetDrawable(myAGLContext, NULL);
591
aglSetCurrentContext(NULL);
592
aglDestroyContext(myAGLContext);
593
myAGLContext = NULL;
594
595
CGDisplayShowCursor(displayId);
596
CGDisplaySwitchToMode(displayId, oldDisplayMode);
597
CGReleaseAllDisplays();
598
599
MySetWindowAsDrawableObject(myWindow);
600
}
601
}
602
}
603
604
return !(err == noErr);
605
}
606
607
void YuiSwapBuffers(void) {
608
aglSwapBuffers(myAGLContext);
609
}
610
611