ref: 649e0914486b43f31c89f8d17efc16d9df120198
dir: /src/OSGLUCCO.m/
/*
OSGLUCCO.m
Copyright (C) 2012 Paul C. Pratt, SDL by Sam Lantinga and others
You can redistribute this file and/or modify it under the terms
of version 2 of the GNU General Public License as published by
the Free Software Foundation. You should have received a copy
of the license along with this file; see the file COPYING.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
license for more details.
*/
/*
Operating System GLUe for mac os CoCOa
All operating system dependent code for the
Mac OS Cocoa should go here.
Originally derived from Cocoa port of SDL Library
by Sam Lantinga (but little trace of that remains).
*/
#include "CNFGRAPI.h"
#include "SYSDEPNS.h"
#include "ENDIANAC.h"
#include "MYOSGLUE.h"
#include "STRCONST.h"
/* --- adapting to API/ABI version differences --- */
#ifndef MAC_OS_X_VERSION_10_5
#define MAC_OS_X_VERSION_10_5 1050
#endif
#ifndef MAC_OS_X_VERSION_10_6
#define MAC_OS_X_VERSION_10_6 1060
#endif
#ifndef WantGraphicsSwitching
#define WantGraphicsSwitching 0
#endif
#if MAC_OS_X_VERSION_10_5 > MAC_OS_X_VERSION_MAX_ALLOWED
typedef unsigned long NSUInteger;
typedef long NSInteger;
typedef struct __CFError * CFErrorRef;
#if WantGraphicsSwitching
#define NSOpenGLPFAAllowOfflineRenderers \
(NSOpenGLPixelFormatAttribute)96
#endif
#endif
#if MAC_OS_X_VERSION_10_6 > MAC_OS_X_VERSION_MAX_ALLOWED
@protocol NSWindowDelegate <NSObject> @end
@protocol NSApplicationDelegate <NSObject> @end
#endif
LOCALVAR CFBundleRef AppServBunRef;
LOCALVAR blnr DidApplicationServicesBun = falseblnr;
LOCALFUNC blnr HaveApplicationServicesBun(void)
{
if (! DidApplicationServicesBun) {
AppServBunRef = CFBundleGetBundleWithIdentifier(
CFSTR("com.apple.ApplicationServices"));
DidApplicationServicesBun = trueblnr;
}
return (AppServBunRef != NULL);
}
#if MayFullScreen
LOCALVAR CFBundleRef HIToolboxBunRef;
LOCALVAR blnr DidHIToolboxBunRef = falseblnr;
LOCALFUNC blnr HaveHIToolboxBunRef(void)
{
if (! DidHIToolboxBunRef) {
HIToolboxBunRef = CFBundleGetBundleWithIdentifier(
CFSTR("com.apple.HIToolbox"));
DidHIToolboxBunRef = trueblnr;
}
return (HIToolboxBunRef != NULL);
}
#endif
#if MayFullScreen
/* SetSystemUIModeProcPtr API always not available */
typedef UInt32 MySystemUIMode;
typedef OptionBits MySystemUIOptions;
enum {
MykUIModeNormal = 0,
MykUIModeAllHidden = 3
};
enum {
MykUIOptionAutoShowMenuBar = 1 << 0,
MykUIOptionDisableAppleMenu = 1 << 2,
MykUIOptionDisableProcessSwitch = 1 << 3,
MykUIOptionDisableForceQuit = 1 << 4,
MykUIOptionDisableSessionTerminate = 1 << 5,
MykUIOptionDisableHide = 1 << 6
};
typedef OSStatus (*SetSystemUIModeProcPtr)
(MySystemUIMode inMode, MySystemUIOptions inOptions);
LOCALVAR SetSystemUIModeProcPtr MySetSystemUIMode = NULL;
LOCALVAR blnr DidSetSystemUIMode = falseblnr;
LOCALFUNC blnr HaveMySetSystemUIMode(void)
{
if (! DidSetSystemUIMode) {
if (HaveHIToolboxBunRef()) {
MySetSystemUIMode =
(SetSystemUIModeProcPtr)
CFBundleGetFunctionPointerForName(
HIToolboxBunRef, CFSTR("SetSystemUIMode"));
}
DidSetSystemUIMode = trueblnr;
}
return (MySetSystemUIMode != NULL);
}
#endif
typedef Boolean (*CFURLCopyResourcePropertyForKeyProcPtr) (
CFURLRef url,
CFStringRef key,
void *propertyValueTypeRefPtr,
CFErrorRef *error
);
LOCALVAR CFURLCopyResourcePropertyForKeyProcPtr
MyCFURLCopyResourcePropertyForKey = NULL;
LOCALVAR blnr DidCFURLCopyResourcePropertyForKey = falseblnr;
LOCALFUNC blnr HaveMyCFURLCopyResourcePropertyForKey(void)
{
if (! DidCFURLCopyResourcePropertyForKey) {
if (HaveApplicationServicesBun()) {
MyCFURLCopyResourcePropertyForKey =
(CFURLCopyResourcePropertyForKeyProcPtr)
CFBundleGetFunctionPointerForName(
AppServBunRef,
CFSTR("CFURLCopyResourcePropertyForKey"));
}
DidCFURLCopyResourcePropertyForKey = trueblnr;
}
return (MyCFURLCopyResourcePropertyForKey != NULL);
}
LOCALVAR const CFStringRef *MykCFURLIsAliasFileKey
= NULL;
LOCALVAR blnr DidkCFURLIsAliasFileKey = falseblnr;
LOCALFUNC blnr HaveMykCFURLIsAliasFileKey(void)
{
if (! DidkCFURLIsAliasFileKey) {
if (HaveApplicationServicesBun()) {
MykCFURLIsAliasFileKey =
(const CFStringRef *)
CFBundleGetDataPointerForName(
AppServBunRef, CFSTR("kCFURLIsAliasFileKey"));
}
DidkCFURLIsAliasFileKey = trueblnr;
}
return (MykCFURLIsAliasFileKey != NULL);
}
LOCALVAR const CFStringRef *MykCFURLIsSymbolicLinkKey
= NULL;
LOCALVAR blnr DidkCFURLIsSymbolicLinkKey = falseblnr;
LOCALFUNC blnr HaveMykCFURLIsSymbolicLinkKey(void)
{
if (! DidkCFURLIsSymbolicLinkKey) {
if (HaveApplicationServicesBun()) {
MykCFURLIsSymbolicLinkKey =
(const CFStringRef *)
CFBundleGetDataPointerForName(
AppServBunRef, CFSTR("kCFURLIsSymbolicLinkKey"));
}
DidkCFURLIsSymbolicLinkKey = trueblnr;
}
return (MykCFURLIsSymbolicLinkKey != NULL);
}
typedef CFDataRef (*CFURLCreateBookmarkDataFromFileProcPtr) (
CFAllocatorRef allocator, CFURLRef fileURL, CFErrorRef *errorRef);
LOCALVAR CFURLCreateBookmarkDataFromFileProcPtr
MyCFURLCreateBookmarkDataFromFile = NULL;
LOCALVAR blnr DidCFURLCreateBookmarkDataFromFile = falseblnr;
LOCALFUNC blnr HaveMyCFURLCreateBookmarkDataFromFile(void)
{
if (! DidCFURLCreateBookmarkDataFromFile) {
if (HaveApplicationServicesBun()) {
MyCFURLCreateBookmarkDataFromFile =
(CFURLCreateBookmarkDataFromFileProcPtr)
CFBundleGetFunctionPointerForName(AppServBunRef,
CFSTR("CFURLCreateBookmarkDataFromFile"));
}
DidCFURLCreateBookmarkDataFromFile = trueblnr;
}
return (MyCFURLCreateBookmarkDataFromFile != NULL);
}
typedef CFOptionFlags MyCFURLBookmarkResolutionOptions;
typedef CFURLRef (*CFURLCreateByResolvingBookmarkDataProcPtr) (
CFAllocatorRef allocator, CFDataRef bookmark,
MyCFURLBookmarkResolutionOptions options, CFURLRef relativeToURL,
CFArrayRef resourcePropertiesToInclude,
Boolean* isStale, CFErrorRef* error);
LOCALVAR CFURLCreateByResolvingBookmarkDataProcPtr
MyCFURLCreateByResolvingBookmarkData = NULL;
LOCALVAR blnr DidCFURLCreateByResolvingBookmarkData = falseblnr;
LOCALFUNC blnr HaveMyCFURLCreateByResolvingBookmarkData(void)
{
if (! DidCFURLCreateByResolvingBookmarkData) {
if (HaveApplicationServicesBun()) {
MyCFURLCreateByResolvingBookmarkData =
(CFURLCreateByResolvingBookmarkDataProcPtr)
CFBundleGetFunctionPointerForName(AppServBunRef,
CFSTR("CFURLCreateByResolvingBookmarkData"));
}
DidCFURLCreateByResolvingBookmarkData = trueblnr;
}
return (MyCFURLCreateByResolvingBookmarkData != NULL);
}
typedef boolean_t (*CGCursorIsVisibleProcPtr)(void);
LOCALVAR CGCursorIsVisibleProcPtr MyCGCursorIsVisible = NULL;
LOCALVAR blnr DidCGCursorIsVisible = falseblnr;
LOCALFUNC blnr HaveMyCGCursorIsVisible(void)
{
if (! DidCGCursorIsVisible) {
if (HaveApplicationServicesBun()) {
MyCGCursorIsVisible =
(CGCursorIsVisibleProcPtr)
CFBundleGetFunctionPointerForName(
AppServBunRef, CFSTR("CGCursorIsVisible"));
}
DidCGCursorIsVisible = trueblnr;
}
return (MyCGCursorIsVisible != NULL);
}
/* --- some simple utilities --- */
GLOBALOSGLUPROC MyMoveBytes(anyp srcPtr, anyp destPtr, si5b byteCount)
{
(void) memcpy((char *)destPtr, (char *)srcPtr, byteCount);
}
/* --- control mode and internationalization --- */
#define NeedCell2UnicodeMap 1
#include "INTLCHAR.h"
/* --- sending debugging info to file --- */
LOCALVAR NSString *myAppName = nil;
LOCALVAR NSString *MyDataPath = nil;
#if dbglog_HAVE
#define dbglog_ToStdErr 0
#if ! dbglog_ToStdErr
LOCALVAR FILE *dbglog_File = NULL;
#endif
LOCALFUNC blnr dbglog_open0(void)
{
#if dbglog_ToStdErr
return trueblnr;
#else
NSString *myLogPath = [MyDataPath
stringByAppendingPathComponent: @"dbglog.txt"];
const char *path = [myLogPath fileSystemRepresentation];
dbglog_File = fopen(path, "w");
return (NULL != dbglog_File);
#endif
}
LOCALPROC dbglog_write0(char *s, uimr L)
{
#if dbglog_ToStdErr
(void) fwrite(s, 1, L, stderr);
#else
if (NULL != dbglog_File) {
(void) fwrite(s, 1, L, dbglog_File);
}
#endif
}
LOCALPROC dbglog_close0(void)
{
#if ! dbglog_ToStdErr
if (NULL != dbglog_File) {
fclose(dbglog_File);
dbglog_File = NULL;
}
#endif
}
#endif
/* --- information about the environment --- */
#define WantColorTransValid 1
#include "COMOSGLU.h"
#define WantKeyboard_RemapMac 1
#include "PBUFSTDC.h"
#include "CONTROLM.h"
/* --- text translation --- */
LOCALPROC UniCharStrFromSubstCStr(int *L, unichar *x, char *s)
{
int i;
int L0;
ui3b ps[ClStrMaxLength];
ClStrFromSubstCStr(&L0, ps, s);
for (i = 0; i < L0; ++i) {
x[i] = Cell2UnicodeMap[ps[i]];
}
*L = L0;
}
LOCALFUNC NSString * NSStringCreateFromSubstCStr(char *s)
{
int L;
unichar x[ClStrMaxLength];
UniCharStrFromSubstCStr(&L, x, s);
return [NSString stringWithCharacters:x length:L];
}
#if IncludeSonyNameNew
LOCALFUNC blnr MacRomanFileNameToNSString(tPbuf i,
NSString **r)
{
ui3p p;
void *Buffer = PbufDat[i];
ui5b L = PbufSize[i];
p = (ui3p)malloc(L /* + 1 */);
if (p != NULL) {
NSData *d;
ui3b *p0 = (ui3b *)Buffer;
ui3b *p1 = (ui3b *)p;
if (L > 0) {
ui5b j = L;
do {
ui3b x = *p0++;
if (x < 32) {
x = '-';
} else if (x >= 128) {
} else {
switch (x) {
case '/':
case '<':
case '>':
case '|':
case ':':
x = '-';
default:
break;
}
}
*p1++ = x;
} while (--j > 0);
if ('.' == p[0]) {
p[0] = '-';
}
}
#if 0
*p1 = 0;
*r = [NSString stringWithCString:(char *)p
encoding:NSMacOSRomanStringEncoding];
/* only as of OS X 10.4 */
free(p);
#endif
d = [[NSData alloc] initWithBytesNoCopy:p length:L];
*r = [[[NSString alloc]
initWithData:d encoding:NSMacOSRomanStringEncoding]
autorelease];
[d release];
return trueblnr;
}
return falseblnr;
}
#endif
#if IncludeSonyGetName || IncludeHostTextClipExchange
LOCALFUNC tMacErr NSStringToRomanPbuf(NSString *string, tPbuf *r)
{
tMacErr v = mnvm_miscErr;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
#if 0
const char *s = [s0
cStringUsingEncoding: NSMacOSRomanStringEncoding];
ui5r L = strlen(s);
/* only as of OS X 10.4 */
#endif
#if 0
NSData *d0 = [string dataUsingEncoding: NSMacOSRomanStringEncoding];
#endif
NSData *d0 = [string dataUsingEncoding: NSMacOSRomanStringEncoding
allowLossyConversion: YES];
const void *s = [d0 bytes];
NSUInteger L = [d0 length];
if (NULL == s) {
v = mnvm_miscErr;
} else {
ui3p p = (ui3p)malloc(L);
if (NULL == p) {
v = mnvm_miscErr;
} else {
/* memcpy((char *)p, s, L); */
ui3b *p0 = (ui3b *)s;
ui3b *p1 = (ui3b *)p;
int i;
for (i = L; --i >= 0; ) {
ui3b v = *p0++;
if (10 == v) {
v = 13;
}
*p1++ = v;
}
v = PbufNewFromPtr(p, L, r);
}
}
[pool release];
return v;
}
#endif
/* --- drives --- */
LOCALFUNC blnr FindNamedChildPath(NSString *parentPath,
char *ChildName, NSString **childPath)
{
blnr v = falseblnr;
#if 0
NSString *ss = [NSString stringWithCString:s
encoding:NSASCIIStringEncoding];
/* only as of OS X 10.4 */
#endif
#if 0
NSData *d = [NSData dataWithBytes: ChildName
length: strlen(ChildName)];
NSString *ss = [[[NSString alloc]
initWithData:d encoding:NSASCIIStringEncoding]
autorelease];
#endif
NSString *ss = NSStringCreateFromSubstCStr(ChildName);
if (nil != ss) {
NSString *r = [parentPath stringByAppendingPathComponent: ss];
if (nil != r) {
*childPath = r;
v = trueblnr;
}
}
return v;
}
LOCALFUNC NSString *MyResolveAlias(NSString *filePath,
Boolean *targetIsFolder)
{
NSString *resolvedPath = nil;
CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
(CFStringRef)filePath, kCFURLPOSIXPathStyle, NO);
if (url != NULL) {
if (HaveMyCFURLCopyResourcePropertyForKey()
&& HaveMykCFURLIsAliasFileKey()
&& HaveMykCFURLIsSymbolicLinkKey()
&& HaveMyCFURLCreateBookmarkDataFromFile()
&& HaveMyCFURLCreateByResolvingBookmarkData())
{
BOOL isDir;
Boolean isStale;
CFBooleanRef is_alias_file = NULL;
CFBooleanRef is_symbolic_link = NULL;
CFDataRef bookmark = NULL;
CFURLRef resolvedurl = NULL;
if (MyCFURLCopyResourcePropertyForKey(url,
*MykCFURLIsAliasFileKey, &is_alias_file, NULL))
if (CFBooleanGetValue(is_alias_file))
if (MyCFURLCopyResourcePropertyForKey(url,
*MykCFURLIsSymbolicLinkKey, &is_symbolic_link, NULL))
if (! CFBooleanGetValue(is_symbolic_link))
if (NULL != (bookmark = MyCFURLCreateBookmarkDataFromFile(
kCFAllocatorDefault, url, NULL)))
if (NULL != (resolvedurl =
MyCFURLCreateByResolvingBookmarkData(
kCFAllocatorDefault,
bookmark,
0 /* MyCFURLBookmarkResolutionOptions options */,
NULL /* relativeToURL */,
NULL /* resourcePropertiesToInclude */,
&isStale,
NULL /* error */)))
if (nil != (resolvedPath =
(NSString *)CFURLCopyFileSystemPath(
resolvedurl, kCFURLPOSIXPathStyle)))
{
if ([[NSFileManager defaultManager]
fileExistsAtPath: resolvedPath isDirectory: &isDir])
{
*targetIsFolder = isDir;
} else
{
*targetIsFolder = FALSE;
}
[resolvedPath autorelease];
}
if (NULL != resolvedurl) {
CFRelease(resolvedurl);
}
if (NULL != bookmark) {
CFRelease(bookmark);
}
if (NULL != is_alias_file) {
CFRelease(is_alias_file);
}
if (NULL != is_symbolic_link) {
CFRelease(is_symbolic_link);
}
} else {
FSRef fsRef;
Boolean wasAliased;
if (CFURLGetFSRef(url, &fsRef)) {
/*
FSResolveAliasFile deprecated in 10.8
*/
if ((FSResolveAliasFile(&fsRef,
TRUE /*resolveAliasChains*/,
targetIsFolder, &wasAliased) == noErr)
&& wasAliased)
{
CFURLRef resolvedurl =
CFURLCreateFromFSRef(kCFAllocatorDefault,
&fsRef);
if (resolvedurl != NULL) {
resolvedPath =
(NSString *)CFURLCopyFileSystemPath(
resolvedurl, kCFURLPOSIXPathStyle);
[resolvedPath autorelease];
CFRelease(resolvedurl);
}
}
}
}
CFRelease(url);
}
return resolvedPath;
}
LOCALFUNC blnr FindNamedChildDirPath(NSString *parentPath,
char *ChildName, NSString **childPath)
{
NSString *r;
BOOL isDir;
Boolean isDirectory;
blnr v = falseblnr;
if (FindNamedChildPath(parentPath, ChildName, &r))
if ([[NSFileManager defaultManager]
fileExistsAtPath:r isDirectory: &isDir])
{
if (isDir) {
*childPath = r;
v = trueblnr;
} else {
NSString *RslvPath = MyResolveAlias(r, &isDirectory);
if (nil != RslvPath) {
if (isDirectory) {
*childPath = RslvPath;
v = trueblnr;
}
}
}
}
return v;
}
LOCALFUNC blnr FindNamedChildFilePath(NSString *parentPath,
char *ChildName, NSString **childPath)
{
NSString *r;
BOOL isDir;
Boolean isDirectory;
blnr v = falseblnr;
if (FindNamedChildPath(parentPath, ChildName, &r))
if ([[NSFileManager defaultManager]
fileExistsAtPath:r isDirectory: &isDir])
{
if (! isDir) {
NSString *RslvPath = MyResolveAlias(r, &isDirectory);
if (nil != RslvPath) {
if (! isDirectory) {
*childPath = RslvPath;
v = trueblnr;
}
} else {
*childPath = r;
v = trueblnr;
}
}
}
return v;
}
#define NotAfileRef NULL
LOCALVAR FILE *Drives[NumDrives]; /* open disk image files */
#if IncludeSonyGetName || IncludeSonyNew
LOCALVAR NSString *DriveNames[NumDrives];
#endif
LOCALPROC InitDrives(void)
{
/*
This isn't really needed, Drives[i] and DriveNames[i]
need not have valid values when not vSonyIsInserted[i].
*/
tDrive i;
for (i = 0; i < NumDrives; ++i) {
Drives[i] = NotAfileRef;
#if IncludeSonyGetName || IncludeSonyNew
DriveNames[i] = nil;
#endif
}
}
GLOBALOSGLUFUNC tMacErr vSonyTransfer(blnr IsWrite, ui3p Buffer,
tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count,
ui5r *Sony_ActCount)
{
tMacErr err = mnvm_miscErr;
FILE *refnum = Drives[Drive_No];
ui5r NewSony_Count = 0;
if (0 == fseek(refnum, Sony_Start, SEEK_SET)) {
if (IsWrite) {
NewSony_Count = fwrite(Buffer, 1, Sony_Count, refnum);
} else {
NewSony_Count = fread(Buffer, 1, Sony_Count, refnum);
}
if (NewSony_Count == Sony_Count) {
err = mnvm_noErr;
}
}
if (nullpr != Sony_ActCount) {
*Sony_ActCount = NewSony_Count;
}
return err; /*& figure out what really to return &*/
}
GLOBALOSGLUFUNC tMacErr vSonyGetSize(tDrive Drive_No, ui5r *Sony_Count)
{
tMacErr err = mnvm_miscErr;
FILE *refnum = Drives[Drive_No];
long v;
if (0 == fseek(refnum, 0, SEEK_END)) {
v = ftell(refnum);
if (v >= 0) {
*Sony_Count = v;
err = mnvm_noErr;
}
}
return err; /*& figure out what really to return &*/
}
#ifndef HaveAdvisoryLocks
#define HaveAdvisoryLocks 1
#endif
/*
What is the difference between fcntl(fd, F_SETLK ...
and flock(fd ... ?
*/
#if HaveAdvisoryLocks
LOCALFUNC blnr MyLockFile(FILE *refnum)
{
blnr IsOk = falseblnr;
#if 0
struct flock fl;
int fd = fileno(refnum);
fl.l_start = 0; /* starting offset */
fl.l_len = 0; /* len = 0 means until end of file */
/* fl.pid_t l_pid; */ /* lock owner, don't need to set */
fl.l_type = F_WRLCK; /* lock type: read/write, etc. */
fl.l_whence = SEEK_SET; /* type of l_start */
if (-1 == fcntl(fd, F_SETLK, &fl)) {
MacMsg(kStrImageInUseTitle, kStrImageInUseMessage,
falseblnr);
} else {
IsOk = trueblnr;
}
#else
int fd = fileno(refnum);
if (-1 == flock(fd, LOCK_EX | LOCK_NB)) {
if (EWOULDBLOCK == errno) {
/* already locked */
MacMsg(kStrImageInUseTitle, kStrImageInUseMessage,
falseblnr);
} else
{
/*
Failed for other reasons, such as unsupported
for this volume.
Don't prevent opening.
*/
IsOk = trueblnr;
}
} else {
IsOk = trueblnr;
}
#endif
return IsOk;
}
#endif
#if HaveAdvisoryLocks
LOCALPROC MyUnlockFile(FILE *refnum)
{
#if 0
struct flock fl;
int fd = fileno(refnum);
fl.l_start = 0; /* starting offset */
fl.l_len = 0; /* len = 0 means until end of file */
/* fl.pid_t l_pid; */ /* lock owner, don't need to set */
fl.l_type = F_UNLCK; /* lock type: read/write, etc. */
fl.l_whence = SEEK_SET; /* type of l_start */
if (-1 == fcntl(fd, F_SETLK, &fl)) {
/* an error occurred */
}
#else
int fd = fileno(refnum);
if (-1 == flock(fd, LOCK_UN)) {
}
#endif
}
#endif
LOCALFUNC tMacErr vSonyEject0(tDrive Drive_No, blnr deleteit)
{
FILE *refnum = Drives[Drive_No];
DiskEjectedNotify(Drive_No);
#if HaveAdvisoryLocks
MyUnlockFile(refnum);
#endif
fclose(refnum);
Drives[Drive_No] = NotAfileRef; /* not really needed */
#if IncludeSonyGetName || IncludeSonyNew
{
NSString *filePath = DriveNames[Drive_No];
if (NULL != filePath) {
if (deleteit) {
NSAutoreleasePool *pool =
[[NSAutoreleasePool alloc] init];
const char *s = [filePath fileSystemRepresentation];
remove(s);
[pool release];
}
[filePath release];
DriveNames[Drive_No] = NULL; /* not really needed */
}
}
#endif
return mnvm_noErr;
}
GLOBALOSGLUFUNC tMacErr vSonyEject(tDrive Drive_No)
{
return vSonyEject0(Drive_No, falseblnr);
}
#if IncludeSonyNew
GLOBALOSGLUFUNC tMacErr vSonyEjectDelete(tDrive Drive_No)
{
return vSonyEject0(Drive_No, trueblnr);
}
#endif
LOCALPROC UnInitDrives(void)
{
tDrive i;
for (i = 0; i < NumDrives; ++i) {
if (vSonyIsInserted(i)) {
(void) vSonyEject(i);
}
}
}
#if IncludeSonyGetName
GLOBALOSGLUFUNC tMacErr vSonyGetName(tDrive Drive_No, tPbuf *r)
{
tMacErr v = mnvm_miscErr;
NSString *filePath = DriveNames[Drive_No];
if (NULL != filePath) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *s0 = [filePath lastPathComponent];
v = NSStringToRomanPbuf(s0, r);
[pool release];
}
return v;
}
#endif
LOCALFUNC blnr Sony_Insert0(FILE *refnum, blnr locked,
NSString *filePath)
{
tDrive Drive_No;
blnr IsOk = falseblnr;
if (! FirstFreeDisk(&Drive_No)) {
MacMsg(kStrTooManyImagesTitle, kStrTooManyImagesMessage,
falseblnr);
} else {
/* printf("Sony_Insert0 %d\n", (int)Drive_No); */
#if HaveAdvisoryLocks
if (locked || MyLockFile(refnum))
#endif
{
Drives[Drive_No] = refnum;
DiskInsertNotify(Drive_No, locked);
#if IncludeSonyGetName || IncludeSonyNew
DriveNames[Drive_No] = [filePath retain];
#endif
IsOk = trueblnr;
}
}
if (! IsOk) {
fclose(refnum);
}
return IsOk;
}
LOCALFUNC blnr Sony_Insert1(NSString *filePath, blnr silentfail)
{
/* const char *drivepath = [filePath UTF8String]; */
const char *drivepath = [filePath fileSystemRepresentation];
blnr locked = falseblnr;
/* printf("Sony_Insert1 %s\n", drivepath); */
FILE *refnum = fopen(drivepath, "rb+");
if (NULL == refnum) {
locked = trueblnr;
refnum = fopen(drivepath, "rb");
}
if (NULL == refnum) {
if (! silentfail) {
MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr);
}
} else {
return Sony_Insert0(refnum, locked, filePath);
}
return falseblnr;
}
LOCALFUNC blnr Sony_Insert2(char *s)
{
NSString *sPath;
if (! FindNamedChildFilePath(MyDataPath, s, &sPath)) {
return falseblnr;
} else {
return Sony_Insert1(sPath, trueblnr);
}
}
LOCALFUNC tMacErr LoadMacRomPath(NSString *RomPath)
{
FILE *ROM_File;
int File_Size;
tMacErr err = mnvm_fnfErr;
const char *path = [RomPath fileSystemRepresentation];
ROM_File = fopen(path, "rb");
if (NULL != ROM_File) {
File_Size = fread(ROM, 1, kROM_Size, ROM_File);
if (kROM_Size != File_Size) {
if (feof(ROM_File)) {
MacMsgOverride(kStrShortROMTitle,
kStrShortROMMessage);
err = mnvm_eofErr;
} else {
MacMsgOverride(kStrNoReadROMTitle,
kStrNoReadROMMessage);
err = mnvm_miscErr;
}
} else {
err = ROM_IsValid();
}
fclose(ROM_File);
}
return err;
}
LOCALFUNC blnr Sony_Insert1a(NSString *filePath)
{
blnr v;
if (! ROM_loaded) {
v = (mnvm_noErr == LoadMacRomPath(filePath));
} else {
v = Sony_Insert1(filePath, falseblnr);
}
return v;
}
LOCALPROC Sony_ResolveInsert(NSString *filePath)
{
Boolean isDirectory;
NSString *RslvPath = MyResolveAlias(filePath, &isDirectory);
if (nil != RslvPath) {
if (! isDirectory) {
(void) Sony_Insert1a(RslvPath);
}
} else {
(void) Sony_Insert1a(filePath);
}
}
LOCALFUNC blnr Sony_InsertIth(int i)
{
blnr v;
if ((i > 9) || ! FirstFreeDisk(nullpr)) {
v = falseblnr;
} else {
char s[] = "disk?.dsk";
s[4] = '0' + i;
v = Sony_Insert2(s);
}
return v;
}
LOCALFUNC blnr LoadInitialImages(void)
{
if (! AnyDiskInserted()) {
int i;
for (i = 1; Sony_InsertIth(i); ++i) {
/* stop on first error (including file not found) */
}
}
return trueblnr;
}
#if IncludeSonyNew
LOCALFUNC blnr WriteZero(FILE *refnum, ui5b L)
{
#define ZeroBufferSize 2048
ui5b i;
ui3b buffer[ZeroBufferSize];
memset(&buffer, 0, ZeroBufferSize);
while (L > 0) {
i = (L > ZeroBufferSize) ? ZeroBufferSize : L;
if (fwrite(buffer, 1, i, refnum) != i) {
return falseblnr;
}
L -= i;
}
return trueblnr;
}
#endif
#if IncludeSonyNew
LOCALPROC MakeNewDisk0(ui5b L, NSString *sPath)
{
blnr IsOk = falseblnr;
const char *drivepath = [sPath fileSystemRepresentation];
FILE *refnum = fopen(drivepath, "wb+");
if (NULL == refnum) {
MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr);
} else {
if (WriteZero(refnum, L)) {
IsOk = Sony_Insert0(refnum, falseblnr, sPath);
refnum = NULL;
}
if (refnum != NULL) {
fclose(refnum);
}
if (! IsOk) {
(void) remove(drivepath);
}
}
}
#endif
/* --- ROM --- */
LOCALFUNC tMacErr LoadMacRomFrom(NSString *parentPath)
{
NSString *RomPath;
tMacErr err = mnvm_fnfErr;
if (FindNamedChildFilePath(parentPath, RomFileName, &RomPath)) {
err = LoadMacRomPath(RomPath);
}
return err;
}
LOCALFUNC tMacErr LoadMacRomFromAppDir(void)
{
return LoadMacRomFrom(MyDataPath);
}
LOCALFUNC tMacErr LoadMacRomFromPrefDir(void)
{
NSString *PrefsPath;
NSString *GryphelPath;
NSString *RomsPath;
tMacErr err = mnvm_fnfErr;
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSLibraryDirectory, NSUserDomainMask, YES);
if ((nil != paths) && ([paths count] > 0))
{
NSString *LibPath = [paths objectAtIndex:0];
if (FindNamedChildDirPath(LibPath, "Preferences", &PrefsPath))
if (FindNamedChildDirPath(PrefsPath, "Gryphel", &GryphelPath))
if (FindNamedChildDirPath(GryphelPath, "mnvm_rom", &RomsPath))
{
err = LoadMacRomFrom(RomsPath);
}
}
return err;
}
LOCALFUNC tMacErr LoadMacRomFromGlobalDir(void)
{
NSString *GryphelPath;
NSString *RomsPath;
tMacErr err = mnvm_fnfErr;
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSApplicationSupportDirectory, NSLocalDomainMask, NO);
if ((nil != paths) && ([paths count] > 0))
{
NSString *LibPath = [paths objectAtIndex:0];
if (FindNamedChildDirPath(LibPath, "Gryphel", &GryphelPath))
if (FindNamedChildDirPath(GryphelPath, "mnvm_rom", &RomsPath))
{
err = LoadMacRomFrom(RomsPath);
}
}
return err;
}
LOCALFUNC blnr LoadMacRom(void)
{
tMacErr err;
if (mnvm_fnfErr == (err = LoadMacRomFromAppDir()))
if (mnvm_fnfErr == (err = LoadMacRomFromPrefDir()))
if (mnvm_fnfErr == (err = LoadMacRomFromGlobalDir()))
{
}
return trueblnr; /* keep launching Mini vMac, regardless */
}
#if IncludeHostTextClipExchange
GLOBALOSGLUFUNC tMacErr HTCEexport(tPbuf i)
{
void *Buffer;
ui5r L;
tMacErr err = mnvm_miscErr;
PbufKillToPtr(&Buffer, &L, i);
if (L > 0) {
int j;
ui3b *p = (ui3b *)Buffer;
for (j = L; --j >= 0; ) {
ui3b v = *p;
if (13 == v) {
*p = 10;
}
++p;
}
}
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSData *d = [[NSData alloc]
initWithBytesNoCopy: Buffer length: L];
/* NSData *d = [NSData dataWithBytes: Buffer length: L]; */
NSString *ss = [[[NSString alloc]
initWithData:d encoding:NSMacOSRomanStringEncoding]
autorelease];
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
NSArray *newTypes =
[NSArray arrayWithObject: NSStringPboardType];
(void) [pasteboard declareTypes: newTypes owner: nil];
if ([pasteboard setString: ss forType: NSStringPboardType]) {
err = mnvm_noErr;
}
[d release];
[pool release];
}
return err;
}
#endif
#if IncludeHostTextClipExchange
GLOBALOSGLUFUNC tMacErr HTCEimport(tPbuf *r)
{
tMacErr err = mnvm_miscErr;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
NSArray *supportedTypes = [NSArray
arrayWithObject: NSStringPboardType];
NSString *available = [pasteboard
availableTypeFromArray: supportedTypes];
if (nil != available) {
NSString *string = [pasteboard
stringForType: NSStringPboardType];
if (nil != string) {
err = NSStringToRomanPbuf(string, r);
}
}
[pool release];
return err;
}
#endif
#if EmLocalTalk
#include "BPFILTER.h"
#endif
#define UseCGContextDrawImage 0
LOCALVAR NSWindow *MyWindow = nil;
LOCALVAR NSView *MyNSview = nil;
#if UseCGContextDrawImage
LOCALVAR NSGraphicsContext *MyNSgfxContext = nil;
LOCALVAR CGContextRef MyCGcontext = nil;
LOCALVAR void *MyPixels = NULL;
LOCALVAR ui4b MyPitch;
LOCALVAR ui3b MyBytesPerPixel;
#endif
LOCALVAR NSOpenGLContext *MyNSOpnGLCntxt = nil;
LOCALVAR short GLhOffset;
LOCALVAR short GLvOffset;
/* OpenGL coordinates of upper left point of drawing area */
LOCALPROC MyHideCursor(void)
{
[NSCursor hide];
}
LOCALPROC MyShowCursor(void)
{
if (nil != MyWindow) {
[MyWindow invalidateCursorRectsForView:
MyNSview];
}
#if 0
[cursor->nscursor performSelectorOnMainThread: @selector(set)
withObject: nil waitUntilDone: NO];
#endif
#if 0
[[NSCursor arrowCursor] set];
#endif
[NSCursor unhide];
}
#if EnableMoveMouse
LOCALFUNC CGPoint QZ_PrivateSDLToCG(NSPoint *p)
{
CGPoint cgp;
*p = [MyNSview convertPoint: *p toView: nil];
p->y = [MyNSview frame].size.height - p->y;
*p = [MyWindow convertBaseToScreen: *p];
cgp.x = p->x;
cgp.y = CGDisplayPixelsHigh(kCGDirectMainDisplay)
- p->y;
return cgp;
}
#endif
LOCALPROC QZ_GetMouseLocation(NSPoint *p)
{
/* incorrect while window is being dragged */
*p = [NSEvent mouseLocation]; /* global coordinates */
if (nil != MyWindow) {
*p = [MyWindow convertScreenToBase: *p];
}
*p = [MyNSview convertPoint: *p fromView: nil];
p->y = [MyNSview frame].size.height - p->y;
}
/* --- keyboard --- */
LOCALVAR NSUInteger MyCurrentMods = 0;
/*
Apple documentation says:
"The lower 16 bits of the modifier flags are reserved
for device-dependent bits."
observed to be:
*/
#define My_NSLShiftKeyMask 0x0002
#define My_NSRShiftKeyMask 0x0004
#define My_NSLControlKeyMask 0x0001
#define My_NSRControlKeyMask 0x2000
#define My_NSLCommandKeyMask 0x0008
#define My_NSRCommandKeyMask 0x0010
#define My_NSLOptionKeyMask 0x0020
#define My_NSROptionKeyMask 0x0040
/*
Avoid using the above unless it is
really needed.
*/
LOCALPROC MyUpdateKeyboardModifiers(NSUInteger newMods)
{
NSUInteger changeMask = MyCurrentMods ^ newMods;
if (0 != changeMask) {
if (0 != (changeMask & NSAlphaShiftKeyMask)) {
Keyboard_UpdateKeyMap2(MKC_formac_CapsLock,
0 != (newMods & NSAlphaShiftKeyMask));
}
#if MKC_formac_RShift == MKC_formac_Shift
if (0 != (changeMask & NSShiftKeyMask)) {
Keyboard_UpdateKeyMap2(MKC_formac_Shift,
0 != (newMods & NSShiftKeyMask));
}
#else
if (0 != (changeMask & My_NSLShiftKeyMask)) {
Keyboard_UpdateKeyMap2(MKC_formac_Shift,
0 != (newMods & My_NSLShiftKeyMask));
}
if (0 != (changeMask & My_NSRShiftKeyMask)) {
Keyboard_UpdateKeyMap2(MKC_formac_RShift,
0 != (newMods & My_NSRShiftKeyMask));
}
#endif
#if MKC_formac_RControl == MKC_formac_Control
if (0 != (changeMask & NSControlKeyMask)) {
Keyboard_UpdateKeyMap2(MKC_formac_Control,
0 != (newMods & NSControlKeyMask));
}
#else
if (0 != (changeMask & My_NSLControlKeyMask)) {
Keyboard_UpdateKeyMap2(MKC_formac_Control,
0 != (newMods & My_NSLControlKeyMask));
}
if (0 != (changeMask & My_NSRControlKeyMask)) {
Keyboard_UpdateKeyMap2(MKC_formac_RControl,
0 != (newMods & My_NSRControlKeyMask));
}
#endif
#if MKC_formac_RCommand == MKC_formac_Command
if (0 != (changeMask & NSCommandKeyMask)) {
Keyboard_UpdateKeyMap2(MKC_formac_Command,
0 != (newMods & NSCommandKeyMask));
}
#else
if (0 != (changeMask & My_NSLCommandKeyMask)) {
Keyboard_UpdateKeyMap2(MKC_formac_Command,
0 != (newMods & My_NSLCommandKeyMask));
}
if (0 != (changeMask & My_NSRCommandKeyMask)) {
Keyboard_UpdateKeyMap2(MKC_formac_RCommand,
0 != (newMods & My_NSRCommandKeyMask));
}
#endif
#if MKC_formac_ROption == MKC_formac_Option
if (0 != (changeMask & NSAlternateKeyMask)) {
Keyboard_UpdateKeyMap2(MKC_formac_Option,
0 != (newMods & NSAlternateKeyMask));
}
#else
if (0 != (changeMask & My_NSLOptionKeyMask)) {
Keyboard_UpdateKeyMap2(MKC_formac_Option,
0 != (newMods & My_NSLOptionKeyMask));
}
if (0 != (changeMask & My_NSROptionKeyMask)) {
Keyboard_UpdateKeyMap2(MKC_formac_ROption,
0 != (newMods & My_NSROptionKeyMask));
}
#endif
MyCurrentMods = newMods;
}
}
/* --- mouse --- */
/* cursor hiding */
LOCALVAR blnr WantCursorHidden = falseblnr;
#if MayFullScreen
LOCALVAR short hOffset;
/* number of pixels to left of drawing area in window */
LOCALVAR short vOffset;
/* number of pixels above drawing area in window */
#endif
#if MayFullScreen
LOCALVAR blnr GrabMachine = falseblnr;
#endif
#if VarFullScreen
LOCALVAR blnr UseFullScreen = (0 != WantInitFullScreen);
#endif
#if EnableMagnify
LOCALVAR blnr UseMagnify = (0 != WantInitMagnify);
#endif
LOCALVAR blnr gBackgroundFlag = falseblnr;
LOCALVAR blnr CurSpeedStopped = trueblnr;
#if EnableMagnify
#define MaxScale MyWindowScale
#else
#define MaxScale 1
#endif
LOCALVAR blnr HaveCursorHidden = falseblnr;
LOCALPROC ForceShowCursor(void)
{
if (HaveCursorHidden) {
HaveCursorHidden = falseblnr;
MyShowCursor();
}
}
/* cursor moving */
#if EnableMoveMouse
LOCALFUNC blnr MyMoveMouse(si4b h, si4b v)
{
NSPoint p;
CGPoint cgp;
#if VarFullScreen
if (UseFullScreen)
#endif
#if MayFullScreen
{
h -= ViewHStart;
v -= ViewVStart;
}
#endif
#if EnableMagnify
if (UseMagnify) {
h *= MyWindowScale;
v *= MyWindowScale;
}
#endif
#if VarFullScreen
if (UseFullScreen)
#endif
#if MayFullScreen
{
h += hOffset;
v += vOffset;
}
#endif
p = NSMakePoint(h, v);
cgp = QZ_PrivateSDLToCG(&p);
/*
this is the magic call that fixes cursor "freezing"
after warp
*/
CGAssociateMouseAndMouseCursorPosition(0);
CGWarpMouseCursorPosition(cgp);
CGAssociateMouseAndMouseCursorPosition(1);
#if 0
if (noErr != CGSetLocalEventsSuppressionInterval(0.0)) {
/* don't use MacMsg which can call MyMoveMouse */
}
if (noErr != CGWarpMouseCursorPosition(cgp)) {
/* don't use MacMsg which can call MyMoveMouse */
}
#endif
return trueblnr;
}
#endif
#if EnableFSMouseMotion
LOCALPROC AdjustMouseMotionGrab(void)
{
#if MayFullScreen
if (GrabMachine) {
/*
if magnification changes, need to reset,
even if HaveMouseMotion already true
*/
if (MyMoveMouse(ViewHStart + (ViewHSize / 2),
ViewVStart + (ViewVSize / 2)))
{
SavedMouseH = ViewHStart + (ViewHSize / 2);
SavedMouseV = ViewVStart + (ViewVSize / 2);
HaveMouseMotion = trueblnr;
}
} else
#endif
{
if (HaveMouseMotion) {
(void) MyMoveMouse(CurMouseH, CurMouseV);
HaveMouseMotion = falseblnr;
}
}
}
#endif
#if EnableFSMouseMotion
LOCALPROC MyMouseConstrain(void)
{
si4b shiftdh;
si4b shiftdv;
if (SavedMouseH < ViewHStart + (ViewHSize / 4)) {
shiftdh = ViewHSize / 2;
} else if (SavedMouseH > ViewHStart + ViewHSize - (ViewHSize / 4)) {
shiftdh = - ViewHSize / 2;
} else {
shiftdh = 0;
}
if (SavedMouseV < ViewVStart + (ViewVSize / 4)) {
shiftdv = ViewVSize / 2;
} else if (SavedMouseV > ViewVStart + ViewVSize - (ViewVSize / 4)) {
shiftdv = - ViewVSize / 2;
} else {
shiftdv = 0;
}
if ((shiftdh != 0) || (shiftdv != 0)) {
SavedMouseH += shiftdh;
SavedMouseV += shiftdv;
if (! MyMoveMouse(SavedMouseH, SavedMouseV)) {
HaveMouseMotion = falseblnr;
}
}
}
#endif
/* cursor state */
LOCALPROC MousePositionNotify(int NewMousePosh, int NewMousePosv)
{
blnr ShouldHaveCursorHidden = trueblnr;
#if VarFullScreen
if (UseFullScreen)
#endif
#if MayFullScreen
{
NewMousePosh -= hOffset;
NewMousePosv -= vOffset;
}
#endif
#if EnableMagnify
if (UseMagnify) {
NewMousePosh /= MyWindowScale;
NewMousePosv /= MyWindowScale;
}
#endif
#if VarFullScreen
if (UseFullScreen)
#endif
#if MayFullScreen
{
NewMousePosh += ViewHStart;
NewMousePosv += ViewVStart;
}
#endif
#if EnableFSMouseMotion
if (HaveMouseMotion) {
MyMousePositionSetDelta(NewMousePosh - SavedMouseH,
NewMousePosv - SavedMouseV);
SavedMouseH = NewMousePosh;
SavedMouseV = NewMousePosv;
} else
#endif
{
if (NewMousePosh < 0) {
NewMousePosh = 0;
ShouldHaveCursorHidden = falseblnr;
} else if (NewMousePosh >= vMacScreenWidth) {
NewMousePosh = vMacScreenWidth - 1;
ShouldHaveCursorHidden = falseblnr;
}
if (NewMousePosv < 0) {
NewMousePosv = 0;
ShouldHaveCursorHidden = falseblnr;
} else if (NewMousePosv >= vMacScreenHeight) {
NewMousePosv = vMacScreenHeight - 1;
ShouldHaveCursorHidden = falseblnr;
}
#if VarFullScreen
if (UseFullScreen)
#endif
#if MayFullScreen
{
ShouldHaveCursorHidden = trueblnr;
}
#endif
/* if (ShouldHaveCursorHidden || CurMouseButton) */
/*
for a game like arkanoid, would like mouse to still
move even when outside window in one direction
*/
MyMousePositionSet(NewMousePosh, NewMousePosv);
}
WantCursorHidden = ShouldHaveCursorHidden;
}
LOCALPROC CheckMouseState(void)
{
/*
incorrect while window is being dragged
so only call when needed.
*/
NSPoint p;
QZ_GetMouseLocation(&p);
MousePositionNotify((int) p.x, (int) p.y);
}
LOCALVAR blnr gTrueBackgroundFlag = falseblnr;
LOCALVAR ui3p ScalingBuff = nullpr;
LOCALVAR ui3p CLUT_final;
#define CLUT_finalsz1 (256 * 8)
#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
#define CLUT_finalClrSz (256 << (5 - vMacScreenDepth))
#define CLUT_finalsz ((CLUT_finalClrSz > CLUT_finalsz1) \
? CLUT_finalClrSz : CLUT_finalsz1)
#else
#define CLUT_finalsz CLUT_finalsz1
#endif
#define ScrnMapr_DoMap UpdateBWLuminanceCopy
#define ScrnMapr_Src GetCurDrawBuff()
#define ScrnMapr_Dst ScalingBuff
#define ScrnMapr_SrcDepth 0
#define ScrnMapr_DstDepth 3
#define ScrnMapr_Map CLUT_final
#include "SCRNMAPR.h"
#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
#define ScrnMapr_DoMap UpdateMappedColorCopy
#define ScrnMapr_Src GetCurDrawBuff()
#define ScrnMapr_Dst ScalingBuff
#define ScrnMapr_SrcDepth vMacScreenDepth
#define ScrnMapr_DstDepth 5
#define ScrnMapr_Map CLUT_final
#include "SCRNMAPR.h"
#endif
#if vMacScreenDepth >= 4
#define ScrnTrns_DoTrans UpdateTransColorCopy
#define ScrnTrns_Src GetCurDrawBuff()
#define ScrnTrns_Dst ScalingBuff
#define ScrnTrns_SrcDepth vMacScreenDepth
#define ScrnTrns_DstDepth 5
#define ScrnTrns_DstZLo 1
#include "SCRNTRNS.h"
#endif
LOCALPROC UpdateLuminanceCopy(si4b top, si4b left,
si4b bottom, si4b right)
{
int i;
#if 0 != vMacScreenDepth
if (UseColorMode) {
#if vMacScreenDepth < 4
if (! ColorTransValid) {
int j;
int k;
ui5p p4;
p4 = (ui5p)CLUT_final;
for (i = 0; i < 256; ++i) {
for (k = 1 << (3 - vMacScreenDepth); --k >= 0; ) {
j = (i >> (k << vMacScreenDepth)) & (CLUT_size - 1);
*p4++ = (((long)CLUT_reds[j] & 0xFF00) << 16)
| (((long)CLUT_greens[j] & 0xFF00) << 8)
| ((long)CLUT_blues[j] & 0xFF00);
}
}
ColorTransValid = trueblnr;
}
UpdateMappedColorCopy(top, left, bottom, right);
#else
UpdateTransColorCopy(top, left, bottom, right);
#endif
} else
#endif
{
if (! ColorTransValid) {
int k;
ui3p p4 = (ui3p)CLUT_final;
for (i = 0; i < 256; ++i) {
for (k = 8; --k >= 0; ) {
*p4++ = ((i >> k) & 0x01) - 1;
}
}
ColorTransValid = trueblnr;
}
UpdateBWLuminanceCopy(top, left, bottom, right);
}
}
LOCALPROC MyDrawWithOpenGL(ui4r top, ui4r left, ui4r bottom, ui4r right)
{
if (nil == MyNSOpnGLCntxt) {
/* oops */
} else {
si4b top2;
si4b left2;
#if VarFullScreen
if (UseFullScreen)
#endif
#if MayFullScreen
{
if (top < ViewVStart) {
top = ViewVStart;
}
if (left < ViewHStart) {
left = ViewHStart;
}
if (bottom > ViewVStart + ViewVSize) {
bottom = ViewVStart + ViewVSize;
}
if (right > ViewHStart + ViewHSize) {
right = ViewHStart + ViewHSize;
}
if ((top >= bottom) || (left >= right)) {
goto label_exit;
}
}
#endif
top2 = top;
left2 = left;
#if VarFullScreen
if (UseFullScreen)
#endif
#if MayFullScreen
{
left2 -= ViewHStart;
top2 -= ViewVStart;
}
#endif
#if EnableMagnify
if (UseMagnify) {
top2 *= MyWindowScale;
left2 *= MyWindowScale;
}
#endif
[MyNSOpnGLCntxt makeCurrentContext];
UpdateLuminanceCopy(top, left, bottom, right);
glRasterPos2i(GLhOffset + left2, GLvOffset - top2);
#if 0 != vMacScreenDepth
if (UseColorMode) {
glDrawPixels(right - left,
bottom - top,
GL_RGBA,
GL_UNSIGNED_INT_8_8_8_8,
ScalingBuff + (left + top * vMacScreenWidth) * 4
);
} else
#endif
{
glDrawPixels(right - left,
bottom - top,
GL_LUMINANCE,
GL_UNSIGNED_BYTE,
ScalingBuff + (left + top * vMacScreenWidth)
);
}
#if 0 /* a very quick and dirty check of where drawing */
glDrawPixels(right - left,
1,
GL_RED,
GL_UNSIGNED_BYTE,
ScalingBuff + (left + top * vMacScreenWidth)
);
glDrawPixels(1,
bottom - top,
GL_RED,
GL_UNSIGNED_BYTE,
ScalingBuff + (left + top * vMacScreenWidth)
);
#endif
glFlush();
}
#if MayFullScreen
label_exit:
;
#endif
}
#if UseCGContextDrawImage
LOCALPROC SDL_UpdateRect(si5b x, si5b y, ui5b w, ui5b h)
{
if ([MyWindow isMiniaturized]) {
/* Do nothing if miniaturized */
} else {
NSGraphicsContext *ctx = [NSGraphicsContext currentContext];
if (ctx != MyNSgfxContext) {
/* uhoh, you might be rendering from another thread... */
[NSGraphicsContext
setCurrentContext: MyNSgfxContext];
ctx = MyNSgfxContext;
}
CGContextRef cgc = (CGContextRef) [ctx graphicsPort];
CGContextFlush(MyCGcontext);
CGImageRef image = CGBitmapContextCreateImage(
MyCGcontext);
CGRect rectangle = CGRectMake(0, 0,
[MyNSview frame].size.width,
[MyNSview frame].size.height);
CGContextDrawImage(cgc, rectangle, image);
CGImageRelease(image);
CGContextFlush(cgc);
}
}
#endif
/* --- time, date, location --- */
#define dbglog_TimeStuff (0 && dbglog_HAVE)
LOCALVAR ui5b TrueEmulatedTime = 0;
LOCALVAR NSTimeInterval LatestTime;
LOCALVAR NSTimeInterval NextTickChangeTime;
#define MyTickDuration (1.0 / 60.14742)
LOCALVAR ui5b NewMacDateInSeconds;
LOCALVAR blnr EmulationWasInterrupted = falseblnr;
LOCALPROC UpdateTrueEmulatedTime(void)
{
NSTimeInterval TimeDiff;
LatestTime = [NSDate timeIntervalSinceReferenceDate];
TimeDiff = LatestTime - NextTickChangeTime;
if (TimeDiff >= 0.0) {
if (TimeDiff > 16 * MyTickDuration) {
/* emulation interrupted, forget it */
++TrueEmulatedTime;
NextTickChangeTime = LatestTime + MyTickDuration;
EmulationWasInterrupted = trueblnr;
#if dbglog_TimeStuff
dbglog_writelnNum("emulation interrupted",
TrueEmulatedTime);
#endif
} else {
do {
#if 0 && dbglog_TimeStuff
dbglog_writeln("got next tick");
#endif
++TrueEmulatedTime;
TimeDiff -= MyTickDuration;
NextTickChangeTime += MyTickDuration;
} while (TimeDiff >= 0.0);
}
} else if (TimeDiff < (-16 * MyTickDuration)) {
/* clock set back, reset */
#if dbglog_TimeStuff
dbglog_writeln("clock set back");
#endif
NextTickChangeTime = LatestTime + MyTickDuration;
}
}
LOCALVAR ui5b MyDateDelta;
LOCALFUNC blnr CheckDateTime(void)
{
NewMacDateInSeconds = ((ui5b)LatestTime) + MyDateDelta;
if (CurMacDateInSeconds != NewMacDateInSeconds) {
CurMacDateInSeconds = NewMacDateInSeconds;
return trueblnr;
} else {
return falseblnr;
}
}
LOCALPROC StartUpTimeAdjust(void)
{
LatestTime = [NSDate timeIntervalSinceReferenceDate];
NextTickChangeTime = LatestTime;
}
LOCALFUNC blnr InitLocationDat(void)
{
NSTimeZone *MyZone = [NSTimeZone localTimeZone];
ui5b TzOffSet = (ui5b)[MyZone secondsFromGMT];
#if AutoTimeZone
BOOL isdst = [MyZone isDaylightSavingTime];
#endif
MyDateDelta = TzOffSet - 1233815296;
LatestTime = [NSDate timeIntervalSinceReferenceDate];
NewMacDateInSeconds = ((ui5b)LatestTime) + MyDateDelta;
CurMacDateInSeconds = NewMacDateInSeconds;
#if AutoTimeZone
CurMacDelta = (TzOffSet & 0x00FFFFFF)
| ((isdst ? 0x80 : 0) << 24);
#endif
return trueblnr;
}
/* --- sound --- */
#if MySoundEnabled
#define kLn2SoundBuffers 4 /* kSoundBuffers must be a power of two */
#define kSoundBuffers (1 << kLn2SoundBuffers)
#define kSoundBuffMask (kSoundBuffers - 1)
#define DesiredMinFilledSoundBuffs 3
/*
if too big then sound lags behind emulation.
if too small then sound will have pauses.
*/
#define kLnOneBuffLen 9
#define kLnAllBuffLen (kLn2SoundBuffers + kLnOneBuffLen)
#define kOneBuffLen (1UL << kLnOneBuffLen)
#define kAllBuffLen (1UL << kLnAllBuffLen)
#define kLnOneBuffSz (kLnOneBuffLen + kLn2SoundSampSz - 3)
#define kLnAllBuffSz (kLnAllBuffLen + kLn2SoundSampSz - 3)
#define kOneBuffSz (1UL << kLnOneBuffSz)
#define kAllBuffSz (1UL << kLnAllBuffSz)
#define kOneBuffMask (kOneBuffLen - 1)
#define kAllBuffMask (kAllBuffLen - 1)
#define dbhBufferSize (kAllBuffSz + kOneBuffSz)
#define dbglog_SoundStuff (0 && dbglog_HAVE)
#define dbglog_SoundBuffStats (0 && dbglog_HAVE)
LOCALVAR tpSoundSamp TheSoundBuffer = nullpr;
static volatile ui4b ThePlayOffset;
static volatile ui4b TheFillOffset;
static volatile ui4b MinFilledSoundBuffs;
#if dbglog_SoundBuffStats
LOCALVAR ui4b MaxFilledSoundBuffs;
#endif
LOCALVAR ui4b TheWriteOffset;
LOCALPROC MySound_Start0(void)
{
/* Reset variables */
ThePlayOffset = 0;
TheFillOffset = 0;
TheWriteOffset = 0;
MinFilledSoundBuffs = kSoundBuffers + 1;
#if dbglog_SoundBuffStats
MaxFilledSoundBuffs = 0;
#endif
}
GLOBALOSGLUFUNC tpSoundSamp MySound_BeginWrite(ui4r n, ui4r *actL)
{
ui4b ToFillLen = kAllBuffLen - (TheWriteOffset - ThePlayOffset);
ui4b WriteBuffContig =
kOneBuffLen - (TheWriteOffset & kOneBuffMask);
if (WriteBuffContig < n) {
n = WriteBuffContig;
}
if (ToFillLen < n) {
/* overwrite previous buffer */
#if dbglog_SoundStuff
dbglog_writeln("sound buffer over flow");
#endif
TheWriteOffset -= kOneBuffLen;
}
*actL = n;
return TheSoundBuffer + (TheWriteOffset & kAllBuffMask);
}
#if 4 == kLn2SoundSampSz
LOCALPROC ConvertSoundBlockToNative(tpSoundSamp p)
{
int i;
for (i = kOneBuffLen; --i >= 0; ) {
*p++ -= 0x8000;
}
}
#else
#define ConvertSoundBlockToNative(p)
#endif
LOCALPROC MySound_WroteABlock(void)
{
#if (4 == kLn2SoundSampSz)
ui4b PrevWriteOffset = TheWriteOffset - kOneBuffLen;
tpSoundSamp p = TheSoundBuffer + (PrevWriteOffset & kAllBuffMask);
#endif
#if dbglog_SoundStuff
dbglog_writeln("enter MySound_WroteABlock");
#endif
ConvertSoundBlockToNative(p);
TheFillOffset = TheWriteOffset;
#if dbglog_SoundBuffStats
{
ui4b ToPlayLen = TheFillOffset
- ThePlayOffset;
ui4b ToPlayBuffs = ToPlayLen >> kLnOneBuffLen;
if (ToPlayBuffs > MaxFilledSoundBuffs) {
MaxFilledSoundBuffs = ToPlayBuffs;
}
}
#endif
}
LOCALFUNC blnr MySound_EndWrite0(ui4r actL)
{
blnr v;
TheWriteOffset += actL;
if (0 != (TheWriteOffset & kOneBuffMask)) {
v = falseblnr;
} else {
/* just finished a block */
MySound_WroteABlock();
v = trueblnr;
}
return v;
}
LOCALPROC MySound_SecondNotify0(void)
{
if (MinFilledSoundBuffs <= kSoundBuffers) {
if (MinFilledSoundBuffs > DesiredMinFilledSoundBuffs) {
#if dbglog_SoundStuff
dbglog_writeln("MinFilledSoundBuffs too high");
#endif
NextTickChangeTime += MyTickDuration;
} else if (MinFilledSoundBuffs < DesiredMinFilledSoundBuffs) {
#if dbglog_SoundStuff
dbglog_writeln("MinFilledSoundBuffs too low");
#endif
++TrueEmulatedTime;
}
#if dbglog_SoundBuffStats
dbglog_writelnNum("MinFilledSoundBuffs",
MinFilledSoundBuffs);
dbglog_writelnNum("MaxFilledSoundBuffs",
MaxFilledSoundBuffs);
MaxFilledSoundBuffs = 0;
#endif
MinFilledSoundBuffs = kSoundBuffers + 1;
}
}
typedef ui4r trSoundTemp;
#define kCenterTempSound 0x8000
#define AudioStepVal 0x0040
#if 3 == kLn2SoundSampSz
#define ConvertTempSoundSampleFromNative(v) ((v) << 8)
#elif 4 == kLn2SoundSampSz
#define ConvertTempSoundSampleFromNative(v) ((v) + kCenterSound)
#else
#error "unsupported kLn2SoundSampSz"
#endif
#if 3 == kLn2SoundSampSz
#define ConvertTempSoundSampleToNative(v) ((v) >> 8)
#elif 4 == kLn2SoundSampSz
#define ConvertTempSoundSampleToNative(v) ((v) - kCenterSound)
#else
#error "unsupported kLn2SoundSampSz"
#endif
LOCALPROC SoundRampTo(trSoundTemp *last_val, trSoundTemp dst_val,
tpSoundSamp *stream, int *len)
{
trSoundTemp diff;
tpSoundSamp p = *stream;
int n = *len;
trSoundTemp v1 = *last_val;
while ((v1 != dst_val) && (0 != n)) {
if (v1 > dst_val) {
diff = v1 - dst_val;
if (diff > AudioStepVal) {
v1 -= AudioStepVal;
} else {
v1 = dst_val;
}
} else {
diff = dst_val - v1;
if (diff > AudioStepVal) {
v1 += AudioStepVal;
} else {
v1 = dst_val;
}
}
--n;
*p++ = ConvertTempSoundSampleToNative(v1);
}
*stream = p;
*len = n;
*last_val = v1;
}
struct MySoundR {
tpSoundSamp fTheSoundBuffer;
volatile ui4b (*fPlayOffset);
volatile ui4b (*fFillOffset);
volatile ui4b (*fMinFilledSoundBuffs);
volatile trSoundTemp lastv;
blnr enabled;
blnr wantplaying;
blnr HaveStartedPlaying;
AudioUnit outputAudioUnit;
};
typedef struct MySoundR MySoundR;
LOCALPROC my_audio_callback(void *udata, void *stream, int len)
{
ui4b ToPlayLen;
ui4b FilledSoundBuffs;
int i;
MySoundR *datp = (MySoundR *)udata;
tpSoundSamp CurSoundBuffer = datp->fTheSoundBuffer;
ui4b CurPlayOffset = *datp->fPlayOffset;
trSoundTemp v0 = datp->lastv;
trSoundTemp v1 = v0;
tpSoundSamp dst = (tpSoundSamp)stream;
#if kLn2SoundSampSz > 3
len >>= (kLn2SoundSampSz - 3);
#endif
#if dbglog_SoundStuff
dbglog_writeln("Enter my_audio_callback");
dbglog_writelnNum("len", len);
#endif
label_retry:
ToPlayLen = *datp->fFillOffset - CurPlayOffset;
FilledSoundBuffs = ToPlayLen >> kLnOneBuffLen;
if (! datp->wantplaying) {
#if dbglog_SoundStuff
dbglog_writeln("playing end transistion");
#endif
SoundRampTo(&v1, kCenterTempSound, &dst, &len);
ToPlayLen = 0;
} else if (! datp->HaveStartedPlaying) {
#if dbglog_SoundStuff
dbglog_writeln("playing start block");
#endif
if ((ToPlayLen >> kLnOneBuffLen) < 8) {
ToPlayLen = 0;
} else {
tpSoundSamp p = datp->fTheSoundBuffer
+ (CurPlayOffset & kAllBuffMask);
trSoundTemp v2 = ConvertTempSoundSampleFromNative(*p);
#if dbglog_SoundStuff
dbglog_writeln("have enough samples to start");
#endif
SoundRampTo(&v1, v2, &dst, &len);
if (v1 == v2) {
#if dbglog_SoundStuff
dbglog_writeln("finished start transition");
#endif
datp->HaveStartedPlaying = trueblnr;
}
}
}
if (0 == len) {
/* done */
if (FilledSoundBuffs < *datp->fMinFilledSoundBuffs) {
*datp->fMinFilledSoundBuffs = FilledSoundBuffs;
}
} else if (0 == ToPlayLen) {
#if dbglog_SoundStuff
dbglog_writeln("under run");
#endif
for (i = 0; i < len; ++i) {
*dst++ = ConvertTempSoundSampleToNative(v1);
}
*datp->fMinFilledSoundBuffs = 0;
} else {
ui4b PlayBuffContig = kAllBuffLen
- (CurPlayOffset & kAllBuffMask);
tpSoundSamp p = CurSoundBuffer
+ (CurPlayOffset & kAllBuffMask);
if (ToPlayLen > PlayBuffContig) {
ToPlayLen = PlayBuffContig;
}
if (ToPlayLen > len) {
ToPlayLen = len;
}
for (i = 0; i < ToPlayLen; ++i) {
*dst++ = *p++;
}
v1 = ConvertTempSoundSampleFromNative(p[-1]);
CurPlayOffset += ToPlayLen;
len -= ToPlayLen;
*datp->fPlayOffset = CurPlayOffset;
goto label_retry;
}
datp->lastv = v1;
}
LOCALFUNC OSStatus audioCallback(
void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
AudioBuffer *abuf;
UInt32 i;
UInt32 n = ioData->mNumberBuffers;
#if dbglog_SoundStuff
dbglog_writeln("Enter audioCallback");
dbglog_writelnNum("mNumberBuffers", n);
#endif
for (i = 0; i < n; i++) {
abuf = &ioData->mBuffers[i];
my_audio_callback(inRefCon,
abuf->mData, abuf->mDataByteSize);
}
return 0;
}
LOCALVAR MySoundR cur_audio;
LOCALPROC ZapAudioVars(void)
{
memset(&cur_audio, 0, sizeof(MySoundR));
}
LOCALPROC MySound_Stop(void)
{
#if dbglog_SoundStuff
dbglog_writeln("enter MySound_Stop");
#endif
if (cur_audio.wantplaying) {
OSStatus result;
ui4r retry_limit = 50; /* half of a second */
cur_audio.wantplaying = falseblnr;
label_retry:
if (kCenterTempSound == cur_audio.lastv) {
#if dbglog_SoundStuff
dbglog_writeln("reached kCenterTempSound");
#endif
/* done */
} else if (0 == --retry_limit) {
#if dbglog_SoundStuff
dbglog_writeln("retry limit reached");
#endif
/* done */
} else
{
/*
give time back, particularly important
if got here on a suspend event.
*/
struct timespec rqt;
struct timespec rmt;
#if dbglog_SoundStuff
dbglog_writeln("busy, so sleep");
#endif
rqt.tv_sec = 0;
rqt.tv_nsec = 10000000;
(void) nanosleep(&rqt, &rmt);
goto label_retry;
}
if (noErr != (result = AudioOutputUnitStop(
cur_audio.outputAudioUnit)))
{
#if dbglog_HAVE
dbglog_writeln("AudioOutputUnitStop fails");
#endif
}
}
#if dbglog_SoundStuff
dbglog_writeln("leave MySound_Stop");
#endif
}
LOCALPROC MySound_Start(void)
{
OSStatus result;
if ((! cur_audio.wantplaying) && cur_audio.enabled) {
#if dbglog_SoundStuff
dbglog_writeln("enter MySound_Start");
#endif
MySound_Start0();
cur_audio.lastv = kCenterTempSound;
cur_audio.HaveStartedPlaying = falseblnr;
cur_audio.wantplaying = trueblnr;
if (noErr != (result = AudioOutputUnitStart(
cur_audio.outputAudioUnit)))
{
#if dbglog_HAVE
dbglog_writeln("AudioOutputUnitStart fails");
#endif
cur_audio.wantplaying = falseblnr;
}
#if dbglog_SoundStuff
dbglog_writeln("leave MySound_Start");
#endif
}
}
LOCALPROC MySound_UnInit(void)
{
if (cur_audio.enabled) {
OSStatus result;
struct AURenderCallbackStruct callback;
cur_audio.enabled = falseblnr;
/* Remove the input callback */
callback.inputProc = 0;
callback.inputProcRefCon = 0;
if (noErr != (result = AudioUnitSetProperty(
cur_audio.outputAudioUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input,
0,
&callback,
sizeof(callback))))
{
#if dbglog_HAVE
dbglog_writeln("AudioUnitSetProperty fails"
"(kAudioUnitProperty_SetRenderCallback)");
#endif
}
if (noErr != (result = CloseComponent(
cur_audio.outputAudioUnit)))
{
#if dbglog_HAVE
dbglog_writeln("CloseComponent fails in MySound_UnInit");
#endif
}
}
}
#define SOUND_SAMPLERATE 22255 /* = round(7833600 * 2 / 704) */
LOCALFUNC blnr MySound_Init(void)
{
OSStatus result = noErr;
Component comp;
ComponentDescription desc;
struct AURenderCallbackStruct callback;
AudioStreamBasicDescription requestedDesc;
cur_audio.fTheSoundBuffer = TheSoundBuffer;
cur_audio.fPlayOffset = &ThePlayOffset;
cur_audio.fFillOffset = &TheFillOffset;
cur_audio.fMinFilledSoundBuffs = &MinFilledSoundBuffs;
cur_audio.wantplaying = falseblnr;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_DefaultOutput;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
requestedDesc.mFormatID = kAudioFormatLinearPCM;
requestedDesc.mFormatFlags = kLinearPCMFormatFlagIsPacked
#if 3 != kLn2SoundSampSz
| kLinearPCMFormatFlagIsSignedInteger
#endif
;
requestedDesc.mChannelsPerFrame = 1;
requestedDesc.mSampleRate = SOUND_SAMPLERATE;
requestedDesc.mBitsPerChannel = (1 << kLn2SoundSampSz);
#if 0
requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
#endif
#if 0
requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
#endif
requestedDesc.mFramesPerPacket = 1;
requestedDesc.mBytesPerFrame = (requestedDesc.mBitsPerChannel
* requestedDesc.mChannelsPerFrame) >> 3;
requestedDesc.mBytesPerPacket = requestedDesc.mBytesPerFrame
* requestedDesc.mFramesPerPacket;
callback.inputProc = audioCallback;
callback.inputProcRefCon = &cur_audio;
if (NULL == (comp = FindNextComponent(NULL, &desc)))
{
#if dbglog_HAVE
dbglog_writeln("Failed to start CoreAudio: "
"FindNextComponent returned NULL");
#endif
} else
if (noErr != (result = OpenAComponent(
comp, &cur_audio.outputAudioUnit)))
{
#if dbglog_HAVE
dbglog_writeln("Failed to start CoreAudio: OpenAComponent");
#endif
} else
if (noErr != (result = AudioUnitInitialize(
cur_audio.outputAudioUnit)))
{
#if dbglog_HAVE
dbglog_writeln(
"Failed to start CoreAudio: AudioUnitInitialize");
#endif
} else
if (noErr != (result = AudioUnitSetProperty(
cur_audio.outputAudioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
0,
&requestedDesc,
sizeof(requestedDesc))))
{
#if dbglog_HAVE
dbglog_writeln("Failed to start CoreAudio: "
"AudioUnitSetProperty(kAudioUnitProperty_StreamFormat)");
#endif
} else
if (noErr != (result = AudioUnitSetProperty(
cur_audio.outputAudioUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input,
0,
&callback,
sizeof(callback))))
{
#if dbglog_HAVE
dbglog_writeln("Failed to start CoreAudio: "
"AudioUnitSetProperty(kAudioUnitProperty_SetInputCallback)"
);
#endif
} else
{
cur_audio.enabled = trueblnr;
MySound_Start();
/*
This should be taken care of by LeaveSpeedStopped,
but since takes a while to get going properly,
start early.
*/
}
return trueblnr; /* keep going, even if no sound */
}
GLOBALOSGLUPROC MySound_EndWrite(ui4r actL)
{
if (MySound_EndWrite0(actL)) {
}
}
LOCALPROC MySound_SecondNotify(void)
{
if (cur_audio.enabled) {
MySound_SecondNotify0();
}
}
#endif
LOCALPROC FinishSubMenu(NSMenu *theMenu, NSMenu *parentMenu,
NSString *sTitle)
{
NSMenuItem *menuItem = [[NSMenuItem alloc]
initWithTitle: sTitle
action: nil
keyEquivalent: @""];
[menuItem setSubmenu: theMenu];
[parentMenu addItem: menuItem];
[menuItem release];
}
LOCALFUNC NSMenu *setApplicationMenu(NSMenu *mainMenu)
{
NSMenuItem *menuItem;
NSString *sAppName = NSStringCreateFromSubstCStr("^p");
/* doesn't matter though, OS X replaces this */
NSString *sAbout =
NSStringCreateFromSubstCStr(kStrMenuItemAbout);
NSString *sHide =
NSStringCreateFromSubstCStr(kStrAppMenuItemHide);
NSString *sHideOthers =
NSStringCreateFromSubstCStr(kStrAppMenuItemHideOthers);
NSString *sShowAll =
NSStringCreateFromSubstCStr(kStrAppMenuItemShowAll);
NSString *sQuit =
NSStringCreateFromSubstCStr(kStrAppMenuItemQuit);
NSMenu *appleMenu = [[NSMenu alloc] initWithTitle: sAppName];
/* Add menu items */
menuItem = [appleMenu addItemWithTitle: sAbout
action: @selector(performApplicationAbout:)
keyEquivalent: @"a"];
[menuItem setKeyEquivalentModifierMask: NSControlKeyMask];
[appleMenu addItem:[NSMenuItem separatorItem]];
[appleMenu addItemWithTitle: sHide
action: @selector(hide:) keyEquivalent: @""];
[appleMenu
addItemWithTitle: sHideOthers
action: @selector(hideOtherApplications:)
keyEquivalent: @""];
[appleMenu addItemWithTitle: sShowAll
action: @selector(unhideAllApplications:)
keyEquivalent: @""];
[appleMenu addItem: [NSMenuItem separatorItem]];
menuItem = [appleMenu addItemWithTitle: sQuit
action: @selector(terminate:) keyEquivalent: @"q"];
[menuItem setKeyEquivalentModifierMask: NSControlKeyMask];
FinishSubMenu(appleMenu, mainMenu, sAppName);
[appleMenu release];
return appleMenu;
}
/* Create File menu */
LOCALPROC setupFileMenu(NSMenu *mainMenu)
{
NSMenu *fileMenu;
NSMenuItem *menuItem;
NSString *sFile =
NSStringCreateFromSubstCStr(kStrMenuFile);
NSString *sOpen =
NSStringCreateFromSubstCStr(kStrMenuItemOpen ";ll");
fileMenu = [[NSMenu alloc] initWithTitle: sFile];
menuItem = [fileMenu
addItemWithTitle: sOpen
action: @selector(performFileOpen:)
keyEquivalent: @"o"];
[menuItem setKeyEquivalentModifierMask: NSControlKeyMask];
FinishSubMenu(fileMenu, mainMenu, sFile);
[fileMenu release];
}
/* Create Special menu */
LOCALPROC setupSpecialMenu(NSMenu *mainMenu)
{
NSMenu *specialMenu;
NSString *sSpecial =
NSStringCreateFromSubstCStr(kStrMenuSpecial);
NSString *sMore =
NSStringCreateFromSubstCStr(kStrMenuItemMore ";ll");
specialMenu = [[NSMenu alloc] initWithTitle: sSpecial];
[specialMenu
addItemWithTitle: sMore
action: @selector(performSpecialMoreCommands:)
keyEquivalent: @""];
FinishSubMenu(specialMenu, mainMenu, sSpecial);
[specialMenu release];
}
LOCALPROC MyMenuSetup(void)
{
NSMenu *mainMenu = [[NSMenu alloc] init];
NSMenu *appleMenu = setApplicationMenu(mainMenu);
setupFileMenu(mainMenu);
setupSpecialMenu(mainMenu);
[NSApp setMainMenu: mainMenu];
/*
Tell the application object that this is now
the application menu, if this unsupported
call actually exists. Doesn't seem to
be needed anyway, at least in OS X 10.7
*/
if([NSApp respondsToSelector:@selector(setAppleMenu:)]) {
/* [NSApp setAppleMenu: appleMenu]; */
[NSApp performSelector: @selector(setAppleMenu:)
withObject:appleMenu];
}
[mainMenu release];
}
/* --- video out --- */
#if ! UseCGContextDrawImage
LOCALPROC HaveChangedScreenBuff(ui4r top, ui4r left,
ui4r bottom, ui4r right)
{
if ([MyNSview lockFocusIfCanDraw]) {
MyDrawWithOpenGL(top, left, bottom, right);
[MyNSview unlockFocus];
}
}
#else
LOCALPROC HaveChangedScreenBuff(ui4r top, ui4r left,
ui4r bottom, ui4r right)
{
int i;
int j;
ui3b *the_data = (ui3b *)GetCurDrawBuff();
ui3b *p;
ui5b color;
ui5b black_color = 0;
/* SDL_MapRGB(cur_video.format, 0, 0, 0) */
ui5b white_color = 0;
/* SDL_MapRGB(cur_video.format, 255, 255, 255) */
switch (MyBytesPerPixel) {
case 2: /* (1)-5-5-5 RGB */
#if 0
rmask = 0x7C00;
gmask = 0x03E0;
bmask = 0x001F;
#endif
break;
case 4:
#if LittleEndianUnaligned
#if 0
rmask = 0x0000FF00;
gmask = 0x00FF0000;
bmask = 0xFF000000;
#endif
black_color = 0x000000FF;
white_color = 0xFFFFFFFF;
#else
#if 0
rmask = 0x00FF0000;
gmask = 0x0000FF00;
bmask = 0x000000FF;
#endif
black_color = 0xFF000000;
white_color = 0xFFFFFFFF;
#endif
break;
}
#if EnableMagnify
if (UseMagnify) {
for (i = top * MyWindowScale; i < bottom * MyWindowScale; ++i) {
for (j = left * MyWindowScale;
j < right * MyWindowScale; ++j)
{
p = the_data + (((i / MyWindowScale) * vMacScreenWidth
+ (j / MyWindowScale)) / 8);
if (0 != (*p & (1 << ((~ (j / MyWindowScale)) & 0x7))))
{
color = black_color;
} else {
color = white_color;
}
switch (MyBytesPerPixel) {
case 2: { /* Probably 15-bpp or 16-bpp */
ui4b *bufp;
bufp = (ui4b *)MyPixels
+ i * MyPitch / 2 + j;
*bufp = color;
}
break;
case 4: { /* Probably 32-bpp */
ui5b *bufp;
bufp = (ui5b *)MyPixels
+ i * MyPitch / 4 + j;
*bufp = color;
}
break;
}
}
}
} else
#endif
{
for (i = top; i < bottom; ++i) {
for (j = left; j < right; ++j) {
p = the_data + ((i * vMacScreenWidth + j) / 8);
if (0 != (*p & (1 << ((~ j) & 0x7)))) {
color = black_color;
} else {
color = white_color;
}
switch (MyBytesPerPixel) {
case 2: { /* Probably 15-bpp or 16-bpp */
ui4b *bufp;
bufp = (ui4b *)MyPixels
+ i * MyPitch / 2 + j;
*bufp = color;
}
break;
case 4: { /* Probably 32-bpp */
ui5b *bufp;
bufp = (ui5b *)MyPixels
+ i * MyPitch / 4 + j;
*bufp = color;
}
break;
}
}
}
}
#if EnableMagnify
if (UseMagnify) {
SDL_UpdateRect(left * MyWindowScale,
top * MyWindowScale,
(right - left) * MyWindowScale,
(bottom - top) * MyWindowScale);
} else
#endif
{
SDL_UpdateRect(left, top,
right - left, bottom - top);
}
}
#endif
LOCALPROC MyDrawChangesAndClear(void)
{
if (ScreenChangedBottom > ScreenChangedTop) {
HaveChangedScreenBuff(ScreenChangedTop, ScreenChangedLeft,
ScreenChangedBottom, ScreenChangedRight);
ScreenClearChanges();
}
}
GLOBALOSGLUPROC DoneWithDrawingForTick(void)
{
#if EnableFSMouseMotion
if (HaveMouseMotion) {
AutoScrollScreen();
}
#endif
MyDrawChangesAndClear();
}
/* --- keyboard input --- */
LOCALPROC DisableKeyRepeat(void)
{
}
LOCALPROC RestoreKeyRepeat(void)
{
}
LOCALPROC ReconnectKeyCodes3(void)
{
}
LOCALPROC DisconnectKeyCodes3(void)
{
DisconnectKeyCodes2();
MyMouseButtonSet(falseblnr);
}
/* --- basic dialogs --- */
LOCALPROC CheckSavedMacMsg(void)
{
/* called only on quit, if error saved but not yet reported */
if (nullpr != SavedBriefMsg) {
NSString *briefMsg0 =
NSStringCreateFromSubstCStr(SavedBriefMsg);
NSString *longMsg0 =
NSStringCreateFromSubstCStr(SavedLongMsg);
NSString *quitMsg0 =
NSStringCreateFromSubstCStr(kStrCmdQuit);
(void) NSRunAlertPanel(briefMsg0, @"%@", quitMsg0, nil, nil,
longMsg0);
SavedBriefMsg = nullpr;
}
}
/* --- hide/show menubar --- */
enum {
MyNSApplicationPresentationDefault = 0,
MyNSApplicationPresentationAutoHideDock = (1 << 0),
MyNSApplicationPresentationHideDock = (1 << 1),
MyNSApplicationPresentationAutoHideMenuBar = (1 << 2),
MyNSApplicationPresentationHideMenuBar = (1 << 3),
MyNSApplicationPresentationDisableAppleMenu = (1 << 4),
MyNSApplicationPresentationDisableProcessSwitching = (1 << 5),
MyNSApplicationPresentationDisableForceQuit = (1 << 6),
MyNSApplicationPresentationDisableSessionTermination = (1 << 7),
MyNSApplicationPresentationDisableHideApplication = (1 << 8),
MyNSApplicationPresentationDisableMenuBarTransparency = (1 << 9),
MyNSApplicationPresentationFullScreen = (1 << 10),
MyNSApplicationPresentationAutoHideToolbar = (1 << 11)
};
typedef NSUInteger MyNSApplicationPresentationOptions;
@interface MyNSApplication : NSObject
- (void)setPresentationOptions:
(MyNSApplicationPresentationOptions)newOptions;
@end
#if MayFullScreen
LOCALPROC My_HideMenuBar(void)
{
if ([NSApp respondsToSelector:@selector(setPresentationOptions:)]) {
[((MyNSApplication *)NSApp) setPresentationOptions:
MyNSApplicationPresentationHideDock
| MyNSApplicationPresentationHideMenuBar
#if GrabKeysFullScreen
| MyNSApplicationPresentationDisableProcessSwitching
#if GrabKeysMaxFullScreen /* dangerous !! */
| MyNSApplicationPresentationDisableForceQuit
| MyNSApplicationPresentationDisableSessionTermination
#endif
#endif
];
} else
if (HaveMySetSystemUIMode()) {
(void) MySetSystemUIMode(MykUIModeAllHidden,
MykUIOptionDisableAppleMenu
#if GrabKeysFullScreen
| MykUIOptionDisableProcessSwitch
#if GrabKeysMaxFullScreen /* dangerous !! */
| MykUIOptionDisableForceQuit
| MykUIOptionDisableSessionTerminate
#endif
#endif
);
} else
{
}
}
#endif
#if MayFullScreen
LOCALPROC My_ShowMenuBar(void)
{
if ([NSApp respondsToSelector:@selector(setPresentationOptions:)]) {
[((MyNSApplication *)NSApp) setPresentationOptions:
MyNSApplicationPresentationDefault];
} else
if (HaveMySetSystemUIMode()) {
(void) MySetSystemUIMode(MykUIModeNormal,
0);
} else
{
}
}
#endif
/* --- event handling for main window --- */
LOCALPROC MyBeginDialog(void)
{
DisconnectKeyCodes3();
ForceShowCursor();
}
LOCALPROC MyEndDialog(void)
{
[MyWindow makeKeyWindow];
EmulationWasInterrupted = trueblnr;
}
LOCALPROC InsertADisk0(void)
{
NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setAllowsMultipleSelection: YES];
MyBeginDialog();
if (NSOKButton == [panel runModal]) {
int i;
NSArray *a = [panel URLs];
int n = [a count];
for (i = 0; i < n; ++i) {
NSURL *fileURL = [a objectAtIndex: i];
NSString* filePath = [fileURL path];
(void) Sony_Insert1a(filePath);
}
}
MyEndDialog();
}
/* --- main window creation and disposal --- */
LOCALFUNC blnr Screen_Init(void)
{
#if 0
if (noErr != Gestalt(gestaltSystemVersion,
&cur_video.system_version))
{
cur_video.system_version = 0;
}
#endif
#if 0
#define MyCGMainDisplayID CGMainDisplayID
CGDirectDisplayID CurMainDisplayID = MyCGMainDisplayID();
cur_video.width = (ui5b) CGDisplayPixelsWide(CurMainDisplayID);
cur_video.height = (ui5b) CGDisplayPixelsHigh(CurMainDisplayID);
#endif
InitKeyCodes();
return trueblnr;
}
#if MayFullScreen
LOCALPROC AdjustMachineGrab(void)
{
#if EnableFSMouseMotion
AdjustMouseMotionGrab();
#endif
}
#endif
#if MayFullScreen
LOCALPROC UngrabMachine(void)
{
GrabMachine = falseblnr;
AdjustMachineGrab();
}
#endif
LOCALPROC MyAdjustGLforSize(int h, int v)
{
[MyNSOpnGLCntxt makeCurrentContext];
glClearColor (0.0, 0.0, 0.0, 1.0);
#if 1
glViewport(0, 0, h, v);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, h, 0, v, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
#endif
glColor3f(0.0, 0.0, 0.0);
#if EnableMagnify
if (UseMagnify) {
glPixelZoom(MyWindowScale, - MyWindowScale);
} else
#endif
{
glPixelZoom(1, -1);
}
glPixelStorei(GL_UNPACK_ROW_LENGTH, vMacScreenWidth);
glClear(GL_COLOR_BUFFER_BIT);
[NSOpenGLContext clearCurrentContext];
ScreenChangedAll();
}
LOCALVAR blnr WantScreensChangedCheck = falseblnr;
LOCALPROC MyUpdateOpenGLContext(void)
{
if (nil != MyNSOpnGLCntxt) {
[MyNSOpnGLCntxt makeCurrentContext];
[MyNSOpnGLCntxt update];
}
}
LOCALPROC CloseMyOpenGLContext(void)
{
if (nil != MyNSOpnGLCntxt) {
[NSOpenGLContext clearCurrentContext];
/*
Only because MyDrawWithOpenGL doesn't
bother to do this. No one
uses the current context
without settting it first.
*/
}
}
LOCALFUNC blnr GetOpnGLCntxt(void)
{
blnr v = falseblnr;
if (nil == MyNSOpnGLCntxt) {
NSRect NewWinRect = [MyNSview frame];
NSOpenGLPixelFormat *fmt;
#if WantGraphicsSwitching
{
NSOpenGLPixelFormatAttribute attr0[] = {
NSOpenGLPFAAllowOfflineRenderers,
0};
fmt =
[[NSOpenGLPixelFormat alloc] initWithAttributes:attr0];
}
if (nil != fmt) {
/* ok */
} else
#endif
{
NSOpenGLPixelFormatAttribute attr[] = {
0};
fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
if (nil == fmt) {
#if dbglog_HAVE
dbglog_writeln("Could not create fmt");
#endif
goto label_exit;
}
}
MyNSOpnGLCntxt = [[NSOpenGLContext alloc]
initWithFormat:fmt shareContext:nil];
[fmt release];
if (nil == MyNSOpnGLCntxt) {
#if dbglog_HAVE
dbglog_writeln("Could not create MyNSOpnGLCntxt");
#endif
goto label_exit;
}
/* fprintf(stderr, "%s\n", "Got OpenGL context"); */
[MyNSOpnGLCntxt setView: MyNSview];
[MyNSOpnGLCntxt update];
MyAdjustGLforSize(NewWinRect.size.width,
NewWinRect.size.height);
#if 0 != vMacScreenDepth
ColorModeWorks = trueblnr;
#endif
}
v = trueblnr;
label_exit:
return v;
}
typedef NSUInteger (*modifierFlagsProcPtr)
(id self, SEL cmd);
/* Subclass of NSWindow to fix genie effect and support resize events */
@interface MyClassWindow : NSWindow
@end
@implementation MyClassWindow
#if MayFullScreen
- (BOOL)canBecomeKeyWindow
{
return
#if VarFullScreen
(! UseFullScreen) ? [super canBecomeKeyWindow] :
#endif
YES;
}
#endif
#if MayFullScreen
- (BOOL)canBecomeMainWindow
{
return
#if VarFullScreen
(! UseFullScreen) ? [super canBecomeMainWindow] :
#endif
YES;
}
#endif
#if MayFullScreen
- (NSRect)constrainFrameRect:(NSRect)frameRect
toScreen:(NSScreen *)screen
{
#if VarFullScreen
if (! UseFullScreen) {
return [super constrainFrameRect:frameRect toScreen:screen];
} else
#endif
{
return frameRect;
}
}
#endif
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
/* NSPasteboard *pboard = [sender draggingPasteboard]; */
NSDragOperation sourceDragMask =
[sender draggingSourceOperationMask];
NSDragOperation v = NSDragOperationNone;
if (0 != (sourceDragMask & NSDragOperationGeneric)) {
return NSDragOperationGeneric;
}
return v;
}
- (void)draggingExited:(id <NSDraggingInfo>)sender
{
/* remove hilighting */
}
- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
{
return YES;
}
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
{
BOOL v = NO;
NSPasteboard *pboard = [sender draggingPasteboard];
/*
NSDragOperation sourceDragMask =
[sender draggingSourceOperationMask];
*/
if ([[pboard types] containsObject:NSFilenamesPboardType]) {
int i;
NSArray *file_names =
[pboard propertyListForType: NSFilenamesPboardType];
int n = [file_names count];
for (i = 0; i < n; ++i) {
NSString *filePath = [file_names objectAtIndex:i];
Sony_ResolveInsert(filePath);
}
v = YES;
} else if ([[pboard types] containsObject: NSURLPboardType]) {
NSURL *fileURL = [NSURL URLFromPasteboard: pboard];
NSString* filePath = [fileURL path];
Sony_ResolveInsert(filePath);
v = YES;
}
if (v && gTrueBackgroundFlag) {
{
SEL sel = @selector(modifierFlags);
if ([NSEvent respondsToSelector:sel]) {
modifierFlagsProcPtr imp = (modifierFlagsProcPtr)
[NSEvent methodForSelector:sel];
MyUpdateKeyboardModifiers(imp([NSEvent class], sel));
}
}
[NSApp activateIgnoringOtherApps: YES];
}
return v;
}
- (void) concludeDragOperation:(id <NSDraggingInfo>)the_sender
{
}
@end
@interface MyClassWindowDelegate : NSObject <NSWindowDelegate>
@end
@implementation MyClassWindowDelegate
- (BOOL)windowShouldClose:(id)sender
{
RequestMacOff = trueblnr;
return NO;
}
- (void)windowDidBecomeKey:(NSNotification *)aNotification
{
gTrueBackgroundFlag = falseblnr;
}
- (void)windowDidResignKey:(NSNotification *)aNotification
{
gTrueBackgroundFlag = trueblnr;
}
@end
@interface MyClassView : NSView
@end
@implementation MyClassView
- (void)resetCursorRects
{
[self addCursorRect: [self visibleRect]
cursor: [NSCursor arrowCursor]];
}
- (BOOL)isOpaque
{
return YES;
}
- (void)drawRect:(NSRect)dirtyRect
{
/*
Called upon makeKeyAndOrderFront. Create our
OpenGL context here, because can't do so
before makeKeyAndOrderFront.
And if create after then our content won't
be drawn initially, resulting in flicker.
*/
if (GetOpnGLCntxt()) {
MyDrawWithOpenGL(0, 0, vMacScreenHeight, vMacScreenWidth);
}
}
@end
#if UseCGContextDrawImage
/* absent in 10.3.9. */
CG_EXTERN CGImageRef CGBitmapContextCreateImage(CGContextRef);
#endif
LOCALVAR MyClassWindowDelegate *MyWinDelegate = nil;
LOCALPROC CloseMainWindow(void)
{
if (nil != MyWinDelegate) {
[MyWinDelegate release];
MyWinDelegate = nil;
}
if (nil != MyWindow) {
[MyWindow close];
MyWindow = nil;
}
if (nil != MyNSview) {
[MyNSview release];
MyNSview = nil;
}
#if UseCGContextDrawImage
if (nil != MyCGcontext) {
CGContextFlush(MyCGcontext);
CGContextRelease(MyCGcontext);
MyCGcontext = nil;
}
if (NULL != MyPixels) {
free(MyPixels);
MyPixels = NULL;
}
#endif
if (nil != MyNSOpnGLCntxt) {
[MyNSOpnGLCntxt release];
MyNSOpnGLCntxt = nil;
}
}
LOCALPROC QZ_SetCaption(void)
{
#if 0
NSString *string =
[[NSString alloc] initWithUTF8String: kStrAppName];
#endif
[MyWindow setTitle: myAppName /* string */];
#if 0
[string release];
#endif
}
enum {
kMagStateNormal,
#if EnableMagnify
kMagStateMagnifgy,
#endif
kNumMagStates
};
#define kMagStateAuto kNumMagStates
#if MayNotFullScreen
LOCALVAR int CurWinIndx;
LOCALVAR blnr HavePositionWins[kNumMagStates];
LOCALVAR NSPoint WinPositionWins[kNumMagStates];
#endif
LOCALVAR NSRect SavedScrnBounds;
LOCALFUNC blnr CreateMainWindow(void)
{
#if UseCGContextDrawImage
CGColorSpaceRef cgColorspace;
#endif
unsigned int style;
NSRect MainScrnBounds;
NSRect AllScrnBounds;
NSRect NewWinRect;
NSPoint botleftPos;
int NewWindowHeight = vMacScreenHeight;
int NewWindowWidth = vMacScreenWidth;
blnr v = falseblnr;
#if VarFullScreen
if (UseFullScreen) {
My_HideMenuBar();
} else {
My_ShowMenuBar();
}
#else
#if MayFullScreen
My_HideMenuBar();
#endif
#endif
MainScrnBounds = [[NSScreen mainScreen] frame];
SavedScrnBounds = MainScrnBounds;
{
int i;
NSArray *screens = [NSScreen screens];
int n = [screens count];
AllScrnBounds = MainScrnBounds;
for (i = 0; i < n; ++i) {
AllScrnBounds = NSUnionRect(AllScrnBounds,
[[screens objectAtIndex:i] frame]);
}
}
#if EnableMagnify
if (UseMagnify) {
NewWindowHeight *= MyWindowScale;
NewWindowWidth *= MyWindowScale;
}
#endif
botleftPos.x = MainScrnBounds.origin.x
+ floor((MainScrnBounds.size.width
- NewWindowWidth) / 2);
botleftPos.y = MainScrnBounds.origin.y
+ floor((MainScrnBounds.size.height
- NewWindowHeight) / 2);
if (botleftPos.x < MainScrnBounds.origin.x) {
botleftPos.x = MainScrnBounds.origin.x;
}
if (botleftPos.y < MainScrnBounds.origin.y) {
botleftPos.y = MainScrnBounds.origin.y;
}
#if VarFullScreen
if (UseFullScreen)
#endif
#if MayFullScreen
{
ViewHSize = MainScrnBounds.size.width;
ViewVSize = MainScrnBounds.size.height;
#if EnableMagnify
if (UseMagnify) {
ViewHSize /= MyWindowScale;
ViewVSize /= MyWindowScale;
}
#endif
if (ViewHSize >= vMacScreenWidth) {
ViewHStart = 0;
ViewHSize = vMacScreenWidth;
} else {
ViewHSize &= ~ 1;
}
if (ViewVSize >= vMacScreenHeight) {
ViewVStart = 0;
ViewVSize = vMacScreenHeight;
} else {
ViewVSize &= ~ 1;
}
}
#endif
#if VarFullScreen
if (UseFullScreen)
#endif
#if MayFullScreen
{
NewWinRect = AllScrnBounds;
GLhOffset = botleftPos.x - AllScrnBounds.origin.x;
GLvOffset = (botleftPos.y - AllScrnBounds.origin.y)
+ ((NewWindowHeight < MainScrnBounds.size.height)
? NewWindowHeight : MainScrnBounds.size.height);
hOffset = GLhOffset;
vOffset = AllScrnBounds.size.height - GLvOffset;
style = NSBorderlessWindowMask;
}
#endif
#if VarFullScreen
else
#endif
#if MayNotFullScreen
{
int WinIndx;
#if EnableMagnify
if (UseMagnify) {
WinIndx = kMagStateMagnifgy;
} else
#endif
{
WinIndx = kMagStateNormal;
}
if (! HavePositionWins[WinIndx]) {
WinPositionWins[WinIndx].x = botleftPos.x;
WinPositionWins[WinIndx].y = botleftPos.y;
HavePositionWins[WinIndx] = trueblnr;
NewWinRect = NSMakeRect(botleftPos.x, botleftPos.y,
NewWindowWidth, NewWindowHeight);
} else {
NewWinRect = NSMakeRect(WinPositionWins[WinIndx].x,
WinPositionWins[WinIndx].y,
NewWindowWidth, NewWindowHeight);
}
GLhOffset = 0;
GLvOffset = NewWindowHeight;
style = NSTitledWindowMask
| NSMiniaturizableWindowMask | NSClosableWindowMask;
CurWinIndx = WinIndx;
}
#endif
/* Manually create a window, avoids having a nib file resource */
MyWindow = [[MyClassWindow alloc]
initWithContentRect: NewWinRect
styleMask: style
backing: NSBackingStoreBuffered
defer: YES];
if (nil == MyWindow) {
#if dbglog_HAVE
dbglog_writeln("Could not create the Cocoa window");
#endif
goto label_exit;
}
/* [MyWindow setReleasedWhenClosed: YES]; */
/*
no need to set current_video as it's the
default for NSWindows
*/
QZ_SetCaption();
[MyWindow setAcceptsMouseMovedEvents: YES];
[MyWindow setViewsNeedDisplay: NO];
[MyWindow registerForDraggedTypes:
[NSArray arrayWithObjects:
NSURLPboardType, NSFilenamesPboardType, nil]];
MyWinDelegate = [[MyClassWindowDelegate alloc] init];
if (nil == MyWinDelegate) {
#if dbglog_HAVE
dbglog_writeln("Could not create MyNSview");
#endif
goto label_exit;
}
[MyWindow setDelegate: MyWinDelegate];
MyNSview = [[MyClassView alloc] init];
if (nil == MyNSview) {
#if dbglog_HAVE
dbglog_writeln("Could not create MyNSview");
#endif
goto label_exit;
}
[MyWindow setContentView: MyNSview];
[MyWindow makeKeyAndOrderFront: nil];
/* just in case drawRect didn't get called */
if (! GetOpnGLCntxt()) {
#if dbglog_HAVE
dbglog_writeln("Could not GetOpnGLCntxt");
#endif
goto label_exit;
}
#if UseCGContextDrawImage
MyPitch = 4 * NewWindowWidth;
MyPixels = malloc(NewWindowHeight * MyPitch);
cgColorspace = CGColorSpaceCreateDeviceRGB();
MyCGcontext = CGBitmapContextCreate(MyPixels,
NewWindowWidth, NewWindowHeight,
8, MyPitch, cgColorspace,
kCGImageAlphaNoneSkipFirst);
CGColorSpaceRelease(cgColorspace);
MyNSgfxContext = [NSGraphicsContext
graphicsContextWithWindow: MyWindow];
[NSGraphicsContext setCurrentContext: MyNSgfxContext];
MyBytesPerPixel = 4;
#endif
v = trueblnr;
label_exit:
return v;
}
#if EnableRecreateW
LOCALPROC ZapMyWState(void)
{
MyWindow = nil;
MyNSview = nil;
MyWinDelegate = nil;
#if UseCGContextDrawImage
MyNSgfxContext = nil;
MyCGcontext = nil;
MyPixels = NULL;
#endif
MyNSOpnGLCntxt = nil;
}
#endif
#if EnableRecreateW
struct MyWState {
#if MayFullScreen
ui4r f_ViewHSize;
ui4r f_ViewVSize;
ui4r f_ViewHStart;
ui4r f_ViewVStart;
short f_hOffset;
short f_vOffset;
#endif
#if VarFullScreen
blnr f_UseFullScreen;
#endif
#if EnableMagnify
blnr f_UseMagnify;
#endif
#if MayNotFullScreen
int f_CurWinIndx;
#endif
NSWindow *f_MyWindow;
NSView *f_MyNSview;
MyClassWindowDelegate *f_MyWinDelegate;
#if UseCGContextDrawImage
NSGraphicsContext *f_MyNSgfxContext;
CGContextRef f_MyCGcontext;
void *f_MyPixels;
ui4b f_MyPitch;
ui3b f_MyBytesPerPixel;
#endif
NSOpenGLContext *f_MyNSOpnGLCntxt;
short f_GLhOffset;
short f_GLvOffset;
};
typedef struct MyWState MyWState;
#endif
#if EnableRecreateW
LOCALPROC GetMyWState(MyWState *r)
{
#if MayFullScreen
r->f_ViewHSize = ViewHSize;
r->f_ViewVSize = ViewVSize;
r->f_ViewHStart = ViewHStart;
r->f_ViewVStart = ViewVStart;
r->f_hOffset = hOffset;
r->f_vOffset = vOffset;
#endif
#if VarFullScreen
r->f_UseFullScreen = UseFullScreen;
#endif
#if EnableMagnify
r->f_UseMagnify = UseMagnify;
#endif
#if MayNotFullScreen
r->f_CurWinIndx = CurWinIndx;
#endif
r->f_MyWindow = MyWindow;
r->f_MyNSview = MyNSview;
r->f_MyWinDelegate = MyWinDelegate;
#if UseCGContextDrawImage
r->f_MyNSgfxContext = MyNSgfxContext;
r->f_MyCGcontext = MyCGcontext;
r->f_MyPixels = MyPixels;
r->f_MyPitch = MyPitch;
r->f_MyBytesPerPixel = MyBytesPerPixel;
#endif
r->f_MyNSOpnGLCntxt = MyNSOpnGLCntxt;
r->f_GLhOffset = GLhOffset;
r->f_GLvOffset = GLvOffset;
}
#endif
#if EnableRecreateW
LOCALPROC SetMyWState(MyWState *r)
{
#if MayFullScreen
ViewHSize = r->f_ViewHSize;
ViewVSize = r->f_ViewVSize;
ViewHStart = r->f_ViewHStart;
ViewVStart = r->f_ViewVStart;
hOffset = r->f_hOffset;
vOffset = r->f_vOffset;
#endif
#if VarFullScreen
UseFullScreen = r->f_UseFullScreen;
#endif
#if EnableMagnify
UseMagnify = r->f_UseMagnify;
#endif
#if MayNotFullScreen
CurWinIndx = r->f_CurWinIndx;
#endif
MyWindow = r->f_MyWindow;
MyNSview = r->f_MyNSview;
MyWinDelegate = r->f_MyWinDelegate;
#if UseCGContextDrawImage
MyNSgfxContext = r->f_MyNSgfxContext;
MyCGcontext = r->f_MyCGcontext;
MyPixels = r->f_MyPixels;
MyPitch = r->f_MyPitch;
MyBytesPerPixel = r->f_MyBytesPerPixel;
#endif
MyNSOpnGLCntxt = r->f_MyNSOpnGLCntxt;
GLhOffset = r->f_GLhOffset;
GLvOffset = r->f_GLvOffset;
}
#endif
#if EnableRecreateW
LOCALPROC ReCreateMainWindow(void)
{
MyWState old_state;
MyWState new_state;
blnr HadCursorHidden = HaveCursorHidden;
#if VarFullScreen
if (! UseFullScreen)
#endif
#if MayNotFullScreen
{
/* save old position */
NSRect r =
[NSWindow contentRectForFrameRect: [MyWindow frame]
styleMask: [MyWindow styleMask]];
WinPositionWins[CurWinIndx] = r.origin;
}
#endif
#if MayFullScreen
if (GrabMachine) {
GrabMachine = falseblnr;
UngrabMachine();
}
#endif
CloseMyOpenGLContext();
GetMyWState(&old_state);
ZapMyWState();
#if EnableMagnify
UseMagnify = WantMagnify;
#endif
#if VarFullScreen
UseFullScreen = WantFullScreen;
#endif
if (! CreateMainWindow()) {
CloseMainWindow();
SetMyWState(&old_state);
#if VarFullScreen
if (UseFullScreen) {
My_HideMenuBar();
} else {
My_ShowMenuBar();
}
#endif
/* avoid retry */
#if VarFullScreen
WantFullScreen = UseFullScreen;
#endif
#if EnableMagnify
WantMagnify = UseMagnify;
#endif
} else {
GetMyWState(&new_state);
SetMyWState(&old_state);
CloseMainWindow();
SetMyWState(&new_state);
if (HadCursorHidden) {
(void) MyMoveMouse(CurMouseH, CurMouseV);
}
}
}
#endif
#if VarFullScreen && EnableMagnify
enum {
kWinStateWindowed,
#if EnableMagnify
kWinStateFullScreen,
#endif
kNumWinStates
};
#endif
#if VarFullScreen && EnableMagnify
LOCALVAR int WinMagStates[kNumWinStates];
#endif
LOCALPROC ZapWinStateVars(void)
{
#if MayNotFullScreen
{
int i;
for (i = 0; i < kNumMagStates; ++i) {
HavePositionWins[i] = falseblnr;
}
}
#endif
#if VarFullScreen && EnableMagnify
{
int i;
for (i = 0; i < kNumWinStates; ++i) {
WinMagStates[i] = kMagStateAuto;
}
}
#endif
}
#if VarFullScreen
LOCALPROC ToggleWantFullScreen(void)
{
WantFullScreen = ! WantFullScreen;
#if EnableMagnify
{
int OldWinState =
UseFullScreen ? kWinStateFullScreen : kWinStateWindowed;
int OldMagState =
UseMagnify ? kMagStateMagnifgy : kMagStateNormal;
int NewWinState =
WantFullScreen ? kWinStateFullScreen : kWinStateWindowed;
int NewMagState = WinMagStates[NewWinState];
WinMagStates[OldWinState] = OldMagState;
if (kMagStateAuto != NewMagState) {
WantMagnify = (kMagStateMagnifgy == NewMagState);
} else {
WantMagnify = falseblnr;
if (WantFullScreen) {
NSRect MainScrnBounds = [[NSScreen mainScreen] frame];
if ((MainScrnBounds.size.width
>= vMacScreenWidth * MyWindowScale)
&& (MainScrnBounds.size.height
>= vMacScreenHeight * MyWindowScale)
)
{
WantMagnify = trueblnr;
}
}
}
}
#endif
}
#endif
/* --- SavedTasks --- */
LOCALPROC LeaveBackground(void)
{
ReconnectKeyCodes3();
DisableKeyRepeat();
EmulationWasInterrupted = trueblnr;
}
LOCALPROC EnterBackground(void)
{
RestoreKeyRepeat();
DisconnectKeyCodes3();
ForceShowCursor();
}
LOCALPROC LeaveSpeedStopped(void)
{
#if MySoundEnabled
MySound_Start();
#endif
StartUpTimeAdjust();
}
LOCALPROC EnterSpeedStopped(void)
{
#if MySoundEnabled
MySound_Stop();
#endif
}
#if IncludeSonyNew && ! SaveDialogEnable
LOCALFUNC blnr FindOrMakeNamedChildDirPath(NSString *parentPath,
char *ChildName, NSString **childPath)
{
NSString *r;
BOOL isDir;
Boolean isDirectory;
NSFileManager *fm = [NSFileManager defaultManager];
blnr v = falseblnr;
if (FindNamedChildPath(parentPath, ChildName, &r)) {
if ([fm fileExistsAtPath:r isDirectory: &isDir])
{
if (isDir) {
*childPath = r;
v = trueblnr;
} else {
NSString *RslvPath = MyResolveAlias(r, &isDirectory);
if (nil != RslvPath) {
if (isDirectory) {
*childPath = RslvPath;
v = trueblnr;
}
}
}
} else {
if ([fm respondsToSelector:@selector(
createDirectoryAtPath:withIntermediateDirectories:attributes:error:
)])
{
if ([fm
createDirectoryAtPath:r
withIntermediateDirectories:NO
attributes:nil
error:nil])
{
*childPath = r;
v = trueblnr;
}
} else
if ([fm respondsToSelector:
@selector(createDirectoryAtPath:attributes:)])
{
if ([fm
createDirectoryAtPath:r
attributes:nil])
{
*childPath = r;
v = trueblnr;
}
} else
{
/* fail */
}
}
}
return v;
}
#endif
@interface MyNSSavePanel : NSObject
- (NSInteger)runModalForDirectory:(NSString *)path
file:(NSString *)filename;
- (void)setNameFieldStringValue:(NSString *)value;
@end
#if IncludeSonyNew
LOCALPROC MakeNewDisk(ui5b L, NSString *drivename)
{
#if SaveDialogEnable
NSInteger result = NSCancelButton;
NSSavePanel *panel = [NSSavePanel savePanel];
MyBeginDialog();
if ([panel respondsToSelector:@selector(setNameFieldStringValue:)])
{
#if 0
[panel setNameFieldStringValue: drivename];
/* available as of OS X 10.6 */
#endif
#if 0
[panel performSelector:@selector(setNameFieldStringValue:)
withObject: drivename];
#endif
[((MyNSSavePanel *)panel)
setNameFieldStringValue: drivename];
result = [panel runModal];
} else
if ([panel
respondsToSelector: @selector(runModalForDirectory:file:)])
{
#if 0
result = [panel runModalForDirectory: nil file: drivename];
/*
compiler warns deprecated. To avoid warning, and
to still work if removed from SDK, use NSInvocation.
*/
#endif
#if 0
NSString *sDirName = nil;
SEL sel = @selector(runModalForDirectory:file:);
NSInvocation* invoc =
[NSInvocation invocationWithMethodSignature:
[panel methodSignatureForSelector: sel]];
[invoc setTarget:panel];
[invoc setSelector:sel];
[invoc setArgument:&sDirName atIndex:2];
[invoc setArgument:&drivename atIndex:3];
[invoc invoke];
[invoc getReturnValue: &result];
#endif
/* an easier way ? seems to work */
result = [((MyNSSavePanel *)panel)
runModalForDirectory: nil file: drivename];
} else
{
/* fail */
}
MyEndDialog();
if (NSOKButton == result) {
NSString* filePath = [[panel URL] path];
MakeNewDisk0(L, filePath);
}
#else /* SaveDialogEnable */
NSString *sPath;
if (FindOrMakeNamedChildDirPath(MyDataPath, "out", &sPath)) {
NSString *filePath =
[sPath stringByAppendingPathComponent: drivename];
MakeNewDisk0(L, filePath);
}
#endif /* SaveDialogEnable */
}
#endif
#if IncludeSonyNew
LOCALPROC MakeNewDiskAtDefault(ui5b L)
{
MakeNewDisk(L, @"untitled.dsk");
}
#endif
LOCALPROC CheckForSavedTasks(void)
{
if (MyEvtQNeedRecover) {
MyEvtQNeedRecover = falseblnr;
/* attempt cleanup, MyEvtQNeedRecover may get set again */
MyEvtQTryRecoverFromFull();
}
if (RequestMacOff) {
RequestMacOff = falseblnr;
if (AnyDiskInserted()) {
MacMsgOverride(kStrQuitWarningTitle,
kStrQuitWarningMessage);
} else {
ForceMacOff = trueblnr;
}
}
if (ForceMacOff) {
return;
}
if (gTrueBackgroundFlag != gBackgroundFlag) {
gBackgroundFlag = gTrueBackgroundFlag;
if (gTrueBackgroundFlag) {
EnterBackground();
} else {
LeaveBackground();
}
}
if (EmulationWasInterrupted) {
EmulationWasInterrupted = falseblnr;
if (! gTrueBackgroundFlag) {
CheckMouseState();
}
}
#if EnableFSMouseMotion
if (HaveMouseMotion) {
MyMouseConstrain();
}
#endif
#if VarFullScreen
if (gTrueBackgroundFlag && WantFullScreen) {
ToggleWantFullScreen();
}
#endif
if (WantScreensChangedCheck) {
WantScreensChangedCheck = falseblnr;
MyUpdateOpenGLContext();
#if VarFullScreen
/*
triggered on enter full screen for some
reason in OS X 10.11. so check against
saved rect.
*/
if ((WantFullScreen)
&& (! NSEqualRects(SavedScrnBounds,
[[NSScreen mainScreen] frame])))
{
ToggleWantFullScreen();
}
#endif
}
if (CurSpeedStopped != (SpeedStopped ||
(gBackgroundFlag && ! RunInBackground
#if EnableAutoSlow && 0
&& (QuietSubTicks >= 4092)
#endif
)))
{
CurSpeedStopped = ! CurSpeedStopped;
if (CurSpeedStopped) {
EnterSpeedStopped();
} else {
LeaveSpeedStopped();
}
}
if ((nullpr != SavedBriefMsg) & ! MacMsgDisplayed) {
MacMsgDisplayOn();
}
#if EnableRecreateW
if (0
#if EnableMagnify
|| (UseMagnify != WantMagnify)
#endif
#if VarFullScreen
|| (UseFullScreen != WantFullScreen)
#endif
)
{
ReCreateMainWindow();
}
#endif
#if MayFullScreen
if (GrabMachine != (
#if VarFullScreen
UseFullScreen &&
#endif
! (gTrueBackgroundFlag || CurSpeedStopped)))
{
GrabMachine = ! GrabMachine;
AdjustMachineGrab();
}
#endif
#if IncludeSonyNew
if (vSonyNewDiskWanted) {
#if IncludeSonyNameNew
if (vSonyNewDiskName != NotAPbuf) {
NSString *sNewDiskName;
if (MacRomanFileNameToNSString(vSonyNewDiskName,
&sNewDiskName))
{
MakeNewDisk(vSonyNewDiskSize, sNewDiskName);
}
PbufDispose(vSonyNewDiskName);
vSonyNewDiskName = NotAPbuf;
} else
#endif
{
MakeNewDiskAtDefault(vSonyNewDiskSize);
}
vSonyNewDiskWanted = falseblnr;
/* must be done after may have gotten disk */
}
#endif
if (NeedWholeScreenDraw) {
NeedWholeScreenDraw = falseblnr;
ScreenChangedAll();
}
if (! gTrueBackgroundFlag) {
if (RequestInsertDisk) {
RequestInsertDisk = falseblnr;
InsertADisk0();
}
}
#if NeedRequestIthDisk
if (0 != RequestIthDisk) {
Sony_InsertIth(RequestIthDisk);
RequestIthDisk = 0;
}
#endif
if (HaveCursorHidden != (
#if MayNotFullScreen
(WantCursorHidden
#if VarFullScreen
|| UseFullScreen
#endif
) &&
#endif
! (gTrueBackgroundFlag || CurSpeedStopped)))
{
HaveCursorHidden = ! HaveCursorHidden;
if (HaveCursorHidden) {
MyHideCursor();
} else {
MyShowCursor();
}
}
#if 1
/*
Check if actual cursor visibility is what it should be.
If move mouse to dock then cursor is made visible, but then
if move directly to our window, cursor is not hidden again.
*/
if (HaveMyCGCursorIsVisible()) {
/* but only in OS X 10.3 and later */
/* deprecated in cocoa, but no alternative (?) */
if (MyCGCursorIsVisible()) {
if (HaveCursorHidden) {
MyHideCursor();
if (MyCGCursorIsVisible()) {
/*
didn't work, attempt undo so that
hide cursor count won't get large
*/
MyShowCursor();
}
}
} else {
if (! HaveCursorHidden) {
MyShowCursor();
/*
don't check if worked, assume can't decrement
hide cursor count below 0
*/
}
}
}
#endif
}
/* --- main program flow --- */
GLOBALOSGLUFUNC blnr ExtraTimeNotOver(void)
{
UpdateTrueEmulatedTime();
return TrueEmulatedTime == OnTrueTime;
}
LOCALPROC ProcessEventModifiers(NSEvent *event)
{
NSUInteger newMods = [event modifierFlags];
MyUpdateKeyboardModifiers(newMods);
}
LOCALPROC ProcessEventLocation(NSEvent *event)
{
NSPoint p = [event locationInWindow];
NSWindow *w = [event window];
if (w != MyWindow) {
if (nil != w) {
p = [w convertBaseToScreen: p];
}
p = [MyWindow convertScreenToBase: p];
}
p = [MyNSview convertPoint: p fromView: nil];
p.y = [MyNSview frame].size.height - p.y;
MousePositionNotify((int) p.x, (int) p.y);
}
LOCALPROC ProcessKeyEvent(blnr down, NSEvent *event)
{
ui3r scancode = [event keyCode];
ProcessEventModifiers(event);
Keyboard_UpdateKeyMap2(Keyboard_RemapMac(scancode), down);
}
LOCALPROC ProcessOneSystemEvent(NSEvent *event)
{
switch ([event type]) {
case NSLeftMouseDown:
case NSRightMouseDown:
case NSOtherMouseDown:
/*
int button = QZ_OtherMouseButtonToSDL(
[event buttonNumber]);
*/
ProcessEventLocation(event);
ProcessEventModifiers(event);
if (([event window] == MyWindow)
&& (! gTrueBackgroundFlag)
#if MayNotFullScreen
&& (WantCursorHidden
#if VarFullScreen
|| UseFullScreen
#endif
)
#endif
)
{
MyMouseButtonSet(trueblnr);
} else {
/* doesn't belong to us */
[NSApp sendEvent: event];
}
break;
case NSLeftMouseUp:
case NSRightMouseUp:
case NSOtherMouseUp:
/*
int button = QZ_OtherMouseButtonToSDL(
[event buttonNumber]);
*/
ProcessEventLocation(event);
ProcessEventModifiers(event);
if (! MyMouseButtonState) {
/* doesn't belong to us */
[NSApp sendEvent: event];
} else {
MyMouseButtonSet(falseblnr);
}
break;
case NSMouseMoved:
{
ProcessEventLocation(event);
ProcessEventModifiers(event);
}
break;
case NSLeftMouseDragged:
case NSRightMouseDragged:
case NSOtherMouseDragged:
if (! MyMouseButtonState) {
/* doesn't belong to us ? */
[NSApp sendEvent: event];
} else {
ProcessEventLocation(event);
ProcessEventModifiers(event);
}
break;
case NSKeyUp:
ProcessKeyEvent(falseblnr, event);
break;
case NSKeyDown:
ProcessKeyEvent(trueblnr, event);
break;
case NSFlagsChanged:
ProcessEventModifiers(event);
break;
/* case NSScrollWheel: */
/* case NSSystemDefined: */
/* case NSAppKitDefined: */
/* case NSApplicationDefined: */
/* case NSPeriodic: */
/* case NSCursorUpdate: */
default:
[NSApp sendEvent: event];
}
}
GLOBALOSGLUPROC WaitForNextTick(void)
{
NSDate *TheUntil;
int i;
NSEvent *event;
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
NSDate *TheDistantFuture = [NSDate distantFuture];
NSDate *TheDistantPast = [NSDate distantPast];
#if 0
NSDate *TheNextTick = [NSDate
dateWithTimeIntervalSinceReferenceDate: NextTickChangeTime];
#endif
TheUntil = TheDistantPast;
label_retry:
i = 32;
while ((--i >= 0) && (nil != (event =
[NSApp nextEventMatchingMask: NSAnyEventMask
untilDate: TheUntil
inMode: NSDefaultRunLoopMode
dequeue: YES])))
{
ProcessOneSystemEvent(event);
TheUntil = TheDistantPast;
}
CheckForSavedTasks();
if (ForceMacOff) {
goto label_exit;
}
if (CurSpeedStopped) {
DoneWithDrawingForTick();
TheUntil = TheDistantFuture;
goto label_retry;
}
if (ExtraTimeNotOver()) {
#if 1
#if 0 && EnableAutoSlow
if ((QuietSubTicks >= 16384)
&& (QuietTime >= 34)
&& ! WantNotAutoSlow)
{
TheUntil = [NSDate
dateWithTimeIntervalSinceReferenceDate:
(NextTickChangeTime + 0.50)];
} else
#endif
{
NSTimeInterval inTimeout =
NextTickChangeTime - LatestTime;
if (inTimeout > 0.0) {
struct timespec rqt;
struct timespec rmt;
rqt.tv_sec = 0;
rqt.tv_nsec = inTimeout * 1000000000.0;
(void) nanosleep(&rqt, &rmt);
}
TheUntil = TheDistantPast;
}
#else
/*
This has higher overhead.
*/
TheUntil = TheNextTick;
#endif
goto label_retry;
}
#if 0
if (! gTrueBackgroundFlag) {
CheckMouseState();
}
#endif
if (CheckDateTime()) {
#if MySoundEnabled
MySound_SecondNotify();
#endif
#if EnableDemoMsg
DemoModeSecondNotify();
#endif
}
OnTrueTime = TrueEmulatedTime;
#if dbglog_TimeStuff
dbglog_writelnNum("WaitForNextTick, OnTrueTime", OnTrueTime);
#endif
label_exit:
[pool release];
}
typedef Boolean (*SecTranslocateIsTranslocatedURL_t)(
CFURLRef path, bool *isTranslocated, CFErrorRef * error);
typedef CFURLRef (*SecTranslocateCreateOriginalPathForURL_t)(
CFURLRef translocatedPath, CFErrorRef * error);
LOCALFUNC blnr setupWorkingDirectory(void)
{
NSString *myAppDir;
NSString *contentsPath;
NSString *dataPath;
NSBundle *myBundle = [NSBundle mainBundle];
NSString *myAppPath = [myBundle bundlePath];
#if WantUnTranslocate
{
bool isTranslocated;
void *sec_handle = NULL;
SecTranslocateIsTranslocatedURL_t
mySecTranslocateIsTranslocatedURL = NULL;
CFURLRef url = NULL;
SecTranslocateCreateOriginalPathForURL_t
mySecTranslocateCreateOriginalPathForURL = NULL;
CFURLRef untranslocatedURL = NULL;
NSString *realAppPath = NULL;
if (NULL == (sec_handle = dlopen(
"/System/Library/Frameworks/Security.framework/Security",
RTLD_LAZY)))
{
/* fail */
} else
if (NULL == (mySecTranslocateIsTranslocatedURL =
dlsym(sec_handle, "SecTranslocateIsTranslocatedURL")))
{
/* fail */
} else
if (NULL == (url =
CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
(CFStringRef)myAppPath, kCFURLPOSIXPathStyle, NO)))
{
/* fail */
} else
if (! mySecTranslocateIsTranslocatedURL(url, &isTranslocated,
NULL))
{
/* fail */
} else
if (! isTranslocated) {
/* done */
} else
if (NULL == (mySecTranslocateCreateOriginalPathForURL =
dlsym(sec_handle,
"SecTranslocateCreateOriginalPathForURL")))
{
/* fail */
} else
if (NULL == (untranslocatedURL =
mySecTranslocateCreateOriginalPathForURL(url, NULL)))
{
/* fail */
} else
if (NULL == (realAppPath =
(NSString *)CFURLCopyFileSystemPath(
untranslocatedURL, kCFURLPOSIXPathStyle)))
{
/* fail */
} else
{
myAppPath = realAppPath;
}
if (NULL != realAppPath) {
[realAppPath autorelease];
}
if (NULL != untranslocatedURL) {
CFRelease(untranslocatedURL);
}
if (NULL != url) {
CFRelease(url);
}
if (NULL != sec_handle) {
if (0 != dlclose(sec_handle)) {
/* dbglog_writeln("dlclose failed"); */
}
}
}
#endif /* WantUnTranslocate */
myAppDir = [myAppPath stringByDeletingLastPathComponent];
myAppName = [[[myAppPath lastPathComponent]
stringByDeletingPathExtension] retain];
MyDataPath = myAppDir;
if (FindNamedChildDirPath(myAppPath, "Contents", &contentsPath))
if (FindNamedChildDirPath(contentsPath, "mnvm_dat", &dataPath))
{
MyDataPath = dataPath;
}
[MyDataPath retain];
return trueblnr;
}
@interface MyClassApplicationDelegate : NSObject <NSApplicationDelegate>
@end
@implementation MyClassApplicationDelegate
- (BOOL)application:(NSApplication *)theApplication
openFile:(NSString *)filename
{
(void) Sony_Insert1a(filename);
return TRUE;
}
- (void) applicationDidFinishLaunching: (NSNotification *) note
{
[NSApp stop: nil]; /* stop immediately */
{
/*
doesn't actually stop until an event, so make one.
(As suggested by Michiel de Hoon in
http://www.cocoabuilder.com/ post.)
*/
NSEvent* event = [NSEvent
otherEventWithType: NSApplicationDefined
location: NSMakePoint(0, 0)
modifierFlags: 0
timestamp: 0.0
windowNumber: 0
context: nil
subtype: 0
data1: 0
data2: 0];
[NSApp postEvent: event atStart: true];
}
}
- (void)applicationDidChangeScreenParameters:
(NSNotification *)aNotification
{
WantScreensChangedCheck = trueblnr;
}
- (IBAction)performSpecialMoreCommands:(id)sender
{
DoMoreCommandsMsg();
}
- (IBAction)performFileOpen:(id)sender
{
RequestInsertDisk = trueblnr;
}
- (IBAction)performApplicationAbout:(id)sender
{
DoAboutMsg();
}
@end
LOCALVAR MyClassApplicationDelegate *MyApplicationDelegate = nil;
LOCALFUNC blnr InitCocoaStuff(void)
{
NSApplication *MyNSApp = [NSApplication sharedApplication];
/*
in Xcode 6.2, MyNSApp isn't the same as NSApp,
breaks NSApp setDelegate
*/
MyMenuSetup();
MyApplicationDelegate = [[MyClassApplicationDelegate alloc] init];
[MyNSApp setDelegate: MyApplicationDelegate];
#if 0
[MyNSApp finishLaunching];
#endif
/*
If use finishLaunching, after
Hide Mini vMac command, activating from
Dock doesn't bring our window forward.
Using "run" instead fixes this.
As suggested by Hugues De Keyzer in
http://forums.libsdl.org/ post.
SDL 2.0 doesn't use this
technique. Was another solution found?
*/
[MyNSApp run];
/*
our applicationDidFinishLaunching forces
immediate halt.
*/
return trueblnr;
}
LOCALPROC UnInitCocoaStuff(void)
{
if (nil != MyApplicationDelegate) {
[MyApplicationDelegate release];
}
if (nil != myAppName) {
[myAppName release];
}
if (nil != MyDataPath) {
[MyDataPath release];
}
}
/* --- platform independent code can be thought of as going here --- */
#include "PROGMAIN.h"
LOCALPROC ZapOSGLUVars(void)
{
InitDrives();
ZapWinStateVars();
#if MySoundEnabled
ZapAudioVars();
#endif
}
LOCALPROC ReserveAllocAll(void)
{
#if dbglog_HAVE
dbglog_ReserveAlloc();
#endif
ReserveAllocOneBlock(&ROM, kROM_Size, 5, falseblnr);
ReserveAllocOneBlock(&screencomparebuff,
vMacScreenNumBytes, 5, trueblnr);
#if UseControlKeys
ReserveAllocOneBlock(&CntrlDisplayBuff,
vMacScreenNumBytes, 5, falseblnr);
#endif
ReserveAllocOneBlock(&ScalingBuff, vMacScreenNumPixels
#if 0 != vMacScreenDepth
* 4
#endif
, 5, falseblnr);
ReserveAllocOneBlock(&CLUT_final, CLUT_finalsz, 5, falseblnr);
#if MySoundEnabled
ReserveAllocOneBlock((ui3p *)&TheSoundBuffer,
dbhBufferSize, 5, falseblnr);
#endif
EmulationReserveAlloc();
}
LOCALFUNC blnr AllocMyMemory(void)
{
#if 0 /* for testing start up error reporting */
MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, trueblnr);
return falseblnr;
#else
uimr n;
blnr IsOk = falseblnr;
ReserveAllocOffset = 0;
ReserveAllocBigBlock = nullpr;
ReserveAllocAll();
n = ReserveAllocOffset;
ReserveAllocBigBlock = (ui3p)calloc(1, n);
if (NULL == ReserveAllocBigBlock) {
MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, trueblnr);
} else {
ReserveAllocOffset = 0;
ReserveAllocAll();
if (n != ReserveAllocOffset) {
/* oops, program error */
} else {
IsOk = trueblnr;
}
}
return IsOk;
#endif
}
LOCALPROC UnallocMyMemory(void)
{
if (nullpr != ReserveAllocBigBlock) {
free((char *) ReserveAllocBigBlock);
}
}
LOCALFUNC blnr InitOSGLU(void)
{
blnr IsOk = falseblnr;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
if (AllocMyMemory())
if (setupWorkingDirectory())
#if dbglog_HAVE
if (dbglog_open())
#endif
#if MySoundEnabled
if (MySound_Init())
/* takes a while to stabilize, do as soon as possible */
#endif
if (LoadMacRom())
if (LoadInitialImages())
if (InitCocoaStuff())
/*
Can get openFile call backs here
for initial files.
So must load ROM, disk1.dsk, etc first.
*/
#if UseActvCode
if (ActvCodeInit())
#endif
#if EmLocalTalk
if (InitLocalTalk())
#endif
if (InitLocationDat())
if (Screen_Init())
if (CreateMainWindow())
if (WaitForRom())
{
IsOk = trueblnr;
}
[pool release];
return IsOk;
}
#if dbglog_HAVE && 0
IMPORTPROC DumpRTC(void);
#endif
LOCALPROC UnInitOSGLU(void)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
#if dbglog_HAVE && 0
DumpRTC();
#endif
if (MacMsgDisplayed) {
MacMsgDisplayOff();
}
RestoreKeyRepeat();
#if MayFullScreen
UngrabMachine();
#endif
#if MySoundEnabled
MySound_Stop();
#endif
#if MySoundEnabled
MySound_UnInit();
#endif
#if IncludePbufs
UnInitPbufs();
#endif
UnInitDrives();
ForceShowCursor();
#if dbglog_HAVE
dbglog_close();
#endif
CheckSavedMacMsg();
CloseMyOpenGLContext();
CloseMainWindow();
#if MayFullScreen
My_ShowMenuBar();
#endif
UnInitCocoaStuff();
UnallocMyMemory();
[pool release];
}
int main(int argc, char **argv)
{
ZapOSGLUVars();
if (InitOSGLU()) {
ProgramMain();
}
UnInitOSGLU();
return 0;
}