4215 lines
94 KiB
C
4215 lines
94 KiB
C
/*
|
|
OSGLUSD2.c
|
|
|
|
Copyright (C) 2012 Paul C. Pratt, Manuel Alfayate
|
|
|
|
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 SDl 2.0 library
|
|
|
|
All operating system dependent code for the
|
|
SDL Library should go here.
|
|
*/
|
|
|
|
#include "CNFGRAPI.h"
|
|
#include "SYSDEPNS.h"
|
|
#include "ENDIANAC.h"
|
|
|
|
#include "UI/MYOSGLUE.h"
|
|
|
|
#include "STRCONST.h"
|
|
|
|
/* --- some simple utilities --- */
|
|
|
|
GLOBALOSGLUPROC MoveBytes(anyp srcPtr, anyp destPtr, int32_t byteCount)
|
|
{
|
|
(void) memcpy((char *)destPtr, (char *)srcPtr, byteCount);
|
|
}
|
|
|
|
/* --- control mode and internationalization --- */
|
|
|
|
#define NeedCell2PlainAsciiMap 1
|
|
|
|
#include "INTLCHAR.h"
|
|
|
|
#ifndef CanGetAppPath
|
|
#define CanGetAppPath 1
|
|
#endif
|
|
|
|
LOCALVAR char *d_arg = NULL;
|
|
LOCALVAR char *n_arg = NULL;
|
|
|
|
#if CanGetAppPath
|
|
LOCALVAR char *app_parent = NULL;
|
|
LOCALVAR char *pref_dir = NULL;
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
#define PathSep '\\'
|
|
#else
|
|
#define PathSep '/'
|
|
#endif
|
|
|
|
LOCALFUNC tMacErr ChildPath(char *x, char *y, char **r)
|
|
{
|
|
tMacErr err = mnvm_miscErr;
|
|
int nx = strlen(x);
|
|
int ny = strlen(y);
|
|
{
|
|
if ((nx > 0) && (PathSep == x[nx - 1])) {
|
|
--nx;
|
|
}
|
|
{
|
|
int nr = nx + 1 + ny;
|
|
char *p = malloc(nr + 1);
|
|
if (p != NULL) {
|
|
char *p2 = p;
|
|
(void) memcpy(p2, x, nx);
|
|
p2 += nx;
|
|
*p2++ = PathSep;
|
|
(void) memcpy(p2, y, ny);
|
|
p2 += ny;
|
|
*p2 = 0;
|
|
*r = p;
|
|
err = mnvm_noErr;
|
|
}
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
LOCALPROC MayFree(char *p)
|
|
{
|
|
if (NULL != p) {
|
|
free(p);
|
|
}
|
|
}
|
|
|
|
/* --- sending debugging info to file --- */
|
|
|
|
#if dbglog_HAVE
|
|
|
|
#ifndef dbglog_ToStdErr
|
|
#define dbglog_ToStdErr 0
|
|
#endif
|
|
#ifndef dbglog_ToSDL_Log
|
|
#define dbglog_ToSDL_Log 0
|
|
#endif
|
|
|
|
#if ! dbglog_ToStdErr
|
|
LOCALVAR FILE *dbglog_File = NULL;
|
|
#endif
|
|
|
|
LOCALFUNC bool dbglog_open0(void)
|
|
{
|
|
#if dbglog_ToStdErr || dbglog_ToSDL_Log
|
|
return true;
|
|
#else
|
|
if (NULL == app_parent) {
|
|
dbglog_File = fopen("dbglog.txt", "w");
|
|
} else {
|
|
char *t;
|
|
|
|
if (mnvm_noErr == ChildPath(app_parent, "dbglog.txt", &t)) {
|
|
dbglog_File = fopen(t, "w");
|
|
free(t);
|
|
}
|
|
}
|
|
|
|
return (NULL != dbglog_File);
|
|
#endif
|
|
}
|
|
|
|
LOCALPROC dbglog_write0(char *s, uimr L)
|
|
{
|
|
#if dbglog_ToStdErr
|
|
(void) fwrite(s, 1, L, stderr);
|
|
#elif dbglog_ToSDL_Log
|
|
char t[256 + 1];
|
|
|
|
if (L > 256) {
|
|
L = 256;
|
|
}
|
|
(void) memcpy(t, s, L);
|
|
t[L] = 1;
|
|
|
|
SDL_Log("%s", t);
|
|
#else
|
|
if (dbglog_File != NULL) {
|
|
(void) fwrite(s, 1, L, dbglog_File);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
LOCALPROC dbglog_close0(void)
|
|
{
|
|
#if ! dbglog_ToStdErr
|
|
if (dbglog_File != NULL) {
|
|
fclose(dbglog_File);
|
|
dbglog_File = NULL;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#endif
|
|
|
|
/* --- information about the environment --- */
|
|
|
|
#define WantColorTransValid 0
|
|
|
|
#include "COMOSGLU.h"
|
|
|
|
#include "PBUFSTDC.h"
|
|
|
|
#include "CONTROLM.h"
|
|
|
|
/* --- text translation --- */
|
|
|
|
LOCALPROC NativeStrFromCStr(char *r, char *s)
|
|
{
|
|
uint8_t ps[ClStrMaxLength];
|
|
int i;
|
|
int L;
|
|
|
|
ClStrFromSubstCStr(&L, ps, s);
|
|
|
|
for (i = 0; i < L; ++i) {
|
|
r[i] = Cell2PlainAsciiMap[ps[i]];
|
|
}
|
|
|
|
r[L] = 0;
|
|
}
|
|
|
|
/* --- drives --- */
|
|
|
|
#define NotAfileRef NULL
|
|
|
|
#ifndef UseRWops
|
|
#define UseRWops 0
|
|
#endif
|
|
|
|
#if UseRWops
|
|
#define FilePtr SDL_RWops *
|
|
#define Seek SDL_RWseek
|
|
#define SeekSet RW_SEEK_SET
|
|
#define SeekCur RW_SEEK_CUR
|
|
#define SeekEnd RW_SEEK_END
|
|
#define FileRead(ptr, size, nmemb, stream) \
|
|
SDL_RWread(stream, ptr, size, nmemb)
|
|
#define FileWrite(ptr, size, nmemb, stream) \
|
|
SDL_RWwrite(stream, ptr, size, nmemb)
|
|
#define FileTell SDL_RWtell
|
|
#define FileClose SDL_RWclose
|
|
#define FileOpen SDL_RWFromFile
|
|
#else
|
|
#define FilePtr FILE *
|
|
#define Seek fseek
|
|
#define SeekSet SEEK_SET
|
|
#define SeekCur SEEK_CUR
|
|
#define SeekEnd SEEK_END
|
|
#define FileRead fread
|
|
#define FileWrite fwrite
|
|
#define FileTell ftell
|
|
#define FileClose fclose
|
|
#define FileOpen fopen
|
|
#define FileEof feof
|
|
#endif
|
|
|
|
LOCALVAR FilePtr Drives[NumDrives]; /* open disk image files */
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
GLOBALOSGLUFUNC tMacErr vSonyTransfer(bool IsWrite, uint8_t * Buffer,
|
|
tDrive Drive_No, uint32_t Sony_Start, uint32_t Sony_Count,
|
|
uint32_t *Sony_ActCount)
|
|
{
|
|
tMacErr err = mnvm_miscErr;
|
|
FilePtr refnum = Drives[Drive_No];
|
|
uint32_t NewSony_Count = 0;
|
|
|
|
if (Seek(refnum, Sony_Start, SeekSet) >= 0) {
|
|
if (IsWrite) {
|
|
NewSony_Count = FileWrite(Buffer, 1, Sony_Count, refnum);
|
|
} else {
|
|
NewSony_Count = FileRead(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, uint32_t *Sony_Count)
|
|
{
|
|
tMacErr err = mnvm_miscErr;
|
|
FilePtr refnum = Drives[Drive_No];
|
|
long v;
|
|
|
|
if (Seek(refnum, 0, SeekEnd) >= 0) {
|
|
v = FileTell(refnum);
|
|
if (v >= 0) {
|
|
*Sony_Count = v;
|
|
err = mnvm_noErr;
|
|
}
|
|
}
|
|
|
|
return err; /*& figure out what really to return &*/
|
|
}
|
|
|
|
LOCALFUNC tMacErr vSonyEject0(tDrive Drive_No, bool deleteit)
|
|
{
|
|
FilePtr refnum = Drives[Drive_No];
|
|
|
|
DiskEjectedNotify(Drive_No);
|
|
|
|
FileClose(refnum);
|
|
Drives[Drive_No] = NotAfileRef; /* not really needed */
|
|
|
|
return mnvm_noErr;
|
|
}
|
|
|
|
GLOBALOSGLUFUNC tMacErr vSonyEject(tDrive Drive_No)
|
|
{
|
|
return vSonyEject0(Drive_No, false);
|
|
}
|
|
|
|
LOCALPROC UnInitDrives(void)
|
|
{
|
|
tDrive i;
|
|
|
|
for (i = 0; i < NumDrives; ++i) {
|
|
if (vSonyIsInserted(i)) {
|
|
(void) vSonyEject(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
LOCALFUNC bool Sony_Insert0(FilePtr refnum, bool locked,
|
|
char *drivepath)
|
|
{
|
|
tDrive Drive_No;
|
|
bool IsOk = false;
|
|
|
|
if (! FirstFreeDisk(&Drive_No)) {
|
|
MacMsg(kStrTooManyImagesTitle, kStrTooManyImagesMessage,
|
|
false);
|
|
} else {
|
|
/* printf("Sony_Insert0 %d\n", (int)Drive_No); */
|
|
|
|
{
|
|
Drives[Drive_No] = refnum;
|
|
DiskInsertNotify(Drive_No, locked);
|
|
|
|
IsOk = true;
|
|
}
|
|
}
|
|
|
|
if (! IsOk) {
|
|
FileClose(refnum);
|
|
}
|
|
|
|
return IsOk;
|
|
}
|
|
|
|
LOCALFUNC bool Sony_Insert1(char *drivepath, bool silentfail)
|
|
{
|
|
bool locked = false;
|
|
/* printf("Sony_Insert1 %s\n", drivepath); */
|
|
FilePtr refnum = FileOpen(drivepath, "rb+");
|
|
if (NULL == refnum) {
|
|
locked = true;
|
|
refnum = FileOpen(drivepath, "rb");
|
|
}
|
|
if (NULL == refnum) {
|
|
if (! silentfail) {
|
|
MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, false);
|
|
}
|
|
} else {
|
|
return Sony_Insert0(refnum, locked, drivepath);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
LOCALFUNC tMacErr LoadMacRomFrom(char *path)
|
|
{
|
|
tMacErr err;
|
|
FilePtr ROM_File;
|
|
int File_Size;
|
|
|
|
ROM_File = FileOpen(path, "rb");
|
|
if (NULL == ROM_File) {
|
|
err = mnvm_fnfErr;
|
|
} else {
|
|
File_Size = FileRead(ROM, 1, kROM_Size, ROM_File);
|
|
if (File_Size != kROM_Size) {
|
|
#ifdef FileEof
|
|
if (FileEof(ROM_File))
|
|
#else
|
|
if (File_Size > 0)
|
|
#endif
|
|
{
|
|
MacMsgOverride(kStrShortROMTitle,
|
|
kStrShortROMMessage);
|
|
err = mnvm_eofErr;
|
|
} else {
|
|
MacMsgOverride(kStrNoReadROMTitle,
|
|
kStrNoReadROMMessage);
|
|
err = mnvm_miscErr;
|
|
}
|
|
} else {
|
|
err = ROM_IsValid();
|
|
}
|
|
FileClose(ROM_File);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
LOCALFUNC bool Sony_Insert1a(char *drivepath, bool silentfail)
|
|
{
|
|
bool v;
|
|
|
|
if (! ROM_loaded) {
|
|
v = (mnvm_noErr == LoadMacRomFrom(drivepath));
|
|
} else {
|
|
v = Sony_Insert1(drivepath, silentfail);
|
|
}
|
|
|
|
return v;
|
|
}
|
|
|
|
LOCALFUNC bool Sony_Insert2(char *s)
|
|
{
|
|
char *d =
|
|
#if CanGetAppPath
|
|
(NULL == d_arg) ? app_parent :
|
|
#endif
|
|
d_arg;
|
|
bool IsOk = false;
|
|
|
|
if (NULL == d) {
|
|
IsOk = Sony_Insert1(s, true);
|
|
} else {
|
|
char *t;
|
|
|
|
if (mnvm_noErr == ChildPath(d, s, &t)) {
|
|
IsOk = Sony_Insert1(t, true);
|
|
free(t);
|
|
}
|
|
}
|
|
|
|
return IsOk;
|
|
}
|
|
|
|
LOCALFUNC bool Sony_InsertIth(int i)
|
|
{
|
|
bool v;
|
|
|
|
if ((i > 9) || ! FirstFreeDisk(nullpr)) {
|
|
v = false;
|
|
} else {
|
|
char s[] = "disk?.dsk";
|
|
|
|
s[4] = '0' + i;
|
|
|
|
v = Sony_Insert2(s);
|
|
}
|
|
|
|
return v;
|
|
}
|
|
|
|
LOCALFUNC bool LoadInitialImages(void)
|
|
{
|
|
if (! AnyDiskInserted()) {
|
|
int i;
|
|
|
|
for (i = 1; Sony_InsertIth(i); ++i) {
|
|
/* stop on first error (including file not found) */
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/* --- ROM --- */
|
|
|
|
LOCALVAR char *rom_path = NULL;
|
|
|
|
#if CanGetAppPath
|
|
LOCALFUNC tMacErr LoadMacRomFromPrefDir(void)
|
|
{
|
|
tMacErr err;
|
|
char *t = NULL;
|
|
char *t2 = NULL;
|
|
|
|
if (NULL == pref_dir) {
|
|
err = mnvm_fnfErr;
|
|
} else
|
|
if (mnvm_noErr != (err =
|
|
ChildPath(pref_dir, "mnvm_rom", &t)))
|
|
{
|
|
/* fail */
|
|
} else
|
|
if (mnvm_noErr != (err =
|
|
ChildPath(t, RomFileName, &t2)))
|
|
{
|
|
/* fail */
|
|
} else
|
|
{
|
|
err = LoadMacRomFrom(t2);
|
|
}
|
|
|
|
MayFree(t2);
|
|
MayFree(t);
|
|
|
|
return err;
|
|
}
|
|
#endif
|
|
|
|
#if CanGetAppPath
|
|
LOCALFUNC tMacErr LoadMacRomFromAppPar(void)
|
|
{
|
|
tMacErr err;
|
|
char *d = (NULL == d_arg) ? app_parent : d_arg;
|
|
char *t = NULL;
|
|
|
|
if (NULL == d) {
|
|
err = mnvm_fnfErr;
|
|
} else
|
|
if (mnvm_noErr != (err =
|
|
ChildPath(d, RomFileName, &t)))
|
|
{
|
|
/* fail */
|
|
} else
|
|
{
|
|
err = LoadMacRomFrom(t);
|
|
}
|
|
|
|
MayFree(t);
|
|
|
|
return err;
|
|
}
|
|
#endif
|
|
|
|
LOCALFUNC bool LoadMacRom(void)
|
|
{
|
|
tMacErr err;
|
|
|
|
if ((NULL == rom_path)
|
|
|| (mnvm_fnfErr == (err = LoadMacRomFrom(rom_path))))
|
|
#if CanGetAppPath
|
|
if (mnvm_fnfErr == (err = LoadMacRomFromAppPar()))
|
|
if (mnvm_fnfErr == (err = LoadMacRomFromPrefDir()))
|
|
#endif
|
|
if (mnvm_fnfErr == (err = LoadMacRomFrom(RomFileName)))
|
|
{
|
|
}
|
|
|
|
return true; /* keep launching Mini vMac, regardless */
|
|
}
|
|
|
|
/* --- video out --- */
|
|
|
|
#if MayFullScreen
|
|
LOCALVAR int hOffset;
|
|
LOCALVAR int vOffset;
|
|
#endif
|
|
|
|
#if VarFullScreen
|
|
LOCALVAR bool UseFullScreen = (WantInitFullScreen != 0);
|
|
#endif
|
|
|
|
#if EnableMagnify
|
|
LOCALVAR bool UseMagnify = (WantInitMagnify != 0);
|
|
#endif
|
|
|
|
#ifndef UseSDLscaling
|
|
#define UseSDLscaling 0
|
|
#endif
|
|
|
|
LOCALVAR bool gBackgroundFlag = false;
|
|
LOCALVAR bool gTrueBackgroundFlag = false;
|
|
LOCALVAR bool CurSpeedStopped = true;
|
|
|
|
#if EnableMagnify && ! UseSDLscaling
|
|
#define MaxScale WindowScale
|
|
#else
|
|
#define MaxScale 1
|
|
#endif
|
|
|
|
|
|
LOCALVAR SDL_Window *main_wind = NULL;
|
|
LOCALVAR SDL_Renderer *renderer = NULL;
|
|
LOCALVAR SDL_Texture *texture = NULL;
|
|
LOCALVAR SDL_PixelFormat *format = NULL;
|
|
|
|
LOCALVAR uint8_t * ScalingBuff = nullpr;
|
|
|
|
LOCALVAR uint8_t * CLUT_final;
|
|
|
|
#define CLUT_finalsz (256 * 8 * 4 * MaxScale)
|
|
/*
|
|
256 possible values of one byte
|
|
8 pixels per byte maximum (when black and white)
|
|
4 bytes per destination pixel maximum
|
|
multiplied by WindowScale if EnableMagnify
|
|
*/
|
|
|
|
#define ScrnMapr_DoMap UpdateBWDepth3Copy
|
|
#define ScrnMapr_Src GetCurDrawBuff()
|
|
#define ScrnMapr_Dst ScalingBuff
|
|
#define ScrnMapr_SrcDepth 0
|
|
#define ScrnMapr_DstDepth 3
|
|
#define ScrnMapr_Map CLUT_final
|
|
|
|
#include "SCRNMAPR.h"
|
|
|
|
#define ScrnMapr_DoMap UpdateBWDepth4Copy
|
|
#define ScrnMapr_Src GetCurDrawBuff()
|
|
#define ScrnMapr_Dst ScalingBuff
|
|
#define ScrnMapr_SrcDepth 0
|
|
#define ScrnMapr_DstDepth 4
|
|
#define ScrnMapr_Map CLUT_final
|
|
|
|
#include "SCRNMAPR.h"
|
|
|
|
#define ScrnMapr_DoMap UpdateBWDepth5Copy
|
|
#define ScrnMapr_Src GetCurDrawBuff()
|
|
#define ScrnMapr_Dst ScalingBuff
|
|
#define ScrnMapr_SrcDepth 0
|
|
#define ScrnMapr_DstDepth 5
|
|
#define ScrnMapr_Map CLUT_final
|
|
|
|
#include "SCRNMAPR.h"
|
|
|
|
#if EnableMagnify && ! UseSDLscaling
|
|
|
|
#define ScrnMapr_DoMap UpdateBWDepth3ScaledCopy
|
|
#define ScrnMapr_Src GetCurDrawBuff()
|
|
#define ScrnMapr_Dst ScalingBuff
|
|
#define ScrnMapr_SrcDepth 0
|
|
#define ScrnMapr_DstDepth 3
|
|
#define ScrnMapr_Map CLUT_final
|
|
#define ScrnMapr_Scale WindowScale
|
|
|
|
#include "SCRNMAPR.h"
|
|
|
|
#define ScrnMapr_DoMap UpdateBWDepth4ScaledCopy
|
|
#define ScrnMapr_Src GetCurDrawBuff()
|
|
#define ScrnMapr_Dst ScalingBuff
|
|
#define ScrnMapr_SrcDepth 0
|
|
#define ScrnMapr_DstDepth 4
|
|
#define ScrnMapr_Map CLUT_final
|
|
#define ScrnMapr_Scale WindowScale
|
|
|
|
#include "SCRNMAPR.h"
|
|
|
|
#define ScrnMapr_DoMap UpdateBWDepth5ScaledCopy
|
|
#define ScrnMapr_Src GetCurDrawBuff()
|
|
#define ScrnMapr_Dst ScalingBuff
|
|
#define ScrnMapr_SrcDepth 0
|
|
#define ScrnMapr_DstDepth 5
|
|
#define ScrnMapr_Map CLUT_final
|
|
#define ScrnMapr_Scale WindowScale
|
|
|
|
#include "SCRNMAPR.h"
|
|
|
|
#endif /* EnableMagnify && ! UseSDLscaling */
|
|
|
|
|
|
#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
|
|
|
|
#define ScrnMapr_DoMap UpdateColorDepth3Copy
|
|
#define ScrnMapr_Src GetCurDrawBuff()
|
|
#define ScrnMapr_Dst ScalingBuff
|
|
#define ScrnMapr_SrcDepth vMacScreenDepth
|
|
#define ScrnMapr_DstDepth 3
|
|
#define ScrnMapr_Map CLUT_final
|
|
|
|
#include "SCRNMAPR.h"
|
|
|
|
#define ScrnMapr_DoMap UpdateColorDepth4Copy
|
|
#define ScrnMapr_Src GetCurDrawBuff()
|
|
#define ScrnMapr_Dst ScalingBuff
|
|
#define ScrnMapr_SrcDepth vMacScreenDepth
|
|
#define ScrnMapr_DstDepth 4
|
|
#define ScrnMapr_Map CLUT_final
|
|
|
|
#include "SCRNMAPR.h"
|
|
|
|
#define ScrnMapr_DoMap UpdateColorDepth5Copy
|
|
#define ScrnMapr_Src GetCurDrawBuff()
|
|
#define ScrnMapr_Dst ScalingBuff
|
|
#define ScrnMapr_SrcDepth vMacScreenDepth
|
|
#define ScrnMapr_DstDepth 5
|
|
#define ScrnMapr_Map CLUT_final
|
|
|
|
#include "SCRNMAPR.h"
|
|
|
|
#if EnableMagnify && ! UseSDLscaling
|
|
|
|
#define ScrnMapr_DoMap UpdateColorDepth3ScaledCopy
|
|
#define ScrnMapr_Src GetCurDrawBuff()
|
|
#define ScrnMapr_Dst ScalingBuff
|
|
#define ScrnMapr_SrcDepth vMacScreenDepth
|
|
#define ScrnMapr_DstDepth 3
|
|
#define ScrnMapr_Map CLUT_final
|
|
#define ScrnMapr_Scale WindowScale
|
|
|
|
#include "SCRNMAPR.h"
|
|
|
|
#define ScrnMapr_DoMap UpdateColorDepth4ScaledCopy
|
|
#define ScrnMapr_Src GetCurDrawBuff()
|
|
#define ScrnMapr_Dst ScalingBuff
|
|
#define ScrnMapr_SrcDepth vMacScreenDepth
|
|
#define ScrnMapr_DstDepth 4
|
|
#define ScrnMapr_Map CLUT_final
|
|
#define ScrnMapr_Scale WindowScale
|
|
|
|
#include "SCRNMAPR.h"
|
|
|
|
#define ScrnMapr_DoMap UpdateColorDepth5ScaledCopy
|
|
#define ScrnMapr_Src GetCurDrawBuff()
|
|
#define ScrnMapr_Dst ScalingBuff
|
|
#define ScrnMapr_SrcDepth vMacScreenDepth
|
|
#define ScrnMapr_DstDepth 5
|
|
#define ScrnMapr_Map CLUT_final
|
|
#define ScrnMapr_Scale WindowScale
|
|
|
|
#include "SCRNMAPR.h"
|
|
|
|
#endif /* EnableMagnify && ! UseSDLscaling */
|
|
|
|
#endif
|
|
|
|
|
|
LOCALPROC HaveChangedScreenBuff(uint16_t top, uint16_t left,
|
|
uint16_t bottom, uint16_t right)
|
|
{
|
|
int i;
|
|
int j;
|
|
uint8_t *p;
|
|
Uint32 pixel;
|
|
#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
|
|
Uint32 CLUT_pixel[CLUT_size];
|
|
#endif
|
|
Uint32 BWLUT_pixel[2];
|
|
uint32_t top2;
|
|
uint32_t left2;
|
|
uint32_t bottom2;
|
|
uint32_t right2;
|
|
void *pixels;
|
|
int pitch;
|
|
SDL_Rect src_rect;
|
|
SDL_Rect dst_rect;
|
|
int XDest;
|
|
int YDest;
|
|
int DestWidth;
|
|
int DestHeight;
|
|
|
|
#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
|
|
|
|
XDest = left;
|
|
YDest = top;
|
|
DestWidth = (right - left);
|
|
DestHeight = (bottom - top);
|
|
|
|
#if VarFullScreen
|
|
if (UseFullScreen)
|
|
#endif
|
|
#if MayFullScreen
|
|
{
|
|
XDest -= ViewHStart;
|
|
YDest -= ViewVStart;
|
|
}
|
|
#endif
|
|
|
|
#if EnableMagnify
|
|
if (UseMagnify) {
|
|
XDest *= WindowScale;
|
|
YDest *= WindowScale;
|
|
DestWidth *= WindowScale;
|
|
DestHeight *= WindowScale;
|
|
}
|
|
#endif
|
|
|
|
#if VarFullScreen
|
|
if (UseFullScreen)
|
|
#endif
|
|
#if MayFullScreen
|
|
{
|
|
XDest += hOffset;
|
|
YDest += vOffset;
|
|
}
|
|
#endif
|
|
|
|
top2 = top;
|
|
left2 = left;
|
|
bottom2 = bottom;
|
|
right2 = right;
|
|
|
|
#if EnableMagnify && ! UseSDLscaling
|
|
if (UseMagnify) {
|
|
top2 *= WindowScale;
|
|
left2 *= WindowScale;
|
|
bottom2 *= WindowScale;
|
|
right2 *= WindowScale;
|
|
}
|
|
#endif
|
|
|
|
if (0 != SDL_LockTexture(texture, NULL, &pixels, &pitch)) {
|
|
return;
|
|
}
|
|
|
|
{
|
|
|
|
int bpp = format->BytesPerPixel;
|
|
uint32_t ExpectedPitch = vMacScreenWidth * bpp;
|
|
|
|
#if EnableMagnify && ! UseSDLscaling
|
|
if (UseMagnify) {
|
|
ExpectedPitch *= WindowScale;
|
|
}
|
|
#endif
|
|
|
|
#if 0 != vMacScreenDepth
|
|
if (UseColorMode) {
|
|
#if vMacScreenDepth < 4
|
|
for (i = 0; i < CLUT_size; ++i) {
|
|
CLUT_pixel[i] = SDL_MapRGB(format,
|
|
CLUT_reds[i] >> 8,
|
|
CLUT_greens[i] >> 8,
|
|
CLUT_blues[i] >> 8);
|
|
}
|
|
#endif
|
|
} else
|
|
#endif
|
|
{
|
|
BWLUT_pixel[1] = SDL_MapRGB(format, 0, 0, 0);
|
|
/* black */
|
|
BWLUT_pixel[0] = SDL_MapRGB(format, 255, 255, 255);
|
|
/* white */
|
|
}
|
|
|
|
if ((0 == ((bpp - 1) & bpp)) /* a power of 2 */
|
|
&& (pitch == ExpectedPitch)
|
|
#if (vMacScreenDepth > 3)
|
|
&& ! UseColorMode
|
|
#endif
|
|
)
|
|
{
|
|
int k;
|
|
Uint32 v;
|
|
#if EnableMagnify && ! UseSDLscaling
|
|
int a;
|
|
#endif
|
|
int PixPerByte =
|
|
#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
|
|
UseColorMode ? (1 << (3 - vMacScreenDepth)) :
|
|
#endif
|
|
8;
|
|
Uint8 *p4 = (Uint8 *)CLUT_final;
|
|
|
|
for (i = 0; i < 256; ++i) {
|
|
for (k = PixPerByte; --k >= 0; ) {
|
|
|
|
#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
|
|
if (UseColorMode) {
|
|
v = CLUT_pixel[
|
|
#if 3 == vMacScreenDepth
|
|
i
|
|
#else
|
|
(i >> (k << vMacScreenDepth))
|
|
& (CLUT_size - 1)
|
|
#endif
|
|
];
|
|
} else
|
|
#endif
|
|
{
|
|
v = BWLUT_pixel[(i >> k) & 1];
|
|
}
|
|
|
|
#if EnableMagnify && ! UseSDLscaling
|
|
for (a = UseMagnify ? WindowScale : 1; --a >= 0; )
|
|
#endif
|
|
{
|
|
switch (bpp) {
|
|
case 1: /* Assuming 8-bpp */
|
|
*p4++ = v;
|
|
break;
|
|
case 2: /* Probably 15-bpp or 16-bpp */
|
|
*(Uint16 *)p4 = v;
|
|
p4 += 2;
|
|
break;
|
|
case 4: /* Probably 32-bpp */
|
|
*(Uint32 *)p4 = v;
|
|
p4 += 4;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ScalingBuff = (uint8_t *)pixels;
|
|
|
|
#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
|
|
if (UseColorMode) {
|
|
#if EnableMagnify && ! UseSDLscaling
|
|
if (UseMagnify) {
|
|
switch (bpp) {
|
|
case 1:
|
|
UpdateColorDepth3ScaledCopy(
|
|
top, left, bottom, right);
|
|
break;
|
|
case 2:
|
|
UpdateColorDepth4ScaledCopy(
|
|
top, left, bottom, right);
|
|
break;
|
|
case 4:
|
|
UpdateColorDepth5ScaledCopy(
|
|
top, left, bottom, right);
|
|
break;
|
|
}
|
|
} else
|
|
#endif
|
|
{
|
|
switch (bpp) {
|
|
case 1:
|
|
UpdateColorDepth3Copy(top, left, bottom, right);
|
|
break;
|
|
case 2:
|
|
UpdateColorDepth4Copy(top, left, bottom, right);
|
|
break;
|
|
case 4:
|
|
UpdateColorDepth5Copy(top, left, bottom, right);
|
|
break;
|
|
}
|
|
}
|
|
} else
|
|
#endif
|
|
{
|
|
#if EnableMagnify && ! UseSDLscaling
|
|
if (UseMagnify) {
|
|
switch (bpp) {
|
|
case 1:
|
|
UpdateBWDepth3ScaledCopy(
|
|
top, left, bottom, right);
|
|
break;
|
|
case 2:
|
|
UpdateBWDepth4ScaledCopy(
|
|
top, left, bottom, right);
|
|
break;
|
|
case 4:
|
|
UpdateBWDepth5ScaledCopy(
|
|
top, left, bottom, right);
|
|
break;
|
|
}
|
|
} else
|
|
#endif
|
|
{
|
|
switch (bpp) {
|
|
case 1:
|
|
UpdateBWDepth3Copy(top, left, bottom, right);
|
|
break;
|
|
case 2:
|
|
UpdateBWDepth4Copy(top, left, bottom, right);
|
|
break;
|
|
case 4:
|
|
UpdateBWDepth5Copy(top, left, bottom, right);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
} else {
|
|
uint8_t *the_data = (uint8_t *)GetCurDrawBuff();
|
|
|
|
/* adapted from putpixel in SDL documentation */
|
|
|
|
for (i = top2; i < bottom2; ++i) {
|
|
for (j = left2; j < right2; ++j) {
|
|
int i0 = i;
|
|
int j0 = j;
|
|
Uint8 *bufp = (Uint8 *)pixels
|
|
+ i * pitch + j * bpp;
|
|
|
|
#if EnableMagnify && ! UseSDLscaling
|
|
if (UseMagnify) {
|
|
i0 /= WindowScale;
|
|
j0 /= WindowScale;
|
|
}
|
|
#endif
|
|
|
|
#if 0 != vMacScreenDepth
|
|
if (UseColorMode) {
|
|
#if vMacScreenDepth < 4
|
|
p = the_data + ((i0 * vMacScreenWidth + j0)
|
|
>> (3 - vMacScreenDepth));
|
|
{
|
|
uint8_t k = (*p >> (((~ j0)
|
|
& ((1 << (3 - vMacScreenDepth)) - 1))
|
|
<< vMacScreenDepth))
|
|
& (CLUT_size - 1);
|
|
pixel = CLUT_pixel[k];
|
|
}
|
|
#elif 4 == vMacScreenDepth
|
|
p = the_data + ((i0 * vMacScreenWidth + j0) << 1);
|
|
{
|
|
uint16_t t0 = do_get_mem_word(p);
|
|
pixel = SDL_MapRGB(format,
|
|
((t0 & 0x7C00) >> 7)
|
|
| ((t0 & 0x7000) >> 12),
|
|
((t0 & 0x03E0) >> 2)
|
|
| ((t0 & 0x0380) >> 7),
|
|
((t0 & 0x001F) << 3)
|
|
| ((t0 & 0x001C) >> 2));
|
|
}
|
|
#elif 5 == vMacScreenDepth
|
|
p = the_data + ((i0 * vMacScreenWidth + j0) << 2);
|
|
pixel = SDL_MapRGB(format,
|
|
p[1],
|
|
p[2],
|
|
p[3]);
|
|
#endif
|
|
} else
|
|
#endif
|
|
{
|
|
p = the_data + ((i0 * vMacScreenWidth + j0) / 8);
|
|
pixel = BWLUT_pixel[(*p >> ((~ j0) & 0x7)) & 1];
|
|
}
|
|
|
|
switch (bpp) {
|
|
case 1: /* Assuming 8-bpp */
|
|
*bufp = pixel;
|
|
break;
|
|
case 2: /* Probably 15-bpp or 16-bpp */
|
|
*(Uint16 *)bufp = pixel;
|
|
break;
|
|
case 3:
|
|
/* Slow 24-bpp mode, usually not used */
|
|
if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
|
|
bufp[0] = (pixel >> 16) & 0xff;
|
|
bufp[1] = (pixel >> 8) & 0xff;
|
|
bufp[2] = pixel & 0xff;
|
|
} else {
|
|
bufp[0] = pixel & 0xff;
|
|
bufp[1] = (pixel >> 8) & 0xff;
|
|
bufp[2] = (pixel >> 16) & 0xff;
|
|
}
|
|
break;
|
|
case 4: /* Probably 32-bpp */
|
|
*(Uint32 *)bufp = pixel;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
SDL_UnlockTexture(texture);
|
|
|
|
src_rect.x = left2;
|
|
src_rect.y = top2;
|
|
src_rect.w = right2 - left2;
|
|
src_rect.h = bottom2 - top2;
|
|
|
|
dst_rect.x = XDest;
|
|
dst_rect.y = YDest;
|
|
dst_rect.w = DestWidth;
|
|
dst_rect.h = DestHeight;
|
|
|
|
/* SDL_RenderClear(renderer); */
|
|
SDL_RenderCopy(renderer, texture, &src_rect, &dst_rect);
|
|
SDL_RenderPresent(renderer);
|
|
|
|
#if MayFullScreen
|
|
label_exit:
|
|
;
|
|
#endif
|
|
}
|
|
|
|
LOCALPROC DrawChangesAndClear(void)
|
|
{
|
|
if (ScreenChangedBottom > ScreenChangedTop) {
|
|
HaveChangedScreenBuff(ScreenChangedTop, ScreenChangedLeft,
|
|
ScreenChangedBottom, ScreenChangedRight);
|
|
ScreenClearChanges();
|
|
}
|
|
}
|
|
|
|
GLOBALOSGLUPROC DoneWithDrawingForTick(void)
|
|
{
|
|
#if EnableFSMouseMotion
|
|
if (HaveMouseMotion) {
|
|
AutoScrollScreen();
|
|
}
|
|
#endif
|
|
DrawChangesAndClear();
|
|
}
|
|
|
|
/* --- mouse --- */
|
|
|
|
/* cursor hiding */
|
|
|
|
LOCALVAR bool HaveCursorHidden = false;
|
|
LOCALVAR bool WantCursorHidden = false;
|
|
|
|
LOCALPROC ForceShowCursor(void)
|
|
{
|
|
if (HaveCursorHidden) {
|
|
HaveCursorHidden = false;
|
|
(void) SDL_ShowCursor(SDL_ENABLE);
|
|
}
|
|
}
|
|
|
|
/* cursor moving */
|
|
|
|
#ifndef HaveWorkingWarp
|
|
#define HaveWorkingWarp 1
|
|
#endif
|
|
|
|
#if EnableMoveMouse && HaveWorkingWarp
|
|
LOCALFUNC bool MoveMouse(int16_t h, int16_t v)
|
|
{
|
|
#if VarFullScreen
|
|
if (UseFullScreen)
|
|
#endif
|
|
#if MayFullScreen
|
|
{
|
|
h -= ViewHStart;
|
|
v -= ViewVStart;
|
|
}
|
|
#endif
|
|
|
|
#if EnableMagnify
|
|
if (UseMagnify) {
|
|
h *= WindowScale;
|
|
v *= WindowScale;
|
|
}
|
|
#endif
|
|
|
|
#if VarFullScreen
|
|
if (UseFullScreen)
|
|
#endif
|
|
#if MayFullScreen
|
|
{
|
|
h += hOffset;
|
|
v += vOffset;
|
|
}
|
|
#endif
|
|
|
|
SDL_WarpMouseInWindow(main_wind, h, v);
|
|
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
/* cursor state */
|
|
|
|
LOCALPROC MousePositionNotify(int NewMousePosh, int NewMousePosv)
|
|
{
|
|
bool ShouldHaveCursorHidden = true;
|
|
|
|
#if VarFullScreen
|
|
if (UseFullScreen)
|
|
#endif
|
|
#if MayFullScreen
|
|
{
|
|
NewMousePosh -= hOffset;
|
|
NewMousePosv -= vOffset;
|
|
}
|
|
#endif
|
|
|
|
#if EnableMagnify
|
|
if (UseMagnify) {
|
|
NewMousePosh /= WindowScale;
|
|
NewMousePosv /= WindowScale;
|
|
}
|
|
#endif
|
|
|
|
#if VarFullScreen
|
|
if (UseFullScreen)
|
|
#endif
|
|
#if MayFullScreen
|
|
{
|
|
NewMousePosh += ViewHStart;
|
|
NewMousePosv += ViewVStart;
|
|
}
|
|
#endif
|
|
|
|
#if EnableFSMouseMotion
|
|
if (HaveMouseMotion) {
|
|
MousePositionSetDelta(NewMousePosh - SavedMouseH,
|
|
NewMousePosv - SavedMouseV);
|
|
SavedMouseH = NewMousePosh;
|
|
SavedMouseV = NewMousePosv;
|
|
} else
|
|
#endif
|
|
{
|
|
if (NewMousePosh < 0) {
|
|
NewMousePosh = 0;
|
|
ShouldHaveCursorHidden = false;
|
|
} else if (NewMousePosh >= vMacScreenWidth) {
|
|
NewMousePosh = vMacScreenWidth - 1;
|
|
ShouldHaveCursorHidden = false;
|
|
}
|
|
if (NewMousePosv < 0) {
|
|
NewMousePosv = 0;
|
|
ShouldHaveCursorHidden = false;
|
|
} else if (NewMousePosv >= vMacScreenHeight) {
|
|
NewMousePosv = vMacScreenHeight - 1;
|
|
ShouldHaveCursorHidden = false;
|
|
}
|
|
|
|
#if VarFullScreen
|
|
if (UseFullScreen)
|
|
#endif
|
|
#if MayFullScreen
|
|
{
|
|
ShouldHaveCursorHidden = true;
|
|
}
|
|
#endif
|
|
|
|
/* if (ShouldHaveCursorHidden || CurMouseButton) */
|
|
/*
|
|
for a game like arkanoid, would like mouse to still
|
|
move even when outside window in one direction
|
|
*/
|
|
MousePositionSet(NewMousePosh, NewMousePosv);
|
|
}
|
|
|
|
WantCursorHidden = ShouldHaveCursorHidden;
|
|
}
|
|
|
|
#if EnableFSMouseMotion && ! HaveWorkingWarp
|
|
LOCALPROC MousePositionNotifyRelative(int deltah, int deltav)
|
|
{
|
|
bool ShouldHaveCursorHidden = true;
|
|
|
|
#if EnableMagnify
|
|
if (UseMagnify) {
|
|
/*
|
|
This is not really right. If only move one pixel
|
|
each time, emulated mouse doesn't move at all.
|
|
*/
|
|
deltah /= WindowScale;
|
|
deltav /= WindowScale;
|
|
}
|
|
#endif
|
|
|
|
MousePositionSetDelta(deltah,
|
|
deltav);
|
|
|
|
WantCursorHidden = ShouldHaveCursorHidden;
|
|
}
|
|
#endif
|
|
|
|
LOCALPROC CheckMouseState(void)
|
|
{
|
|
/*
|
|
this doesn't work as desired, doesn't get mouse movements
|
|
when outside of our window.
|
|
*/
|
|
int x;
|
|
int y;
|
|
|
|
(void) SDL_GetMouseState(&x, &y);
|
|
MousePositionNotify(x, y);
|
|
}
|
|
|
|
/* --- keyboard input --- */
|
|
|
|
LOCALFUNC uint8_t SDLScan2MacKeyCode(SDL_Scancode i)
|
|
{
|
|
uint8_t v = MKC_None;
|
|
|
|
switch (i) {
|
|
case SDL_SCANCODE_BACKSPACE: v = MKC_BackSpace; break;
|
|
case SDL_SCANCODE_TAB: v = MKC_Tab; break;
|
|
case SDL_SCANCODE_CLEAR: v = MKC_Clear; break;
|
|
case SDL_SCANCODE_RETURN: v = MKC_Return; break;
|
|
case SDL_SCANCODE_PAUSE: v = MKC_Pause; break;
|
|
case SDL_SCANCODE_ESCAPE: v = MKC_formac_Escape; break;
|
|
case SDL_SCANCODE_SPACE: v = MKC_Space; break;
|
|
case SDL_SCANCODE_APOSTROPHE: v = MKC_SingleQuote; break;
|
|
case SDL_SCANCODE_COMMA: v = MKC_Comma; break;
|
|
case SDL_SCANCODE_MINUS: v = MKC_Minus; break;
|
|
case SDL_SCANCODE_PERIOD: v = MKC_Period; break;
|
|
case SDL_SCANCODE_SLASH: v = MKC_formac_Slash; break;
|
|
case SDL_SCANCODE_0: v = MKC_0; break;
|
|
case SDL_SCANCODE_1: v = MKC_1; break;
|
|
case SDL_SCANCODE_2: v = MKC_2; break;
|
|
case SDL_SCANCODE_3: v = MKC_3; break;
|
|
case SDL_SCANCODE_4: v = MKC_4; break;
|
|
case SDL_SCANCODE_5: v = MKC_5; break;
|
|
case SDL_SCANCODE_6: v = MKC_6; break;
|
|
case SDL_SCANCODE_7: v = MKC_7; break;
|
|
case SDL_SCANCODE_8: v = MKC_8; break;
|
|
case SDL_SCANCODE_9: v = MKC_9; break;
|
|
case SDL_SCANCODE_SEMICOLON: v = MKC_SemiColon; break;
|
|
case SDL_SCANCODE_EQUALS: v = MKC_Equal; break;
|
|
|
|
case SDL_SCANCODE_LEFTBRACKET: v = MKC_LeftBracket; break;
|
|
case SDL_SCANCODE_BACKSLASH: v = MKC_formac_BackSlash; break;
|
|
case SDL_SCANCODE_RIGHTBRACKET: v = MKC_RightBracket; break;
|
|
case SDL_SCANCODE_GRAVE: v = MKC_formac_Grave; break;
|
|
|
|
case SDL_SCANCODE_A: v = MKC_A; break;
|
|
case SDL_SCANCODE_B: v = MKC_B; break;
|
|
case SDL_SCANCODE_C: v = MKC_C; break;
|
|
case SDL_SCANCODE_D: v = MKC_D; break;
|
|
case SDL_SCANCODE_E: v = MKC_E; break;
|
|
case SDL_SCANCODE_F: v = MKC_F; break;
|
|
case SDL_SCANCODE_G: v = MKC_G; break;
|
|
case SDL_SCANCODE_H: v = MKC_H; break;
|
|
case SDL_SCANCODE_I: v = MKC_I; break;
|
|
case SDL_SCANCODE_J: v = MKC_J; break;
|
|
case SDL_SCANCODE_K: v = MKC_K; break;
|
|
case SDL_SCANCODE_L: v = MKC_L; break;
|
|
case SDL_SCANCODE_M: v = MKC_M; break;
|
|
case SDL_SCANCODE_N: v = MKC_N; break;
|
|
case SDL_SCANCODE_O: v = MKC_O; break;
|
|
case SDL_SCANCODE_P: v = MKC_P; break;
|
|
case SDL_SCANCODE_Q: v = MKC_Q; break;
|
|
case SDL_SCANCODE_R: v = MKC_R; break;
|
|
case SDL_SCANCODE_S: v = MKC_S; break;
|
|
case SDL_SCANCODE_T: v = MKC_T; break;
|
|
case SDL_SCANCODE_U: v = MKC_U; break;
|
|
case SDL_SCANCODE_V: v = MKC_V; break;
|
|
case SDL_SCANCODE_W: v = MKC_W; break;
|
|
case SDL_SCANCODE_X: v = MKC_X; break;
|
|
case SDL_SCANCODE_Y: v = MKC_Y; break;
|
|
case SDL_SCANCODE_Z: v = MKC_Z; break;
|
|
|
|
case SDL_SCANCODE_KP_0: v = MKC_KP0; break;
|
|
case SDL_SCANCODE_KP_1: v = MKC_KP1; break;
|
|
case SDL_SCANCODE_KP_2: v = MKC_KP2; break;
|
|
case SDL_SCANCODE_KP_3: v = MKC_KP3; break;
|
|
case SDL_SCANCODE_KP_4: v = MKC_KP4; break;
|
|
case SDL_SCANCODE_KP_5: v = MKC_KP5; break;
|
|
case SDL_SCANCODE_KP_6: v = MKC_KP6; break;
|
|
case SDL_SCANCODE_KP_7: v = MKC_KP7; break;
|
|
case SDL_SCANCODE_KP_8: v = MKC_KP8; break;
|
|
case SDL_SCANCODE_KP_9: v = MKC_KP9; break;
|
|
|
|
case SDL_SCANCODE_KP_PERIOD: v = MKC_Decimal; break;
|
|
case SDL_SCANCODE_KP_DIVIDE: v = MKC_KPDevide; break;
|
|
case SDL_SCANCODE_KP_MULTIPLY: v = MKC_KPMultiply; break;
|
|
case SDL_SCANCODE_KP_MINUS: v = MKC_KPSubtract; break;
|
|
case SDL_SCANCODE_KP_PLUS: v = MKC_KPAdd; break;
|
|
case SDL_SCANCODE_KP_ENTER: v = MKC_formac_Enter; break;
|
|
case SDL_SCANCODE_KP_EQUALS: v = MKC_KPEqual; break;
|
|
|
|
case SDL_SCANCODE_UP: v = MKC_Up; break;
|
|
case SDL_SCANCODE_DOWN: v = MKC_Down; break;
|
|
case SDL_SCANCODE_RIGHT: v = MKC_Right; break;
|
|
case SDL_SCANCODE_LEFT: v = MKC_Left; break;
|
|
case SDL_SCANCODE_INSERT: v = MKC_formac_Help; break;
|
|
case SDL_SCANCODE_HOME: v = MKC_formac_Home; break;
|
|
case SDL_SCANCODE_END: v = MKC_formac_End; break;
|
|
case SDL_SCANCODE_PAGEUP: v = MKC_formac_PageUp; break;
|
|
case SDL_SCANCODE_PAGEDOWN: v = MKC_formac_PageDown; break;
|
|
|
|
case SDL_SCANCODE_F1: v = MKC_formac_F1; break;
|
|
case SDL_SCANCODE_F2: v = MKC_formac_F2; break;
|
|
case SDL_SCANCODE_F3: v = MKC_formac_F3; break;
|
|
case SDL_SCANCODE_F4: v = MKC_formac_F4; break;
|
|
case SDL_SCANCODE_F5: v = MKC_formac_F5; break;
|
|
case SDL_SCANCODE_F6: v = MKC_F6; break;
|
|
case SDL_SCANCODE_F7: v = MKC_F7; break;
|
|
case SDL_SCANCODE_F8: v = MKC_F8; break;
|
|
case SDL_SCANCODE_F9: v = MKC_F9; break;
|
|
case SDL_SCANCODE_F10: v = MKC_F10; break;
|
|
case SDL_SCANCODE_F11: v = MKC_F11; break;
|
|
case SDL_SCANCODE_F12: v = MKC_F12; break;
|
|
|
|
case SDL_SCANCODE_NUMLOCKCLEAR:
|
|
v = MKC_formac_ForwardDel; break;
|
|
case SDL_SCANCODE_CAPSLOCK: v = MKC_formac_CapsLock; break;
|
|
case SDL_SCANCODE_SCROLLLOCK: v = MKC_ScrollLock; break;
|
|
case SDL_SCANCODE_RSHIFT: v = MKC_formac_RShift; break;
|
|
case SDL_SCANCODE_LSHIFT: v = MKC_formac_Shift; break;
|
|
case SDL_SCANCODE_RCTRL: v = MKC_formac_RControl; break;
|
|
case SDL_SCANCODE_LCTRL: v = MKC_formac_Control; break;
|
|
case SDL_SCANCODE_RALT: v = MKC_formac_ROption; break;
|
|
case SDL_SCANCODE_LALT: v = MKC_formac_Option; break;
|
|
case SDL_SCANCODE_RGUI: v = MKC_formac_RCommand; break;
|
|
case SDL_SCANCODE_LGUI: v = MKC_formac_Command; break;
|
|
/* case SDLK_LSUPER: v = MKC_formac_Option; break; */
|
|
/* case SDLK_RSUPER: v = MKC_formac_ROption; break; */
|
|
|
|
case SDL_SCANCODE_HELP: v = MKC_formac_Help; break;
|
|
case SDL_SCANCODE_PRINTSCREEN: v = MKC_Print; break;
|
|
|
|
case SDL_SCANCODE_UNDO: v = MKC_formac_F1; break;
|
|
case SDL_SCANCODE_CUT: v = MKC_formac_F2; break;
|
|
case SDL_SCANCODE_COPY: v = MKC_formac_F3; break;
|
|
case SDL_SCANCODE_PASTE: v = MKC_formac_F4; break;
|
|
|
|
case SDL_SCANCODE_AC_HOME: v = MKC_formac_Home; break;
|
|
|
|
case SDL_SCANCODE_KP_A: v = MKC_A; break;
|
|
case SDL_SCANCODE_KP_B: v = MKC_B; break;
|
|
case SDL_SCANCODE_KP_C: v = MKC_C; break;
|
|
case SDL_SCANCODE_KP_D: v = MKC_D; break;
|
|
case SDL_SCANCODE_KP_E: v = MKC_E; break;
|
|
case SDL_SCANCODE_KP_F: v = MKC_F; break;
|
|
|
|
case SDL_SCANCODE_KP_BACKSPACE: v = MKC_BackSpace; break;
|
|
case SDL_SCANCODE_KP_CLEAR: v = MKC_Clear; break;
|
|
case SDL_SCANCODE_KP_COMMA: v = MKC_Comma; break;
|
|
case SDL_SCANCODE_KP_DECIMAL: v = MKC_Decimal; break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return v;
|
|
}
|
|
|
|
LOCALPROC DoKeyCode(SDL_Keysym *r, bool down)
|
|
{
|
|
uint8_t v = SDLScan2MacKeyCode(r->scancode);
|
|
if (MKC_None != v) {
|
|
Keyboard_UpdateKeyMap2(v, down);
|
|
}
|
|
}
|
|
|
|
LOCALPROC DisableKeyRepeat(void)
|
|
{
|
|
}
|
|
|
|
LOCALPROC RestoreKeyRepeat(void)
|
|
{
|
|
}
|
|
|
|
LOCALPROC ReconnectKeyCodes3(void)
|
|
{
|
|
}
|
|
|
|
LOCALPROC DisconnectKeyCodes3(void)
|
|
{
|
|
DisconnectKeyCodes2();
|
|
MouseButtonSet(false);
|
|
}
|
|
|
|
/* --- time, date, location --- */
|
|
|
|
#define dbglog_TimeStuff (0 && dbglog_HAVE)
|
|
|
|
LOCALVAR uint32_t TrueEmulatedTime = 0;
|
|
|
|
#define InvTimeDivPow 16
|
|
#define InvTimeDiv (1 << InvTimeDivPow)
|
|
#define InvTimeDivMask (InvTimeDiv - 1)
|
|
#define InvTimeStep 1089590 /* 1000 / 60.14742 * InvTimeDiv */
|
|
|
|
LOCALVAR Uint32 LastTime;
|
|
|
|
LOCALVAR Uint32 NextIntTime;
|
|
LOCALVAR uint32_t NextFracTime;
|
|
|
|
LOCALPROC IncrNextTime(void)
|
|
{
|
|
NextFracTime += InvTimeStep;
|
|
NextIntTime += (NextFracTime >> InvTimeDivPow);
|
|
NextFracTime &= InvTimeDivMask;
|
|
}
|
|
|
|
LOCALPROC InitNextTime(void)
|
|
{
|
|
NextIntTime = LastTime;
|
|
NextFracTime = 0;
|
|
IncrNextTime();
|
|
}
|
|
|
|
LOCALVAR uint32_t NewMacDateInSeconds;
|
|
|
|
LOCALFUNC bool UpdateTrueEmulatedTime(void)
|
|
{
|
|
Uint32 LatestTime;
|
|
int32_t TimeDiff;
|
|
|
|
LatestTime = SDL_GetTicks();
|
|
if (LatestTime != LastTime) {
|
|
|
|
NewMacDateInSeconds = LatestTime / 1000;
|
|
/* no date and time api in SDL */
|
|
|
|
LastTime = LatestTime;
|
|
TimeDiff = (LatestTime - NextIntTime);
|
|
/* this should work even when time wraps */
|
|
if (TimeDiff >= 0) {
|
|
if (TimeDiff > 256) {
|
|
/* emulation interrupted, forget it */
|
|
++TrueEmulatedTime;
|
|
InitNextTime();
|
|
|
|
#if dbglog_TimeStuff
|
|
dbglog_writelnNum("emulation interrupted",
|
|
TrueEmulatedTime);
|
|
#endif
|
|
} else {
|
|
do {
|
|
++TrueEmulatedTime;
|
|
IncrNextTime();
|
|
TimeDiff = (LatestTime - NextIntTime);
|
|
} while (TimeDiff >= 0);
|
|
}
|
|
return true;
|
|
} else {
|
|
if (TimeDiff < -256) {
|
|
#if dbglog_TimeStuff
|
|
dbglog_writeln("clock set back");
|
|
#endif
|
|
/* clock goofed if ever get here, reset */
|
|
InitNextTime();
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
LOCALFUNC bool CheckDateTime(void)
|
|
{
|
|
if (CurMacDateInSeconds != NewMacDateInSeconds) {
|
|
CurMacDateInSeconds = NewMacDateInSeconds;
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
LOCALPROC StartUpTimeAdjust(void)
|
|
{
|
|
LastTime = SDL_GetTicks();
|
|
InitNextTime();
|
|
}
|
|
|
|
LOCALFUNC bool InitLocationDat(void)
|
|
{
|
|
LastTime = SDL_GetTicks();
|
|
InitNextTime();
|
|
NewMacDateInSeconds = LastTime / 1000;
|
|
CurMacDateInSeconds = NewMacDateInSeconds;
|
|
|
|
return true;
|
|
}
|
|
|
|
/* --- sound --- */
|
|
|
|
#if SoundEnabled
|
|
|
|
#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;
|
|
volatile static uint16_t ThePlayOffset;
|
|
volatile static uint16_t TheFillOffset;
|
|
volatile static uint16_t MinFilledSoundBuffs;
|
|
#if dbglog_SoundBuffStats
|
|
LOCALVAR uint16_t MaxFilledSoundBuffs;
|
|
#endif
|
|
LOCALVAR uint16_t TheWriteOffset;
|
|
|
|
LOCALPROC Sound_Init0(void)
|
|
{
|
|
ThePlayOffset = 0;
|
|
TheFillOffset = 0;
|
|
TheWriteOffset = 0;
|
|
}
|
|
|
|
LOCALPROC Sound_Start0(void)
|
|
{
|
|
/* Reset variables */
|
|
MinFilledSoundBuffs = kSoundBuffers + 1;
|
|
#if dbglog_SoundBuffStats
|
|
MaxFilledSoundBuffs = 0;
|
|
#endif
|
|
}
|
|
|
|
GLOBALOSGLUFUNC tpSoundSamp Sound_BeginWrite(uint16_t n, uint16_t *actL)
|
|
{
|
|
uint16_t ToFillLen = kAllBuffLen - (TheWriteOffset - ThePlayOffset);
|
|
uint16_t 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 Sound_WroteABlock(void)
|
|
{
|
|
#if (4 == kLn2SoundSampSz)
|
|
uint16_t PrevWriteOffset = TheWriteOffset - kOneBuffLen;
|
|
tpSoundSamp p = TheSoundBuffer + (PrevWriteOffset & kAllBuffMask);
|
|
#endif
|
|
|
|
#if dbglog_SoundStuff
|
|
dbglog_writeln("enter Sound_WroteABlock");
|
|
#endif
|
|
|
|
ConvertSoundBlockToNative(p);
|
|
|
|
TheFillOffset = TheWriteOffset;
|
|
|
|
#if dbglog_SoundBuffStats
|
|
{
|
|
uint16_t ToPlayLen = TheFillOffset
|
|
- ThePlayOffset;
|
|
uint16_t ToPlayBuffs = ToPlayLen >> kLnOneBuffLen;
|
|
|
|
if (ToPlayBuffs > MaxFilledSoundBuffs) {
|
|
MaxFilledSoundBuffs = ToPlayBuffs;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
LOCALFUNC bool Sound_EndWrite0(uint16_t actL)
|
|
{
|
|
bool v;
|
|
|
|
TheWriteOffset += actL;
|
|
|
|
if (0 != (TheWriteOffset & kOneBuffMask)) {
|
|
v = false;
|
|
} else {
|
|
/* just finished a block */
|
|
|
|
Sound_WroteABlock();
|
|
|
|
v = true;
|
|
}
|
|
|
|
return v;
|
|
}
|
|
|
|
LOCALPROC Sound_SecondNotify0(void)
|
|
{
|
|
if (MinFilledSoundBuffs <= kSoundBuffers) {
|
|
if (MinFilledSoundBuffs > DesiredMinFilledSoundBuffs) {
|
|
#if dbglog_SoundStuff
|
|
dbglog_writeln("MinFilledSoundBuffs too high");
|
|
#endif
|
|
IncrNextTime();
|
|
} 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 uint16_t 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 SoundR {
|
|
tpSoundSamp fTheSoundBuffer;
|
|
volatile uint16_t (*fPlayOffset);
|
|
volatile uint16_t (*fFillOffset);
|
|
volatile uint16_t (*fMinFilledSoundBuffs);
|
|
|
|
volatile trSoundTemp lastv;
|
|
|
|
bool wantplaying;
|
|
bool HaveStartedPlaying;
|
|
};
|
|
typedef struct SoundR SoundR;
|
|
|
|
static void audio_callback(void *udata, Uint8 *stream, int len)
|
|
{
|
|
uint16_t ToPlayLen;
|
|
uint16_t FilledSoundBuffs;
|
|
int i;
|
|
SoundR *datp = (SoundR *)udata;
|
|
tpSoundSamp CurSoundBuffer = datp->fTheSoundBuffer;
|
|
uint16_t 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 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 = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
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 {
|
|
uint16_t 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;
|
|
}
|
|
|
|
LOCALVAR SoundR cur_audio;
|
|
|
|
LOCALVAR bool HaveSoundOut = false;
|
|
|
|
LOCALPROC Sound_Stop(void)
|
|
{
|
|
#if dbglog_SoundStuff
|
|
dbglog_writeln("enter Sound_Stop");
|
|
#endif
|
|
|
|
if (cur_audio.wantplaying && HaveSoundOut) {
|
|
uint16_t retry_limit = 50; /* half of a second */
|
|
|
|
cur_audio.wantplaying = false;
|
|
|
|
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.
|
|
*/
|
|
|
|
#if dbglog_SoundStuff
|
|
dbglog_writeln("busy, so sleep");
|
|
#endif
|
|
|
|
(void) SDL_Delay(10);
|
|
|
|
goto label_retry;
|
|
}
|
|
|
|
SDL_PauseAudio(1);
|
|
}
|
|
|
|
#if dbglog_SoundStuff
|
|
dbglog_writeln("leave Sound_Stop");
|
|
#endif
|
|
}
|
|
|
|
LOCALPROC Sound_Start(void)
|
|
{
|
|
if ((! cur_audio.wantplaying) && HaveSoundOut) {
|
|
Sound_Start0();
|
|
cur_audio.lastv = kCenterTempSound;
|
|
cur_audio.HaveStartedPlaying = false;
|
|
cur_audio.wantplaying = true;
|
|
|
|
SDL_PauseAudio(0);
|
|
}
|
|
}
|
|
|
|
LOCALPROC Sound_UnInit(void)
|
|
{
|
|
if (HaveSoundOut) {
|
|
SDL_CloseAudio();
|
|
}
|
|
}
|
|
|
|
#define SOUND_SAMPLERATE 22255 /* = round(7833600 * 2 / 704) */
|
|
|
|
LOCALFUNC bool Sound_Init(void)
|
|
{
|
|
SDL_AudioSpec desired;
|
|
|
|
Sound_Init0();
|
|
|
|
cur_audio.fTheSoundBuffer = TheSoundBuffer;
|
|
cur_audio.fPlayOffset = &ThePlayOffset;
|
|
cur_audio.fFillOffset = &TheFillOffset;
|
|
cur_audio.fMinFilledSoundBuffs = &MinFilledSoundBuffs;
|
|
cur_audio.wantplaying = false;
|
|
|
|
desired.freq = SOUND_SAMPLERATE;
|
|
|
|
#if 3 == kLn2SoundSampSz
|
|
desired.format = AUDIO_U8;
|
|
#elif 4 == kLn2SoundSampSz
|
|
desired.format = AUDIO_S16SYS;
|
|
#else
|
|
#error "unsupported audio format"
|
|
#endif
|
|
|
|
desired.channels = 1;
|
|
desired.samples = 1024;
|
|
desired.callback = audio_callback;
|
|
desired.userdata = (void *)&cur_audio;
|
|
|
|
/* Open the audio device */
|
|
if (SDL_OpenAudio(&desired, NULL) < 0) {
|
|
fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
|
|
} else {
|
|
HaveSoundOut = true;
|
|
|
|
Sound_Start();
|
|
/*
|
|
This should be taken care of by LeaveSpeedStopped,
|
|
but since takes a while to get going properly,
|
|
start early.
|
|
*/
|
|
}
|
|
|
|
return true; /* keep going, even if no sound */
|
|
}
|
|
|
|
GLOBALOSGLUPROC Sound_EndWrite(uint16_t actL)
|
|
{
|
|
if (Sound_EndWrite0(actL)) {
|
|
}
|
|
}
|
|
|
|
LOCALPROC Sound_SecondNotify(void)
|
|
{
|
|
if (HaveSoundOut) {
|
|
Sound_SecondNotify0();
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/* --- basic dialogs --- */
|
|
|
|
LOCALPROC CheckSavedMacMsg(void)
|
|
{
|
|
/* called only on quit, if error saved but not yet reported */
|
|
|
|
if (nullpr != SavedBriefMsg) {
|
|
char briefMsg0[ClStrMaxLength + 1];
|
|
char longMsg0[ClStrMaxLength + 1];
|
|
|
|
NativeStrFromCStr(briefMsg0, SavedBriefMsg);
|
|
NativeStrFromCStr(longMsg0, SavedLongMsg);
|
|
|
|
if (0 != SDL_ShowSimpleMessageBox(
|
|
SDL_MESSAGEBOX_ERROR,
|
|
SavedBriefMsg,
|
|
SavedLongMsg,
|
|
main_wind
|
|
))
|
|
{
|
|
fprintf(stderr, "%s\n", briefMsg0);
|
|
fprintf(stderr, "%s\n", longMsg0);
|
|
}
|
|
|
|
SavedBriefMsg = nullpr;
|
|
}
|
|
}
|
|
|
|
/* --- clipboard --- */
|
|
|
|
#if IncludeHostTextClipExchange
|
|
LOCALFUNC uimr MacRoman2UniCodeSize(uint8_t *s, uimr L)
|
|
{
|
|
uimr i;
|
|
uint8_t x;
|
|
uimr n;
|
|
uimr v = 0;
|
|
|
|
for (i = 0; i < L; ++i) {
|
|
x = *s++;
|
|
if (x < 128) {
|
|
n = 1;
|
|
} else {
|
|
switch (x) {
|
|
case 0x80: n = 2; break;
|
|
/* LATIN CAPITAL LETTER A WITH DIAERESIS */
|
|
case 0x81: n = 2; break;
|
|
/* LATIN CAPITAL LETTER A WITH RING ABOVE */
|
|
case 0x82: n = 2; break;
|
|
/* LATIN CAPITAL LETTER C WITH CEDILLA */
|
|
case 0x83: n = 2; break;
|
|
/* LATIN CAPITAL LETTER E WITH ACUTE */
|
|
case 0x84: n = 2; break;
|
|
/* LATIN CAPITAL LETTER N WITH TILDE */
|
|
case 0x85: n = 2; break;
|
|
/* LATIN CAPITAL LETTER O WITH DIAERESIS */
|
|
case 0x86: n = 2; break;
|
|
/* LATIN CAPITAL LETTER U WITH DIAERESIS */
|
|
case 0x87: n = 2; break;
|
|
/* LATIN SMALL LETTER A WITH ACUTE */
|
|
case 0x88: n = 2; break;
|
|
/* LATIN SMALL LETTER A WITH GRAVE */
|
|
case 0x89: n = 2; break;
|
|
/* LATIN SMALL LETTER A WITH CIRCUMFLEX */
|
|
case 0x8A: n = 2; break;
|
|
/* LATIN SMALL LETTER A WITH DIAERESIS */
|
|
case 0x8B: n = 2; break;
|
|
/* LATIN SMALL LETTER A WITH TILDE */
|
|
case 0x8C: n = 2; break;
|
|
/* LATIN SMALL LETTER A WITH RING ABOVE */
|
|
case 0x8D: n = 2; break;
|
|
/* LATIN SMALL LETTER C WITH CEDILLA */
|
|
case 0x8E: n = 2; break;
|
|
/* LATIN SMALL LETTER E WITH ACUTE */
|
|
case 0x8F: n = 2; break;
|
|
/* LATIN SMALL LETTER E WITH GRAVE */
|
|
case 0x90: n = 2; break;
|
|
/* LATIN SMALL LETTER E WITH CIRCUMFLEX */
|
|
case 0x91: n = 2; break;
|
|
/* LATIN SMALL LETTER E WITH DIAERESIS */
|
|
case 0x92: n = 2; break;
|
|
/* LATIN SMALL LETTER I WITH ACUTE */
|
|
case 0x93: n = 2; break;
|
|
/* LATIN SMALL LETTER I WITH GRAVE */
|
|
case 0x94: n = 2; break;
|
|
/* LATIN SMALL LETTER I WITH CIRCUMFLEX */
|
|
case 0x95: n = 2; break;
|
|
/* LATIN SMALL LETTER I WITH DIAERESIS */
|
|
case 0x96: n = 2; break;
|
|
/* LATIN SMALL LETTER N WITH TILDE */
|
|
case 0x97: n = 2; break;
|
|
/* LATIN SMALL LETTER O WITH ACUTE */
|
|
case 0x98: n = 2; break;
|
|
/* LATIN SMALL LETTER O WITH GRAVE */
|
|
case 0x99: n = 2; break;
|
|
/* LATIN SMALL LETTER O WITH CIRCUMFLEX */
|
|
case 0x9A: n = 2; break;
|
|
/* LATIN SMALL LETTER O WITH DIAERESIS */
|
|
case 0x9B: n = 2; break;
|
|
/* LATIN SMALL LETTER O WITH TILDE */
|
|
case 0x9C: n = 2; break;
|
|
/* LATIN SMALL LETTER U WITH ACUTE */
|
|
case 0x9D: n = 2; break;
|
|
/* LATIN SMALL LETTER U WITH GRAVE */
|
|
case 0x9E: n = 2; break;
|
|
/* LATIN SMALL LETTER U WITH CIRCUMFLEX */
|
|
case 0x9F: n = 2; break;
|
|
/* LATIN SMALL LETTER U WITH DIAERESIS */
|
|
case 0xA0: n = 3; break;
|
|
/* DAGGER */
|
|
case 0xA1: n = 2; break;
|
|
/* DEGREE SIGN */
|
|
case 0xA2: n = 2; break;
|
|
/* CENT SIGN */
|
|
case 0xA3: n = 2; break;
|
|
/* POUND SIGN */
|
|
case 0xA4: n = 2; break;
|
|
/* SECTION SIGN */
|
|
case 0xA5: n = 3; break;
|
|
/* BULLET */
|
|
case 0xA6: n = 2; break;
|
|
/* PILCROW SIGN */
|
|
case 0xA7: n = 2; break;
|
|
/* LATIN SMALL LETTER SHARP S */
|
|
case 0xA8: n = 2; break;
|
|
/* REGISTERED SIGN */
|
|
case 0xA9: n = 2; break;
|
|
/* COPYRIGHT SIGN */
|
|
case 0xAA: n = 3; break;
|
|
/* TRADE MARK SIGN */
|
|
case 0xAB: n = 2; break;
|
|
/* ACUTE ACCENT */
|
|
case 0xAC: n = 2; break;
|
|
/* DIAERESIS */
|
|
case 0xAD: n = 3; break;
|
|
/* NOT EQUAL TO */
|
|
case 0xAE: n = 2; break;
|
|
/* LATIN CAPITAL LETTER AE */
|
|
case 0xAF: n = 2; break;
|
|
/* LATIN CAPITAL LETTER O WITH STROKE */
|
|
case 0xB0: n = 3; break;
|
|
/* INFINITY */
|
|
case 0xB1: n = 2; break;
|
|
/* PLUS-MINUS SIGN */
|
|
case 0xB2: n = 3; break;
|
|
/* LESS-THAN OR EQUAL TO */
|
|
case 0xB3: n = 3; break;
|
|
/* GREATER-THAN OR EQUAL TO */
|
|
case 0xB4: n = 2; break;
|
|
/* YEN SIGN */
|
|
case 0xB5: n = 2; break;
|
|
/* MICRO SIGN */
|
|
case 0xB6: n = 3; break;
|
|
/* PARTIAL DIFFERENTIAL */
|
|
case 0xB7: n = 3; break;
|
|
/* N-ARY SUMMATION */
|
|
case 0xB8: n = 3; break;
|
|
/* N-ARY PRODUCT */
|
|
case 0xB9: n = 2; break;
|
|
/* GREEK SMALL LETTER PI */
|
|
case 0xBA: n = 3; break;
|
|
/* INTEGRAL */
|
|
case 0xBB: n = 2; break;
|
|
/* FEMININE ORDINAL INDICATOR */
|
|
case 0xBC: n = 2; break;
|
|
/* MASCULINE ORDINAL INDICATOR */
|
|
case 0xBD: n = 2; break;
|
|
/* GREEK CAPITAL LETTER OMEGA */
|
|
case 0xBE: n = 2; break;
|
|
/* LATIN SMALL LETTER AE */
|
|
case 0xBF: n = 2; break;
|
|
/* LATIN SMALL LETTER O WITH STROKE */
|
|
case 0xC0: n = 2; break;
|
|
/* INVERTED QUESTION MARK */
|
|
case 0xC1: n = 2; break;
|
|
/* INVERTED EXCLAMATION MARK */
|
|
case 0xC2: n = 2; break;
|
|
/* NOT SIGN */
|
|
case 0xC3: n = 3; break;
|
|
/* SQUARE ROOT */
|
|
case 0xC4: n = 2; break;
|
|
/* LATIN SMALL LETTER F WITH HOOK */
|
|
case 0xC5: n = 3; break;
|
|
/* ALMOST EQUAL TO */
|
|
case 0xC6: n = 3; break;
|
|
/* INCREMENT */
|
|
case 0xC7: n = 2; break;
|
|
/* LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
|
|
case 0xC8: n = 2; break;
|
|
/* RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
|
|
case 0xC9: n = 3; break;
|
|
/* HORIZONTAL ELLIPSIS */
|
|
case 0xCA: n = 2; break;
|
|
/* NO-BREAK SPACE */
|
|
case 0xCB: n = 2; break;
|
|
/* LATIN CAPITAL LETTER A WITH GRAVE */
|
|
case 0xCC: n = 2; break;
|
|
/* LATIN CAPITAL LETTER A WITH TILDE */
|
|
case 0xCD: n = 2; break;
|
|
/* LATIN CAPITAL LETTER O WITH TILDE */
|
|
case 0xCE: n = 2; break;
|
|
/* LATIN CAPITAL LIGATURE OE */
|
|
case 0xCF: n = 2; break;
|
|
/* LATIN SMALL LIGATURE OE */
|
|
case 0xD0: n = 3; break;
|
|
/* EN DASH */
|
|
case 0xD1: n = 3; break;
|
|
/* EM DASH */
|
|
case 0xD2: n = 3; break;
|
|
/* LEFT DOUBLE QUOTATION MARK */
|
|
case 0xD3: n = 3; break;
|
|
/* RIGHT DOUBLE QUOTATION MARK */
|
|
case 0xD4: n = 3; break;
|
|
/* LEFT SINGLE QUOTATION MARK */
|
|
case 0xD5: n = 3; break;
|
|
/* RIGHT SINGLE QUOTATION MARK */
|
|
case 0xD6: n = 2; break;
|
|
/* DIVISION SIGN */
|
|
case 0xD7: n = 3; break;
|
|
/* LOZENGE */
|
|
case 0xD8: n = 2; break;
|
|
/* LATIN SMALL LETTER Y WITH DIAERESIS */
|
|
case 0xD9: n = 2; break;
|
|
/* LATIN CAPITAL LETTER Y WITH DIAERESIS */
|
|
case 0xDA: n = 3; break;
|
|
/* FRACTION SLASH */
|
|
case 0xDB: n = 3; break;
|
|
/* EURO SIGN */
|
|
case 0xDC: n = 3; break;
|
|
/* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
|
|
case 0xDD: n = 3; break;
|
|
/* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
|
|
case 0xDE: n = 3; break;
|
|
/* LATIN SMALL LIGATURE FI */
|
|
case 0xDF: n = 3; break;
|
|
/* LATIN SMALL LIGATURE FL */
|
|
case 0xE0: n = 3; break;
|
|
/* DOUBLE DAGGER */
|
|
case 0xE1: n = 2; break;
|
|
/* MIDDLE DOT */
|
|
case 0xE2: n = 3; break;
|
|
/* SINGLE LOW-9 QUOTATION MARK */
|
|
case 0xE3: n = 3; break;
|
|
/* DOUBLE LOW-9 QUOTATION MARK */
|
|
case 0xE4: n = 3; break;
|
|
/* PER MILLE SIGN */
|
|
case 0xE5: n = 2; break;
|
|
/* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
|
|
case 0xE6: n = 2; break;
|
|
/* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
|
|
case 0xE7: n = 2; break;
|
|
/* LATIN CAPITAL LETTER A WITH ACUTE */
|
|
case 0xE8: n = 2; break;
|
|
/* LATIN CAPITAL LETTER E WITH DIAERESIS */
|
|
case 0xE9: n = 2; break;
|
|
/* LATIN CAPITAL LETTER E WITH GRAVE */
|
|
case 0xEA: n = 2; break;
|
|
/* LATIN CAPITAL LETTER I WITH ACUTE */
|
|
case 0xEB: n = 2; break;
|
|
/* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
|
|
case 0xEC: n = 2; break;
|
|
/* LATIN CAPITAL LETTER I WITH DIAERESIS */
|
|
case 0xED: n = 2; break;
|
|
/* LATIN CAPITAL LETTER I WITH GRAVE */
|
|
case 0xEE: n = 2; break;
|
|
/* LATIN CAPITAL LETTER O WITH ACUTE */
|
|
case 0xEF: n = 2; break;
|
|
/* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
|
|
case 0xF0: n = 3; break;
|
|
/* Apple logo */
|
|
case 0xF1: n = 2; break;
|
|
/* LATIN CAPITAL LETTER O WITH GRAVE */
|
|
case 0xF2: n = 2; break;
|
|
/* LATIN CAPITAL LETTER U WITH ACUTE */
|
|
case 0xF3: n = 2; break;
|
|
/* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
|
|
case 0xF4: n = 2; break;
|
|
/* LATIN CAPITAL LETTER U WITH GRAVE */
|
|
case 0xF5: n = 2; break;
|
|
/* LATIN SMALL LETTER DOTLESS I */
|
|
case 0xF6: n = 2; break;
|
|
/* MODIFIER LETTER CIRCUMFLEX ACCENT */
|
|
case 0xF7: n = 2; break;
|
|
/* SMALL TILDE */
|
|
case 0xF8: n = 2; break;
|
|
/* MACRON */
|
|
case 0xF9: n = 2; break;
|
|
/* BREVE */
|
|
case 0xFA: n = 2; break;
|
|
/* DOT ABOVE */
|
|
case 0xFB: n = 2; break;
|
|
/* RING ABOVE */
|
|
case 0xFC: n = 2; break;
|
|
/* CEDILLA */
|
|
case 0xFD: n = 2; break;
|
|
/* DOUBLE ACUTE ACCENT */
|
|
case 0xFE: n = 2; break;
|
|
/* OGONEK */
|
|
case 0xFF: n = 2; break;
|
|
/* CARON */
|
|
default: n = 1; break;
|
|
/* shouldn't get here */
|
|
}
|
|
}
|
|
v += n;
|
|
}
|
|
|
|
return v;
|
|
}
|
|
#endif
|
|
|
|
#if IncludeHostTextClipExchange
|
|
LOCALPROC MacRoman2UniCodeData(uint8_t *s, uimr L, char *t)
|
|
{
|
|
uimr i;
|
|
uint8_t x;
|
|
|
|
for (i = 0; i < L; ++i) {
|
|
x = *s++;
|
|
if (x < 128) {
|
|
*t++ = x;
|
|
} else {
|
|
switch (x) {
|
|
case 0x80: *t++ = 0xC3; *t++ = 0x84; break;
|
|
/* LATIN CAPITAL LETTER A WITH DIAERESIS */
|
|
case 0x81: *t++ = 0xC3; *t++ = 0x85; break;
|
|
/* LATIN CAPITAL LETTER A WITH RING ABOVE */
|
|
case 0x82: *t++ = 0xC3; *t++ = 0x87; break;
|
|
/* LATIN CAPITAL LETTER C WITH CEDILLA */
|
|
case 0x83: *t++ = 0xC3; *t++ = 0x89; break;
|
|
/* LATIN CAPITAL LETTER E WITH ACUTE */
|
|
case 0x84: *t++ = 0xC3; *t++ = 0x91; break;
|
|
/* LATIN CAPITAL LETTER N WITH TILDE */
|
|
case 0x85: *t++ = 0xC3; *t++ = 0x96; break;
|
|
/* LATIN CAPITAL LETTER O WITH DIAERESIS */
|
|
case 0x86: *t++ = 0xC3; *t++ = 0x9C; break;
|
|
/* LATIN CAPITAL LETTER U WITH DIAERESIS */
|
|
case 0x87: *t++ = 0xC3; *t++ = 0xA1; break;
|
|
/* LATIN SMALL LETTER A WITH ACUTE */
|
|
case 0x88: *t++ = 0xC3; *t++ = 0xA0; break;
|
|
/* LATIN SMALL LETTER A WITH GRAVE */
|
|
case 0x89: *t++ = 0xC3; *t++ = 0xA2; break;
|
|
/* LATIN SMALL LETTER A WITH CIRCUMFLEX */
|
|
case 0x8A: *t++ = 0xC3; *t++ = 0xA4; break;
|
|
/* LATIN SMALL LETTER A WITH DIAERESIS */
|
|
case 0x8B: *t++ = 0xC3; *t++ = 0xA3; break;
|
|
/* LATIN SMALL LETTER A WITH TILDE */
|
|
case 0x8C: *t++ = 0xC3; *t++ = 0xA5; break;
|
|
/* LATIN SMALL LETTER A WITH RING ABOVE */
|
|
case 0x8D: *t++ = 0xC3; *t++ = 0xA7; break;
|
|
/* LATIN SMALL LETTER C WITH CEDILLA */
|
|
case 0x8E: *t++ = 0xC3; *t++ = 0xA9; break;
|
|
/* LATIN SMALL LETTER E WITH ACUTE */
|
|
case 0x8F: *t++ = 0xC3; *t++ = 0xA8; break;
|
|
/* LATIN SMALL LETTER E WITH GRAVE */
|
|
case 0x90: *t++ = 0xC3; *t++ = 0xAA; break;
|
|
/* LATIN SMALL LETTER E WITH CIRCUMFLEX */
|
|
case 0x91: *t++ = 0xC3; *t++ = 0xAB; break;
|
|
/* LATIN SMALL LETTER E WITH DIAERESIS */
|
|
case 0x92: *t++ = 0xC3; *t++ = 0xAD; break;
|
|
/* LATIN SMALL LETTER I WITH ACUTE */
|
|
case 0x93: *t++ = 0xC3; *t++ = 0xAC; break;
|
|
/* LATIN SMALL LETTER I WITH GRAVE */
|
|
case 0x94: *t++ = 0xC3; *t++ = 0xAE; break;
|
|
/* LATIN SMALL LETTER I WITH CIRCUMFLEX */
|
|
case 0x95: *t++ = 0xC3; *t++ = 0xAF; break;
|
|
/* LATIN SMALL LETTER I WITH DIAERESIS */
|
|
case 0x96: *t++ = 0xC3; *t++ = 0xB1; break;
|
|
/* LATIN SMALL LETTER N WITH TILDE */
|
|
case 0x97: *t++ = 0xC3; *t++ = 0xB3; break;
|
|
/* LATIN SMALL LETTER O WITH ACUTE */
|
|
case 0x98: *t++ = 0xC3; *t++ = 0xB2; break;
|
|
/* LATIN SMALL LETTER O WITH GRAVE */
|
|
case 0x99: *t++ = 0xC3; *t++ = 0xB4; break;
|
|
/* LATIN SMALL LETTER O WITH CIRCUMFLEX */
|
|
case 0x9A: *t++ = 0xC3; *t++ = 0xB6; break;
|
|
/* LATIN SMALL LETTER O WITH DIAERESIS */
|
|
case 0x9B: *t++ = 0xC3; *t++ = 0xB5; break;
|
|
/* LATIN SMALL LETTER O WITH TILDE */
|
|
case 0x9C: *t++ = 0xC3; *t++ = 0xBA; break;
|
|
/* LATIN SMALL LETTER U WITH ACUTE */
|
|
case 0x9D: *t++ = 0xC3; *t++ = 0xB9; break;
|
|
/* LATIN SMALL LETTER U WITH GRAVE */
|
|
case 0x9E: *t++ = 0xC3; *t++ = 0xBB; break;
|
|
/* LATIN SMALL LETTER U WITH CIRCUMFLEX */
|
|
case 0x9F: *t++ = 0xC3; *t++ = 0xBC; break;
|
|
/* LATIN SMALL LETTER U WITH DIAERESIS */
|
|
case 0xA0: *t++ = 0xE2; *t++ = 0x80; *t++ = 0xA0; break;
|
|
/* DAGGER */
|
|
case 0xA1: *t++ = 0xC2; *t++ = 0xB0; break;
|
|
/* DEGREE SIGN */
|
|
case 0xA2: *t++ = 0xC2; *t++ = 0xA2; break;
|
|
/* CENT SIGN */
|
|
case 0xA3: *t++ = 0xC2; *t++ = 0xA3; break;
|
|
/* POUND SIGN */
|
|
case 0xA4: *t++ = 0xC2; *t++ = 0xA7; break;
|
|
/* SECTION SIGN */
|
|
case 0xA5: *t++ = 0xE2; *t++ = 0x80; *t++ = 0xA2; break;
|
|
/* BULLET */
|
|
case 0xA6: *t++ = 0xC2; *t++ = 0xB6; break;
|
|
/* PILCROW SIGN */
|
|
case 0xA7: *t++ = 0xC3; *t++ = 0x9F; break;
|
|
/* LATIN SMALL LETTER SHARP S */
|
|
case 0xA8: *t++ = 0xC2; *t++ = 0xAE; break;
|
|
/* REGISTERED SIGN */
|
|
case 0xA9: *t++ = 0xC2; *t++ = 0xA9; break;
|
|
/* COPYRIGHT SIGN */
|
|
case 0xAA: *t++ = 0xE2; *t++ = 0x84; *t++ = 0xA2; break;
|
|
/* TRADE MARK SIGN */
|
|
case 0xAB: *t++ = 0xC2; *t++ = 0xB4; break;
|
|
/* ACUTE ACCENT */
|
|
case 0xAC: *t++ = 0xC2; *t++ = 0xA8; break;
|
|
/* DIAERESIS */
|
|
case 0xAD: *t++ = 0xE2; *t++ = 0x89; *t++ = 0xA0; break;
|
|
/* NOT EQUAL TO */
|
|
case 0xAE: *t++ = 0xC3; *t++ = 0x86; break;
|
|
/* LATIN CAPITAL LETTER AE */
|
|
case 0xAF: *t++ = 0xC3; *t++ = 0x98; break;
|
|
/* LATIN CAPITAL LETTER O WITH STROKE */
|
|
case 0xB0: *t++ = 0xE2; *t++ = 0x88; *t++ = 0x9E; break;
|
|
/* INFINITY */
|
|
case 0xB1: *t++ = 0xC2; *t++ = 0xB1; break;
|
|
/* PLUS-MINUS SIGN */
|
|
case 0xB2: *t++ = 0xE2; *t++ = 0x89; *t++ = 0xA4; break;
|
|
/* LESS-THAN OR EQUAL TO */
|
|
case 0xB3: *t++ = 0xE2; *t++ = 0x89; *t++ = 0xA5; break;
|
|
/* GREATER-THAN OR EQUAL TO */
|
|
case 0xB4: *t++ = 0xC2; *t++ = 0xA5; break;
|
|
/* YEN SIGN */
|
|
case 0xB5: *t++ = 0xC2; *t++ = 0xB5; break;
|
|
/* MICRO SIGN */
|
|
case 0xB6: *t++ = 0xE2; *t++ = 0x88; *t++ = 0x82; break;
|
|
/* PARTIAL DIFFERENTIAL */
|
|
case 0xB7: *t++ = 0xE2; *t++ = 0x88; *t++ = 0x91; break;
|
|
/* N-ARY SUMMATION */
|
|
case 0xB8: *t++ = 0xE2; *t++ = 0x88; *t++ = 0x8F; break;
|
|
/* N-ARY PRODUCT */
|
|
case 0xB9: *t++ = 0xCF; *t++ = 0x80; break;
|
|
/* GREEK SMALL LETTER PI */
|
|
case 0xBA: *t++ = 0xE2; *t++ = 0x88; *t++ = 0xAB; break;
|
|
/* INTEGRAL */
|
|
case 0xBB: *t++ = 0xC2; *t++ = 0xAA; break;
|
|
/* FEMININE ORDINAL INDICATOR */
|
|
case 0xBC: *t++ = 0xC2; *t++ = 0xBA; break;
|
|
/* MASCULINE ORDINAL INDICATOR */
|
|
case 0xBD: *t++ = 0xCE; *t++ = 0xA9; break;
|
|
/* GREEK CAPITAL LETTER OMEGA */
|
|
case 0xBE: *t++ = 0xC3; *t++ = 0xA6; break;
|
|
/* LATIN SMALL LETTER AE */
|
|
case 0xBF: *t++ = 0xC3; *t++ = 0xB8; break;
|
|
/* LATIN SMALL LETTER O WITH STROKE */
|
|
case 0xC0: *t++ = 0xC2; *t++ = 0xBF; break;
|
|
/* INVERTED QUESTION MARK */
|
|
case 0xC1: *t++ = 0xC2; *t++ = 0xA1; break;
|
|
/* INVERTED EXCLAMATION MARK */
|
|
case 0xC2: *t++ = 0xC2; *t++ = 0xAC; break;
|
|
/* NOT SIGN */
|
|
case 0xC3: *t++ = 0xE2; *t++ = 0x88; *t++ = 0x9A; break;
|
|
/* SQUARE ROOT */
|
|
case 0xC4: *t++ = 0xC6; *t++ = 0x92; break;
|
|
/* LATIN SMALL LETTER F WITH HOOK */
|
|
case 0xC5: *t++ = 0xE2; *t++ = 0x89; *t++ = 0x88; break;
|
|
/* ALMOST EQUAL TO */
|
|
case 0xC6: *t++ = 0xE2; *t++ = 0x88; *t++ = 0x86; break;
|
|
/* INCREMENT */
|
|
case 0xC7: *t++ = 0xC2; *t++ = 0xAB; break;
|
|
/* LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
|
|
case 0xC8: *t++ = 0xC2; *t++ = 0xBB; break;
|
|
/* RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
|
|
case 0xC9: *t++ = 0xE2; *t++ = 0x80; *t++ = 0xA6; break;
|
|
/* HORIZONTAL ELLIPSIS */
|
|
case 0xCA: *t++ = 0xC2; *t++ = 0xA0; break;
|
|
/* NO-BREAK SPACE */
|
|
case 0xCB: *t++ = 0xC3; *t++ = 0x80; break;
|
|
/* LATIN CAPITAL LETTER A WITH GRAVE */
|
|
case 0xCC: *t++ = 0xC3; *t++ = 0x83; break;
|
|
/* LATIN CAPITAL LETTER A WITH TILDE */
|
|
case 0xCD: *t++ = 0xC3; *t++ = 0x95; break;
|
|
/* LATIN CAPITAL LETTER O WITH TILDE */
|
|
case 0xCE: *t++ = 0xC5; *t++ = 0x92; break;
|
|
/* LATIN CAPITAL LIGATURE OE */
|
|
case 0xCF: *t++ = 0xC5; *t++ = 0x93; break;
|
|
/* LATIN SMALL LIGATURE OE */
|
|
case 0xD0: *t++ = 0xE2; *t++ = 0x80; *t++ = 0x93; break;
|
|
/* EN DASH */
|
|
case 0xD1: *t++ = 0xE2; *t++ = 0x80; *t++ = 0x94; break;
|
|
/* EM DASH */
|
|
case 0xD2: *t++ = 0xE2; *t++ = 0x80; *t++ = 0x9C; break;
|
|
/* LEFT DOUBLE QUOTATION MARK */
|
|
case 0xD3: *t++ = 0xE2; *t++ = 0x80; *t++ = 0x9D; break;
|
|
/* RIGHT DOUBLE QUOTATION MARK */
|
|
case 0xD4: *t++ = 0xE2; *t++ = 0x80; *t++ = 0x98; break;
|
|
/* LEFT SINGLE QUOTATION MARK */
|
|
case 0xD5: *t++ = 0xE2; *t++ = 0x80; *t++ = 0x99; break;
|
|
/* RIGHT SINGLE QUOTATION MARK */
|
|
case 0xD6: *t++ = 0xC3; *t++ = 0xB7; break;
|
|
/* DIVISION SIGN */
|
|
case 0xD7: *t++ = 0xE2; *t++ = 0x97; *t++ = 0x8A; break;
|
|
/* LOZENGE */
|
|
case 0xD8: *t++ = 0xC3; *t++ = 0xBF; break;
|
|
/* LATIN SMALL LETTER Y WITH DIAERESIS */
|
|
case 0xD9: *t++ = 0xC5; *t++ = 0xB8; break;
|
|
/* LATIN CAPITAL LETTER Y WITH DIAERESIS */
|
|
case 0xDA: *t++ = 0xE2; *t++ = 0x81; *t++ = 0x84; break;
|
|
/* FRACTION SLASH */
|
|
case 0xDB: *t++ = 0xE2; *t++ = 0x82; *t++ = 0xAC; break;
|
|
/* EURO SIGN */
|
|
case 0xDC: *t++ = 0xE2; *t++ = 0x80; *t++ = 0xB9; break;
|
|
/* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
|
|
case 0xDD: *t++ = 0xE2; *t++ = 0x80; *t++ = 0xBA; break;
|
|
/* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
|
|
case 0xDE: *t++ = 0xEF; *t++ = 0xAC; *t++ = 0x81; break;
|
|
/* LATIN SMALL LIGATURE FI */
|
|
case 0xDF: *t++ = 0xEF; *t++ = 0xAC; *t++ = 0x82; break;
|
|
/* LATIN SMALL LIGATURE FL */
|
|
case 0xE0: *t++ = 0xE2; *t++ = 0x80; *t++ = 0xA1; break;
|
|
/* DOUBLE DAGGER */
|
|
case 0xE1: *t++ = 0xC2; *t++ = 0xB7; break;
|
|
/* MIDDLE DOT */
|
|
case 0xE2: *t++ = 0xE2; *t++ = 0x80; *t++ = 0x9A; break;
|
|
/* SINGLE LOW-9 QUOTATION MARK */
|
|
case 0xE3: *t++ = 0xE2; *t++ = 0x80; *t++ = 0x9E; break;
|
|
/* DOUBLE LOW-9 QUOTATION MARK */
|
|
case 0xE4: *t++ = 0xE2; *t++ = 0x80; *t++ = 0xB0; break;
|
|
/* PER MILLE SIGN */
|
|
case 0xE5: *t++ = 0xC3; *t++ = 0x82; break;
|
|
/* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
|
|
case 0xE6: *t++ = 0xC3; *t++ = 0x8A; break;
|
|
/* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
|
|
case 0xE7: *t++ = 0xC3; *t++ = 0x81; break;
|
|
/* LATIN CAPITAL LETTER A WITH ACUTE */
|
|
case 0xE8: *t++ = 0xC3; *t++ = 0x8B; break;
|
|
/* LATIN CAPITAL LETTER E WITH DIAERESIS */
|
|
case 0xE9: *t++ = 0xC3; *t++ = 0x88; break;
|
|
/* LATIN CAPITAL LETTER E WITH GRAVE */
|
|
case 0xEA: *t++ = 0xC3; *t++ = 0x8D; break;
|
|
/* LATIN CAPITAL LETTER I WITH ACUTE */
|
|
case 0xEB: *t++ = 0xC3; *t++ = 0x8E; break;
|
|
/* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
|
|
case 0xEC: *t++ = 0xC3; *t++ = 0x8F; break;
|
|
/* LATIN CAPITAL LETTER I WITH DIAERESIS */
|
|
case 0xED: *t++ = 0xC3; *t++ = 0x8C; break;
|
|
/* LATIN CAPITAL LETTER I WITH GRAVE */
|
|
case 0xEE: *t++ = 0xC3; *t++ = 0x93; break;
|
|
/* LATIN CAPITAL LETTER O WITH ACUTE */
|
|
case 0xEF: *t++ = 0xC3; *t++ = 0x94; break;
|
|
/* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
|
|
case 0xF0: *t++ = 0xEF; *t++ = 0xA3; *t++ = 0xBF; break;
|
|
/* Apple logo */
|
|
case 0xF1: *t++ = 0xC3; *t++ = 0x92; break;
|
|
/* LATIN CAPITAL LETTER O WITH GRAVE */
|
|
case 0xF2: *t++ = 0xC3; *t++ = 0x9A; break;
|
|
/* LATIN CAPITAL LETTER U WITH ACUTE */
|
|
case 0xF3: *t++ = 0xC3; *t++ = 0x9B; break;
|
|
/* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
|
|
case 0xF4: *t++ = 0xC3; *t++ = 0x99; break;
|
|
/* LATIN CAPITAL LETTER U WITH GRAVE */
|
|
case 0xF5: *t++ = 0xC4; *t++ = 0xB1; break;
|
|
/* LATIN SMALL LETTER DOTLESS I */
|
|
case 0xF6: *t++ = 0xCB; *t++ = 0x86; break;
|
|
/* MODIFIER LETTER CIRCUMFLEX ACCENT */
|
|
case 0xF7: *t++ = 0xCB; *t++ = 0x9C; break;
|
|
/* SMALL TILDE */
|
|
case 0xF8: *t++ = 0xC2; *t++ = 0xAF; break;
|
|
/* MACRON */
|
|
case 0xF9: *t++ = 0xCB; *t++ = 0x98; break;
|
|
/* BREVE */
|
|
case 0xFA: *t++ = 0xCB; *t++ = 0x99; break;
|
|
/* DOT ABOVE */
|
|
case 0xFB: *t++ = 0xCB; *t++ = 0x9A; break;
|
|
/* RING ABOVE */
|
|
case 0xFC: *t++ = 0xC2; *t++ = 0xB8; break;
|
|
/* CEDILLA */
|
|
case 0xFD: *t++ = 0xCB; *t++ = 0x9D; break;
|
|
/* DOUBLE ACUTE ACCENT */
|
|
case 0xFE: *t++ = 0xCB; *t++ = 0x9B; break;
|
|
/* OGONEK */
|
|
case 0xFF: *t++ = 0xCB; *t++ = 0x87; break;
|
|
/* CARON */
|
|
default: *t++ = '?'; break;
|
|
/* shouldn't get here */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if IncludeHostTextClipExchange
|
|
GLOBALOSGLUFUNC tMacErr HTCEexport(tPbuf i)
|
|
{
|
|
tMacErr err;
|
|
char *p;
|
|
uint8_t * s = PbufDat[i];
|
|
uimr L = PbufSize[i];
|
|
uimr sz = MacRoman2UniCodeSize(s, L);
|
|
|
|
if (NULL == (p = malloc(sz + 1))) {
|
|
err = mnvm_miscErr;
|
|
} else {
|
|
MacRoman2UniCodeData(s, L, p);
|
|
p[sz] = 0;
|
|
|
|
if (0 != SDL_SetClipboardText(p)) {
|
|
err = mnvm_miscErr;
|
|
} else {
|
|
err = mnvm_noErr;
|
|
}
|
|
free(p);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif
|
|
|
|
#if IncludeHostTextClipExchange
|
|
LOCALFUNC tMacErr UniCodeStrLength(char *s, uimr *r)
|
|
{
|
|
tMacErr err;
|
|
uint8_t t;
|
|
uint8_t t2;
|
|
char *p = s;
|
|
uimr L = 0;
|
|
|
|
label_retry:
|
|
if (0 == (t = *p++)) {
|
|
err = mnvm_noErr;
|
|
/* done */
|
|
} else
|
|
if (0 == (0x80 & t)) {
|
|
/* One-byte code */
|
|
L += 1;
|
|
goto label_retry;
|
|
} else
|
|
if (0 == (0x40 & t)) {
|
|
/* continuation code, error */
|
|
err = mnvm_miscErr;
|
|
} else
|
|
if (0 == (t2 = *p++)) {
|
|
err = mnvm_miscErr;
|
|
} else
|
|
if (0x80 != (0xC0 & t2)) {
|
|
/* not a continuation code, error */
|
|
err = mnvm_miscErr;
|
|
} else
|
|
if (0 == (0x20 & t)) {
|
|
/* two bytes */
|
|
L += 2;
|
|
goto label_retry;
|
|
} else
|
|
if (0 == (t2 = *p++)) {
|
|
err = mnvm_miscErr;
|
|
} else
|
|
if (0x80 != (0xC0 & t2)) {
|
|
/* not a continuation code, error */
|
|
err = mnvm_miscErr;
|
|
} else
|
|
if (0 == (0x10 & t)) {
|
|
/* three bytes */
|
|
L += 3;
|
|
goto label_retry;
|
|
} else
|
|
if (0 == (t2 = *p++)) {
|
|
err = mnvm_miscErr;
|
|
} else
|
|
if (0x80 != (0xC0 & t2)) {
|
|
/* not a continuation code, error */
|
|
err = mnvm_miscErr;
|
|
} else
|
|
if (0 == (0x08 & t)) {
|
|
/* four bytes */
|
|
L += 5;
|
|
goto label_retry;
|
|
} else
|
|
{
|
|
err = mnvm_miscErr;
|
|
/* longer code not supported yet */
|
|
}
|
|
|
|
*r = L;
|
|
return err;
|
|
}
|
|
#endif
|
|
|
|
#if IncludeHostTextClipExchange
|
|
LOCALFUNC uint8_t UniCodePoint2MacRoman(uint32_t x)
|
|
{
|
|
/*
|
|
adapted from
|
|
http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/ROMAN.TXT
|
|
*/
|
|
uint8_t y;
|
|
|
|
if (x < 128) {
|
|
y = x;
|
|
} else {
|
|
switch (x) {
|
|
case 0x00C4: y = 0x80; break;
|
|
/* LATIN CAPITAL LETTER A WITH DIAERESIS */
|
|
case 0x00C5: y = 0x81; break;
|
|
/* LATIN CAPITAL LETTER A WITH RING ABOVE */
|
|
case 0x00C7: y = 0x82; break;
|
|
/* LATIN CAPITAL LETTER C WITH CEDILLA */
|
|
case 0x00C9: y = 0x83; break;
|
|
/* LATIN CAPITAL LETTER E WITH ACUTE */
|
|
case 0x00D1: y = 0x84; break;
|
|
/* LATIN CAPITAL LETTER N WITH TILDE */
|
|
case 0x00D6: y = 0x85; break;
|
|
/* LATIN CAPITAL LETTER O WITH DIAERESIS */
|
|
case 0x00DC: y = 0x86; break;
|
|
/* LATIN CAPITAL LETTER U WITH DIAERESIS */
|
|
case 0x00E1: y = 0x87; break;
|
|
/* LATIN SMALL LETTER A WITH ACUTE */
|
|
case 0x00E0: y = 0x88; break;
|
|
/* LATIN SMALL LETTER A WITH GRAVE */
|
|
case 0x00E2: y = 0x89; break;
|
|
/* LATIN SMALL LETTER A WITH CIRCUMFLEX */
|
|
case 0x00E4: y = 0x8A; break;
|
|
/* LATIN SMALL LETTER A WITH DIAERESIS */
|
|
case 0x00E3: y = 0x8B; break;
|
|
/* LATIN SMALL LETTER A WITH TILDE */
|
|
case 0x00E5: y = 0x8C; break;
|
|
/* LATIN SMALL LETTER A WITH RING ABOVE */
|
|
case 0x00E7: y = 0x8D; break;
|
|
/* LATIN SMALL LETTER C WITH CEDILLA */
|
|
case 0x00E9: y = 0x8E; break;
|
|
/* LATIN SMALL LETTER E WITH ACUTE */
|
|
case 0x00E8: y = 0x8F; break;
|
|
/* LATIN SMALL LETTER E WITH GRAVE */
|
|
case 0x00EA: y = 0x90; break;
|
|
/* LATIN SMALL LETTER E WITH CIRCUMFLEX */
|
|
case 0x00EB: y = 0x91; break;
|
|
/* LATIN SMALL LETTER E WITH DIAERESIS */
|
|
case 0x00ED: y = 0x92; break;
|
|
/* LATIN SMALL LETTER I WITH ACUTE */
|
|
case 0x00EC: y = 0x93; break;
|
|
/* LATIN SMALL LETTER I WITH GRAVE */
|
|
case 0x00EE: y = 0x94; break;
|
|
/* LATIN SMALL LETTER I WITH CIRCUMFLEX */
|
|
case 0x00EF: y = 0x95; break;
|
|
/* LATIN SMALL LETTER I WITH DIAERESIS */
|
|
case 0x00F1: y = 0x96; break;
|
|
/* LATIN SMALL LETTER N WITH TILDE */
|
|
case 0x00F3: y = 0x97; break;
|
|
/* LATIN SMALL LETTER O WITH ACUTE */
|
|
case 0x00F2: y = 0x98; break;
|
|
/* LATIN SMALL LETTER O WITH GRAVE */
|
|
case 0x00F4: y = 0x99; break;
|
|
/* LATIN SMALL LETTER O WITH CIRCUMFLEX */
|
|
case 0x00F6: y = 0x9A; break;
|
|
/* LATIN SMALL LETTER O WITH DIAERESIS */
|
|
case 0x00F5: y = 0x9B; break;
|
|
/* LATIN SMALL LETTER O WITH TILDE */
|
|
case 0x00FA: y = 0x9C; break;
|
|
/* LATIN SMALL LETTER U WITH ACUTE */
|
|
case 0x00F9: y = 0x9D; break;
|
|
/* LATIN SMALL LETTER U WITH GRAVE */
|
|
case 0x00FB: y = 0x9E; break;
|
|
/* LATIN SMALL LETTER U WITH CIRCUMFLEX */
|
|
case 0x00FC: y = 0x9F; break;
|
|
/* LATIN SMALL LETTER U WITH DIAERESIS */
|
|
case 0x2020: y = 0xA0; break;
|
|
/* DAGGER */
|
|
case 0x00B0: y = 0xA1; break;
|
|
/* DEGREE SIGN */
|
|
case 0x00A2: y = 0xA2; break;
|
|
/* CENT SIGN */
|
|
case 0x00A3: y = 0xA3; break;
|
|
/* POUND SIGN */
|
|
case 0x00A7: y = 0xA4; break;
|
|
/* SECTION SIGN */
|
|
case 0x2022: y = 0xA5; break;
|
|
/* BULLET */
|
|
case 0x00B6: y = 0xA6; break;
|
|
/* PILCROW SIGN */
|
|
case 0x00DF: y = 0xA7; break;
|
|
/* LATIN SMALL LETTER SHARP S */
|
|
case 0x00AE: y = 0xA8; break;
|
|
/* REGISTERED SIGN */
|
|
case 0x00A9: y = 0xA9; break;
|
|
/* COPYRIGHT SIGN */
|
|
case 0x2122: y = 0xAA; break;
|
|
/* TRADE MARK SIGN */
|
|
case 0x00B4: y = 0xAB; break;
|
|
/* ACUTE ACCENT */
|
|
case 0x00A8: y = 0xAC; break;
|
|
/* DIAERESIS */
|
|
case 0x2260: y = 0xAD; break;
|
|
/* NOT EQUAL TO */
|
|
case 0x00C6: y = 0xAE; break;
|
|
/* LATIN CAPITAL LETTER AE */
|
|
case 0x00D8: y = 0xAF; break;
|
|
/* LATIN CAPITAL LETTER O WITH STROKE */
|
|
case 0x221E: y = 0xB0; break;
|
|
/* INFINITY */
|
|
case 0x00B1: y = 0xB1; break;
|
|
/* PLUS-MINUS SIGN */
|
|
case 0x2264: y = 0xB2; break;
|
|
/* LESS-THAN OR EQUAL TO */
|
|
case 0x2265: y = 0xB3; break;
|
|
/* GREATER-THAN OR EQUAL TO */
|
|
case 0x00A5: y = 0xB4; break;
|
|
/* YEN SIGN */
|
|
case 0x00B5: y = 0xB5; break;
|
|
/* MICRO SIGN */
|
|
case 0x2202: y = 0xB6; break;
|
|
/* PARTIAL DIFFERENTIAL */
|
|
case 0x2211: y = 0xB7; break;
|
|
/* N-ARY SUMMATION */
|
|
case 0x220F: y = 0xB8; break;
|
|
/* N-ARY PRODUCT */
|
|
case 0x03C0: y = 0xB9; break;
|
|
/* GREEK SMALL LETTER PI */
|
|
case 0x222B: y = 0xBA; break;
|
|
/* INTEGRAL */
|
|
case 0x00AA: y = 0xBB; break;
|
|
/* FEMININE ORDINAL INDICATOR */
|
|
case 0x00BA: y = 0xBC; break;
|
|
/* MASCULINE ORDINAL INDICATOR */
|
|
case 0x03A9: y = 0xBD; break;
|
|
/* GREEK CAPITAL LETTER OMEGA */
|
|
case 0x00E6: y = 0xBE; break;
|
|
/* LATIN SMALL LETTER AE */
|
|
case 0x00F8: y = 0xBF; break;
|
|
/* LATIN SMALL LETTER O WITH STROKE */
|
|
case 0x00BF: y = 0xC0; break;
|
|
/* INVERTED QUESTION MARK */
|
|
case 0x00A1: y = 0xC1; break;
|
|
/* INVERTED EXCLAMATION MARK */
|
|
case 0x00AC: y = 0xC2; break;
|
|
/* NOT SIGN */
|
|
case 0x221A: y = 0xC3; break;
|
|
/* SQUARE ROOT */
|
|
case 0x0192: y = 0xC4; break;
|
|
/* LATIN SMALL LETTER F WITH HOOK */
|
|
case 0x2248: y = 0xC5; break;
|
|
/* ALMOST EQUAL TO */
|
|
case 0x2206: y = 0xC6; break;
|
|
/* INCREMENT */
|
|
case 0x00AB: y = 0xC7; break;
|
|
/* LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
|
|
case 0x00BB: y = 0xC8; break;
|
|
/* RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
|
|
case 0x2026: y = 0xC9; break;
|
|
/* HORIZONTAL ELLIPSIS */
|
|
case 0x00A0: y = 0xCA; break;
|
|
/* NO-BREAK SPACE */
|
|
case 0x00C0: y = 0xCB; break;
|
|
/* LATIN CAPITAL LETTER A WITH GRAVE */
|
|
case 0x00C3: y = 0xCC; break;
|
|
/* LATIN CAPITAL LETTER A WITH TILDE */
|
|
case 0x00D5: y = 0xCD; break;
|
|
/* LATIN CAPITAL LETTER O WITH TILDE */
|
|
case 0x0152: y = 0xCE; break;
|
|
/* LATIN CAPITAL LIGATURE OE */
|
|
case 0x0153: y = 0xCF; break;
|
|
/* LATIN SMALL LIGATURE OE */
|
|
case 0x2013: y = 0xD0; break;
|
|
/* EN DASH */
|
|
case 0x2014: y = 0xD1; break;
|
|
/* EM DASH */
|
|
case 0x201C: y = 0xD2; break;
|
|
/* LEFT DOUBLE QUOTATION MARK */
|
|
case 0x201D: y = 0xD3; break;
|
|
/* RIGHT DOUBLE QUOTATION MARK */
|
|
case 0x2018: y = 0xD4; break;
|
|
/* LEFT SINGLE QUOTATION MARK */
|
|
case 0x2019: y = 0xD5; break;
|
|
/* RIGHT SINGLE QUOTATION MARK */
|
|
case 0x00F7: y = 0xD6; break;
|
|
/* DIVISION SIGN */
|
|
case 0x25CA: y = 0xD7; break;
|
|
/* LOZENGE */
|
|
case 0x00FF: y = 0xD8; break;
|
|
/* LATIN SMALL LETTER Y WITH DIAERESIS */
|
|
case 0x0178: y = 0xD9; break;
|
|
/* LATIN CAPITAL LETTER Y WITH DIAERESIS */
|
|
case 0x2044: y = 0xDA; break;
|
|
/* FRACTION SLASH */
|
|
case 0x20AC: y = 0xDB; break;
|
|
/* EURO SIGN */
|
|
case 0x2039: y = 0xDC; break;
|
|
/* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
|
|
case 0x203A: y = 0xDD; break;
|
|
/* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
|
|
case 0xFB01: y = 0xDE; break;
|
|
/* LATIN SMALL LIGATURE FI */
|
|
case 0xFB02: y = 0xDF; break;
|
|
/* LATIN SMALL LIGATURE FL */
|
|
case 0x2021: y = 0xE0; break;
|
|
/* DOUBLE DAGGER */
|
|
case 0x00B7: y = 0xE1; break;
|
|
/* MIDDLE DOT */
|
|
case 0x201A: y = 0xE2; break;
|
|
/* SINGLE LOW-9 QUOTATION MARK */
|
|
case 0x201E: y = 0xE3; break;
|
|
/* DOUBLE LOW-9 QUOTATION MARK */
|
|
case 0x2030: y = 0xE4; break;
|
|
/* PER MILLE SIGN */
|
|
case 0x00C2: y = 0xE5; break;
|
|
/* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
|
|
case 0x00CA: y = 0xE6; break;
|
|
/* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
|
|
case 0x00C1: y = 0xE7; break;
|
|
/* LATIN CAPITAL LETTER A WITH ACUTE */
|
|
case 0x00CB: y = 0xE8; break;
|
|
/* LATIN CAPITAL LETTER E WITH DIAERESIS */
|
|
case 0x00C8: y = 0xE9; break;
|
|
/* LATIN CAPITAL LETTER E WITH GRAVE */
|
|
case 0x00CD: y = 0xEA; break;
|
|
/* LATIN CAPITAL LETTER I WITH ACUTE */
|
|
case 0x00CE: y = 0xEB; break;
|
|
/* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
|
|
case 0x00CF: y = 0xEC; break;
|
|
/* LATIN CAPITAL LETTER I WITH DIAERESIS */
|
|
case 0x00CC: y = 0xED; break;
|
|
/* LATIN CAPITAL LETTER I WITH GRAVE */
|
|
case 0x00D3: y = 0xEE; break;
|
|
/* LATIN CAPITAL LETTER O WITH ACUTE */
|
|
case 0x00D4: y = 0xEF; break;
|
|
/* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
|
|
case 0xF8FF: y = 0xF0; break;
|
|
/* Apple logo */
|
|
case 0x00D2: y = 0xF1; break;
|
|
/* LATIN CAPITAL LETTER O WITH GRAVE */
|
|
case 0x00DA: y = 0xF2; break;
|
|
/* LATIN CAPITAL LETTER U WITH ACUTE */
|
|
case 0x00DB: y = 0xF3; break;
|
|
/* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
|
|
case 0x00D9: y = 0xF4; break;
|
|
/* LATIN CAPITAL LETTER U WITH GRAVE */
|
|
case 0x0131: y = 0xF5; break;
|
|
/* LATIN SMALL LETTER DOTLESS I */
|
|
case 0x02C6: y = 0xF6; break;
|
|
/* MODIFIER LETTER CIRCUMFLEX ACCENT */
|
|
case 0x02DC: y = 0xF7; break;
|
|
/* SMALL TILDE */
|
|
case 0x00AF: y = 0xF8; break;
|
|
/* MACRON */
|
|
case 0x02D8: y = 0xF9; break;
|
|
/* BREVE */
|
|
case 0x02D9: y = 0xFA; break;
|
|
/* DOT ABOVE */
|
|
case 0x02DA: y = 0xFB; break;
|
|
/* RING ABOVE */
|
|
case 0x00B8: y = 0xFC; break;
|
|
/* CEDILLA */
|
|
case 0x02DD: y = 0xFD; break;
|
|
/* DOUBLE ACUTE ACCENT */
|
|
case 0x02DB: y = 0xFE; break;
|
|
/* OGONEK */
|
|
case 0x02C7: y = 0xFF; break;
|
|
/* CARON */
|
|
default: y = '?'; break;
|
|
/* unrecognized */
|
|
}
|
|
}
|
|
|
|
return y;
|
|
}
|
|
#endif
|
|
|
|
#if IncludeHostTextClipExchange
|
|
LOCALPROC UniCodeStr2MacRoman(char *s, char *r)
|
|
{
|
|
tMacErr err;
|
|
uint8_t t;
|
|
uint8_t t2;
|
|
uint8_t t3;
|
|
uint8_t t4;
|
|
uint32_t v;
|
|
char *p = s;
|
|
char *q = r;
|
|
|
|
label_retry:
|
|
if (0 == (t = *p++)) {
|
|
err = mnvm_noErr;
|
|
/* done */
|
|
} else
|
|
if (0 == (0x80 & t)) {
|
|
*q++ = t;
|
|
goto label_retry;
|
|
} else
|
|
if (0 == (0x40 & t)) {
|
|
/* continuation code, error */
|
|
err = mnvm_miscErr;
|
|
} else
|
|
if (0 == (t2 = *p++)) {
|
|
err = mnvm_miscErr;
|
|
} else
|
|
if (0x80 != (0xC0 & t2)) {
|
|
/* not a continuation code, error */
|
|
err = mnvm_miscErr;
|
|
} else
|
|
if (0 == (0x20 & t)) {
|
|
/* two bytes */
|
|
v = t & 0x1F;
|
|
v = (v << 6) | (t2 & 0x3F);
|
|
*q++ = UniCodePoint2MacRoman(v);
|
|
goto label_retry;
|
|
} else
|
|
if (0 == (t3 = *p++)) {
|
|
err = mnvm_miscErr;
|
|
} else
|
|
if (0x80 != (0xC0 & t3)) {
|
|
/* not a continuation code, error */
|
|
err = mnvm_miscErr;
|
|
} else
|
|
if (0 == (0x10 & t)) {
|
|
/* three bytes */
|
|
v = t & 0x0F;
|
|
v = (v << 6) | (t3 & 0x3F);
|
|
v = (v << 6) | (t2 & 0x3F);
|
|
*q++ = UniCodePoint2MacRoman(v);
|
|
goto label_retry;
|
|
} else
|
|
if (0 == (t4 = *p++)) {
|
|
err = mnvm_miscErr;
|
|
} else
|
|
if (0x80 != (0xC0 & t4)) {
|
|
/* not a continuation code, error */
|
|
err = mnvm_miscErr;
|
|
} else
|
|
if (0 == (0x08 & t)) {
|
|
/* four bytes */
|
|
v = t & 0x07;
|
|
v = (v << 6) | (t4 & 0x3F);
|
|
v = (v << 6) | (t3 & 0x3F);
|
|
v = (v << 6) | (t2 & 0x3F);
|
|
*q++ = UniCodePoint2MacRoman(v);
|
|
goto label_retry;
|
|
} else
|
|
{
|
|
err = mnvm_miscErr;
|
|
/* longer code not supported yet */
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if IncludeHostTextClipExchange
|
|
GLOBALOSGLUFUNC tMacErr HTCEimport(tPbuf *r)
|
|
{
|
|
tMacErr err;
|
|
uimr L;
|
|
char *s = NULL;
|
|
tPbuf t = NotAPbuf;
|
|
|
|
if (NULL == (s = SDL_GetClipboardText())) {
|
|
err = mnvm_miscErr;
|
|
} else
|
|
if (mnvm_noErr != (err =
|
|
UniCodeStrLength(s, &L)))
|
|
{
|
|
/* fail */
|
|
} else
|
|
if (mnvm_noErr != (err =
|
|
PbufNew(L, &t)))
|
|
{
|
|
/* fail */
|
|
} else
|
|
{
|
|
err = mnvm_noErr;
|
|
|
|
UniCodeStr2MacRoman(s, PbufDat[t]);
|
|
*r = t;
|
|
t = NotAPbuf;
|
|
}
|
|
|
|
if (NotAPbuf != t) {
|
|
PbufDispose(t);
|
|
}
|
|
if (NULL != s) {
|
|
SDL_free(s);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif
|
|
|
|
/* --- event handling for main window --- */
|
|
|
|
#define UseMotionEvents 1
|
|
|
|
#if UseMotionEvents
|
|
LOCALVAR bool CaughtMouse = false;
|
|
#endif
|
|
|
|
LOCALPROC HandleTheEvent(SDL_Event *event)
|
|
{
|
|
switch (event->type) {
|
|
case SDL_QUIT:
|
|
RequestMacOff = true;
|
|
break;
|
|
case SDL_WINDOWEVENT:
|
|
switch (event->window.event) {
|
|
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
|
gTrueBackgroundFlag = 0;
|
|
break;
|
|
case SDL_WINDOWEVENT_FOCUS_LOST:
|
|
gTrueBackgroundFlag = 1;
|
|
break;
|
|
case SDL_WINDOWEVENT_ENTER:
|
|
CaughtMouse = 1;
|
|
break;
|
|
case SDL_WINDOWEVENT_LEAVE:
|
|
CaughtMouse = 0;
|
|
break;
|
|
}
|
|
break;
|
|
case SDL_MOUSEMOTION:
|
|
#if EnableFSMouseMotion && ! HaveWorkingWarp
|
|
if (HaveMouseMotion) {
|
|
MousePositionNotifyRelative(
|
|
event->motion.xrel, event->motion.yrel);
|
|
} else
|
|
#endif
|
|
{
|
|
MousePositionNotify(
|
|
event->motion.x, event->motion.y);
|
|
}
|
|
break;
|
|
case SDL_MOUSEBUTTONDOWN:
|
|
/* any mouse button, we don't care which */
|
|
#if EnableFSMouseMotion && ! HaveWorkingWarp
|
|
if (HaveMouseMotion) {
|
|
/* ignore position */
|
|
} else
|
|
#endif
|
|
{
|
|
MousePositionNotify(
|
|
event->button.x, event->button.y);
|
|
}
|
|
MouseButtonSet(true);
|
|
break;
|
|
case SDL_MOUSEBUTTONUP:
|
|
#if EnableFSMouseMotion && ! HaveWorkingWarp
|
|
if (HaveMouseMotion) {
|
|
/* ignore position */
|
|
} else
|
|
#endif
|
|
{
|
|
MousePositionNotify(
|
|
event->button.x, event->button.y);
|
|
}
|
|
MouseButtonSet(false);
|
|
break;
|
|
case SDL_KEYDOWN:
|
|
DoKeyCode(&event->key.keysym, true);
|
|
break;
|
|
case SDL_KEYUP:
|
|
DoKeyCode(&event->key.keysym, false);
|
|
break;
|
|
case SDL_MOUSEWHEEL:
|
|
if (event->wheel.x < 0) {
|
|
Keyboard_UpdateKeyMap2(MKC_Left, true);
|
|
Keyboard_UpdateKeyMap2(MKC_Left, false);
|
|
} else if (event->wheel.x > 0) {
|
|
Keyboard_UpdateKeyMap2(MKC_Right, true);
|
|
Keyboard_UpdateKeyMap2(MKC_Right, false);
|
|
}
|
|
if (event->wheel.y < 0) {
|
|
Keyboard_UpdateKeyMap2(MKC_Down, true);
|
|
Keyboard_UpdateKeyMap2(MKC_Down, false);
|
|
} else if(event->wheel.y > 0) {
|
|
Keyboard_UpdateKeyMap2(MKC_Up, true);
|
|
Keyboard_UpdateKeyMap2(MKC_Up, false);
|
|
}
|
|
break;
|
|
case SDL_DROPFILE:
|
|
{
|
|
char *s = event->drop.file;
|
|
|
|
(void) Sony_Insert1a(s, false);
|
|
SDL_RaiseWindow(main_wind);
|
|
SDL_free(s);
|
|
}
|
|
break;
|
|
#if 0
|
|
case Expose: /* SDL doesn't have an expose event */
|
|
int x0 = event->expose.x;
|
|
int y0 = event->expose.y;
|
|
int x1 = x0 + event->expose.width;
|
|
int y1 = y0 + event->expose.height;
|
|
|
|
if (x0 < 0) {
|
|
x0 = 0;
|
|
}
|
|
if (x1 > vMacScreenWidth) {
|
|
x1 = vMacScreenWidth;
|
|
}
|
|
if (y0 < 0) {
|
|
y0 = 0;
|
|
}
|
|
if (y1 > vMacScreenHeight) {
|
|
y1 = vMacScreenHeight;
|
|
}
|
|
if ((x0 < x1) && (y0 < y1)) {
|
|
HaveChangedScreenBuff(y0, x0, y1, x1);
|
|
}
|
|
break;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/* --- main window creation and disposal --- */
|
|
|
|
LOCALVAR int argc;
|
|
LOCALVAR char **argv;
|
|
|
|
LOCALFUNC bool Screen_Init(void)
|
|
{
|
|
bool v = false;
|
|
|
|
InitKeyCodes();
|
|
|
|
if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
|
|
{
|
|
fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
|
|
} else {
|
|
v = true;
|
|
}
|
|
|
|
return v;
|
|
}
|
|
|
|
#if MayFullScreen
|
|
LOCALVAR bool GrabMachine = false;
|
|
#endif
|
|
|
|
#if MayFullScreen
|
|
LOCALPROC GrabTheMachine(void)
|
|
{
|
|
#if GrabKeysFullScreen
|
|
SDL_SetWindowGrab(main_wind, SDL_TRUE);
|
|
#endif
|
|
|
|
#if EnableFSMouseMotion
|
|
|
|
#if HaveWorkingWarp
|
|
/*
|
|
if magnification changes, need to reset,
|
|
even if HaveMouseMotion already true
|
|
*/
|
|
if (MoveMouse(ViewHStart + (ViewHSize / 2),
|
|
ViewVStart + (ViewVSize / 2)))
|
|
{
|
|
SavedMouseH = ViewHStart + (ViewHSize / 2);
|
|
SavedMouseV = ViewVStart + (ViewVSize / 2);
|
|
HaveMouseMotion = true;
|
|
}
|
|
#else
|
|
if (0 == SDL_SetRelativeMouseMode(SDL_ENABLE)) {
|
|
HaveMouseMotion = true;
|
|
}
|
|
#endif
|
|
|
|
#endif /* EnableFSMouseMotion */
|
|
}
|
|
#endif
|
|
|
|
#if MayFullScreen
|
|
LOCALPROC UngrabMachine(void)
|
|
{
|
|
#if EnableFSMouseMotion
|
|
|
|
if (HaveMouseMotion) {
|
|
#if HaveWorkingWarp
|
|
(void) MoveMouse(CurMouseH, CurMouseV);
|
|
#else
|
|
SDL_SetRelativeMouseMode(SDL_DISABLE);
|
|
#endif
|
|
|
|
HaveMouseMotion = false;
|
|
}
|
|
|
|
#endif /* EnableFSMouseMotion */
|
|
|
|
#if GrabKeysFullScreen
|
|
SDL_SetWindowGrab(main_wind, SDL_FALSE);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#if EnableFSMouseMotion && HaveWorkingWarp
|
|
LOCALPROC MouseConstrain(void)
|
|
{
|
|
int16_t shiftdh;
|
|
int16_t 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 (! MoveMouse(SavedMouseH, SavedMouseV)) {
|
|
HaveMouseMotion = false;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
enum {
|
|
kMagStateNormal,
|
|
#if EnableMagnify
|
|
kMagStateMagnifgy,
|
|
#endif
|
|
kNumMagStates
|
|
};
|
|
|
|
#define kMagStateAuto kNumMagStates
|
|
|
|
#if MayNotFullScreen
|
|
LOCALVAR int CurWinIndx;
|
|
LOCALVAR bool HavePositionWins[kNumMagStates];
|
|
LOCALVAR int WinPositionsX[kNumMagStates];
|
|
LOCALVAR int WinPositionsY[kNumMagStates];
|
|
#endif
|
|
|
|
LOCALFUNC bool CreateMainWindow(void)
|
|
{
|
|
int NewWindowX;
|
|
int NewWindowY;
|
|
int NewWindowHeight = vMacScreenHeight;
|
|
int NewWindowWidth = vMacScreenWidth;
|
|
Uint32 flags = 0 /* SDL_WINDOW_HIDDEN */;
|
|
bool v = false;
|
|
|
|
#if EnableMagnify && 1
|
|
if (UseMagnify) {
|
|
NewWindowHeight *= WindowScale;
|
|
NewWindowWidth *= WindowScale;
|
|
}
|
|
#endif
|
|
|
|
#if VarFullScreen
|
|
if (UseFullScreen)
|
|
#endif
|
|
#if MayFullScreen
|
|
{
|
|
/*
|
|
We don't want physical screen mode to be changed in modern
|
|
displays, so we pass this _DESKTOP flag.
|
|
*/
|
|
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
|
|
|
NewWindowX = SDL_WINDOWPOS_UNDEFINED;
|
|
NewWindowY = SDL_WINDOWPOS_UNDEFINED;
|
|
}
|
|
#endif
|
|
#if VarFullScreen
|
|
else
|
|
#endif
|
|
#if MayNotFullScreen
|
|
{
|
|
int WinIndx;
|
|
|
|
#if EnableMagnify
|
|
if (UseMagnify) {
|
|
WinIndx = kMagStateMagnifgy;
|
|
} else
|
|
#endif
|
|
{
|
|
WinIndx = kMagStateNormal;
|
|
}
|
|
|
|
if (! HavePositionWins[WinIndx]) {
|
|
NewWindowX = SDL_WINDOWPOS_CENTERED;
|
|
NewWindowY = SDL_WINDOWPOS_CENTERED;
|
|
} else {
|
|
NewWindowX = WinPositionsX[WinIndx];
|
|
NewWindowY = WinPositionsY[WinIndx];
|
|
}
|
|
|
|
CurWinIndx = WinIndx;
|
|
}
|
|
#endif
|
|
|
|
#if 0
|
|
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
|
|
#endif
|
|
|
|
if (NULL == (main_wind = SDL_CreateWindow(
|
|
(NULL != n_arg) ? n_arg : kStrAppName,
|
|
NewWindowX, NewWindowY,
|
|
NewWindowWidth, NewWindowHeight,
|
|
flags)))
|
|
{
|
|
fprintf(stderr, "SDL_CreateWindow fails: %s\n",
|
|
SDL_GetError());
|
|
} else
|
|
if (NULL == (renderer = SDL_CreateRenderer(
|
|
main_wind, -1,
|
|
0 /* SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC */
|
|
/*
|
|
SDL_RENDERER_ACCELERATED not needed
|
|
"no flags gives priority to available
|
|
SDL_RENDERER_ACCELERATED renderers"
|
|
*/
|
|
/* would rather not require vsync */
|
|
)))
|
|
{
|
|
fprintf(stderr, "SDL_CreateRenderer fails: %s\n",
|
|
SDL_GetError());
|
|
} else
|
|
if (NULL == (texture = SDL_CreateTexture(
|
|
renderer,
|
|
SDL_PIXELFORMAT_ARGB8888,
|
|
SDL_TEXTUREACCESS_STREAMING,
|
|
#if UseSDLscaling
|
|
vMacScreenWidth, vMacScreenHeight
|
|
#else
|
|
NewWindowWidth, NewWindowHeight
|
|
#endif
|
|
)))
|
|
{
|
|
fprintf(stderr, "SDL_CreateTexture fails: %s\n",
|
|
SDL_GetError());
|
|
} else
|
|
if (NULL == (format = SDL_AllocFormat(SDL_PIXELFORMAT_ARGB8888)))
|
|
{
|
|
fprintf(stderr, "SDL_AllocFormat fails: %s\n",
|
|
SDL_GetError());
|
|
} else
|
|
{
|
|
/* SDL_ShowWindow(main_wind); */
|
|
|
|
SDL_RenderClear(renderer);
|
|
|
|
#if 0
|
|
SDL_DisplayMode info;
|
|
|
|
if (0 != SDL_GetCurrentDisplayMode(0, &info)) {
|
|
fprintf(stderr, "SDL_GetCurrentDisplayMode fails: %s\n",
|
|
SDL_GetError());
|
|
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
#if VarFullScreen
|
|
if (UseFullScreen)
|
|
#endif
|
|
#if MayFullScreen
|
|
{
|
|
int wr;
|
|
int hr;
|
|
|
|
SDL_GL_GetDrawableSize(main_wind, &wr, &hr);
|
|
|
|
ViewHSize = wr;
|
|
ViewVSize = hr;
|
|
#if EnableMagnify
|
|
if (UseMagnify) {
|
|
ViewHSize /= WindowScale;
|
|
ViewVSize /= WindowScale;
|
|
}
|
|
#endif
|
|
if (ViewHSize >= vMacScreenWidth) {
|
|
ViewHStart = 0;
|
|
ViewHSize = vMacScreenWidth;
|
|
} else {
|
|
ViewHSize &= ~ 1;
|
|
}
|
|
if (ViewVSize >= vMacScreenHeight) {
|
|
ViewVStart = 0;
|
|
ViewVSize = vMacScreenHeight;
|
|
} else {
|
|
ViewVSize &= ~ 1;
|
|
}
|
|
|
|
if (wr > NewWindowWidth) {
|
|
hOffset = (wr - NewWindowWidth) / 2;
|
|
} else {
|
|
hOffset = 0;
|
|
}
|
|
if (hr > NewWindowHeight) {
|
|
vOffset = (hr - NewWindowHeight) / 2;
|
|
} else {
|
|
vOffset = 0;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if 0 != vMacScreenDepth
|
|
ColorModeWorks = true;
|
|
#endif
|
|
|
|
v = true;
|
|
}
|
|
|
|
return v;
|
|
}
|
|
|
|
LOCALPROC CloseMainWindow(void)
|
|
{
|
|
if (NULL != format) {
|
|
SDL_FreeFormat(format);
|
|
format = NULL;
|
|
}
|
|
|
|
if (NULL != texture) {
|
|
SDL_DestroyTexture(texture);
|
|
texture = NULL;
|
|
}
|
|
|
|
if (NULL != renderer) {
|
|
SDL_DestroyRenderer(renderer);
|
|
renderer = NULL;
|
|
}
|
|
|
|
if (NULL != main_wind) {
|
|
SDL_DestroyWindow(main_wind);
|
|
main_wind = NULL;
|
|
}
|
|
}
|
|
|
|
#if EnableRecreateW
|
|
LOCALPROC ZapWState(void)
|
|
{
|
|
main_wind = NULL;
|
|
renderer = NULL;
|
|
texture = NULL;
|
|
format = NULL;
|
|
}
|
|
#endif
|
|
|
|
#if EnableRecreateW
|
|
struct WState {
|
|
#if MayFullScreen
|
|
uint16_t f_ViewHSize;
|
|
uint16_t f_ViewVSize;
|
|
uint16_t f_ViewHStart;
|
|
uint16_t f_ViewVStart;
|
|
int f_hOffset;
|
|
int f_vOffset;
|
|
#endif
|
|
#if VarFullScreen
|
|
bool f_UseFullScreen;
|
|
#endif
|
|
#if EnableMagnify
|
|
bool f_UseMagnify;
|
|
#endif
|
|
#if MayNotFullScreen
|
|
int f_CurWinIndx;
|
|
#endif
|
|
SDL_Window *f_main_wind;
|
|
SDL_Renderer *f_renderer;
|
|
SDL_Texture *f_texture;
|
|
SDL_PixelFormat *f_format;
|
|
};
|
|
typedef struct WState WState;
|
|
#endif
|
|
|
|
#if EnableRecreateW
|
|
LOCALPROC GetWState(WState *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_main_wind = main_wind;
|
|
r->f_renderer = renderer;
|
|
r->f_texture = texture;
|
|
r->f_format = format;
|
|
}
|
|
#endif
|
|
|
|
#if EnableRecreateW
|
|
LOCALPROC SetWState(WState *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
|
|
main_wind = r->f_main_wind;
|
|
renderer = r->f_renderer;
|
|
texture = r->f_texture;
|
|
format = r->f_format;
|
|
}
|
|
#endif
|
|
|
|
#if VarFullScreen && EnableMagnify
|
|
enum {
|
|
kWinStateWindowed,
|
|
#if EnableMagnify
|
|
kWinStateFullScreen,
|
|
#endif
|
|
kNumWinStates
|
|
};
|
|
#endif
|
|
|
|
#if VarFullScreen && EnableMagnify
|
|
LOCALVAR int WinMagStates[kNumWinStates];
|
|
#endif
|
|
|
|
#if EnableRecreateW
|
|
LOCALFUNC bool ReCreateMainWindow(void)
|
|
{
|
|
WState old_state;
|
|
WState new_state;
|
|
#if HaveWorkingWarp
|
|
bool HadCursorHidden = HaveCursorHidden;
|
|
#endif
|
|
#if VarFullScreen && EnableMagnify
|
|
int OldWinState =
|
|
UseFullScreen ? kWinStateFullScreen : kWinStateWindowed;
|
|
int OldMagState =
|
|
UseMagnify ? kMagStateMagnifgy : kMagStateNormal;
|
|
|
|
WinMagStates[OldWinState] =
|
|
OldMagState;
|
|
#endif
|
|
|
|
#if VarFullScreen
|
|
if (! UseFullScreen)
|
|
#endif
|
|
#if MayNotFullScreen
|
|
{
|
|
SDL_GetWindowPosition(main_wind,
|
|
&WinPositionsX[CurWinIndx],
|
|
&WinPositionsY[CurWinIndx]);
|
|
HavePositionWins[CurWinIndx] = true;
|
|
}
|
|
#endif
|
|
|
|
ForceShowCursor(); /* hide/show cursor api is per window */
|
|
|
|
#if MayFullScreen
|
|
if (GrabMachine) {
|
|
GrabMachine = false;
|
|
UngrabMachine();
|
|
}
|
|
#endif
|
|
|
|
GetWState(&old_state);
|
|
|
|
ZapWState();
|
|
|
|
#if EnableMagnify
|
|
UseMagnify = WantMagnify;
|
|
#endif
|
|
#if VarFullScreen
|
|
UseFullScreen = WantFullScreen;
|
|
#endif
|
|
|
|
if (! CreateMainWindow()) {
|
|
CloseMainWindow();
|
|
SetWState(&old_state);
|
|
|
|
/* avoid retry */
|
|
#if VarFullScreen
|
|
WantFullScreen = UseFullScreen;
|
|
#endif
|
|
#if EnableMagnify
|
|
WantMagnify = UseMagnify;
|
|
#endif
|
|
|
|
} else {
|
|
GetWState(&new_state);
|
|
SetWState(&old_state);
|
|
CloseMainWindow();
|
|
SetWState(&new_state);
|
|
|
|
#if HaveWorkingWarp
|
|
if (HadCursorHidden) {
|
|
(void) MoveMouse(CurMouseH, CurMouseV);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
LOCALPROC ZapWinStateVars(void)
|
|
{
|
|
#if MayNotFullScreen
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < kNumMagStates; ++i) {
|
|
HavePositionWins[i] = false;
|
|
}
|
|
}
|
|
#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 = false;
|
|
if (WantFullScreen) {
|
|
SDL_Rect r;
|
|
|
|
if (0 == SDL_GetDisplayBounds(0, &r)) {
|
|
if ((r.w >= vMacScreenWidth * WindowScale)
|
|
&& (r.h >= vMacScreenHeight * WindowScale)
|
|
)
|
|
{
|
|
WantMagnify = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
/* --- SavedTasks --- */
|
|
|
|
LOCALPROC LeaveBackground(void)
|
|
{
|
|
ReconnectKeyCodes3();
|
|
DisableKeyRepeat();
|
|
}
|
|
|
|
LOCALPROC EnterBackground(void)
|
|
{
|
|
RestoreKeyRepeat();
|
|
DisconnectKeyCodes3();
|
|
|
|
ForceShowCursor();
|
|
}
|
|
|
|
LOCALPROC LeaveSpeedStopped(void)
|
|
{
|
|
#if SoundEnabled
|
|
Sound_Start();
|
|
#endif
|
|
|
|
StartUpTimeAdjust();
|
|
}
|
|
|
|
LOCALPROC EnterSpeedStopped(void)
|
|
{
|
|
#if SoundEnabled
|
|
Sound_Stop();
|
|
#endif
|
|
}
|
|
|
|
LOCALPROC CheckForSavedTasks(void)
|
|
{
|
|
if (EvtQNeedRecover) {
|
|
EvtQNeedRecover = false;
|
|
|
|
/* attempt cleanup, EvtQNeedRecover may get set again */
|
|
EvtQTryRecoverFromFull();
|
|
}
|
|
|
|
#if EnableFSMouseMotion && HaveWorkingWarp
|
|
if (HaveMouseMotion) {
|
|
MouseConstrain();
|
|
}
|
|
#endif
|
|
|
|
if (RequestMacOff) {
|
|
RequestMacOff = false;
|
|
if (AnyDiskInserted()) {
|
|
MacMsgOverride(kStrQuitWarningTitle,
|
|
kStrQuitWarningMessage);
|
|
} else {
|
|
ForceMacOff = true;
|
|
}
|
|
}
|
|
|
|
if (ForceMacOff) {
|
|
return;
|
|
}
|
|
|
|
if (gTrueBackgroundFlag != gBackgroundFlag) {
|
|
gBackgroundFlag = gTrueBackgroundFlag;
|
|
if (gTrueBackgroundFlag) {
|
|
EnterBackground();
|
|
} else {
|
|
LeaveBackground();
|
|
}
|
|
}
|
|
|
|
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
|
|
)
|
|
{
|
|
(void) ReCreateMainWindow();
|
|
}
|
|
#endif
|
|
|
|
#if MayFullScreen
|
|
if (GrabMachine != (
|
|
#if VarFullScreen
|
|
UseFullScreen &&
|
|
#endif
|
|
! (gTrueBackgroundFlag || CurSpeedStopped)))
|
|
{
|
|
GrabMachine = ! GrabMachine;
|
|
if (GrabMachine) {
|
|
GrabTheMachine();
|
|
} else {
|
|
UngrabMachine();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (NeedWholeScreenDraw) {
|
|
NeedWholeScreenDraw = false;
|
|
ScreenChangedAll();
|
|
}
|
|
|
|
#if NeedRequestIthDisk
|
|
if (0 != RequestIthDisk) {
|
|
Sony_InsertIth(RequestIthDisk);
|
|
RequestIthDisk = 0;
|
|
}
|
|
#endif
|
|
|
|
if (HaveCursorHidden != (WantCursorHidden
|
|
&& ! (gTrueBackgroundFlag || CurSpeedStopped)))
|
|
{
|
|
HaveCursorHidden = ! HaveCursorHidden;
|
|
(void) SDL_ShowCursor(
|
|
HaveCursorHidden ? SDL_DISABLE : SDL_ENABLE);
|
|
}
|
|
}
|
|
|
|
/* --- command line parsing --- */
|
|
|
|
LOCALFUNC bool ScanCommandLine(void)
|
|
{
|
|
char *pa;
|
|
int i = 1;
|
|
|
|
label_retry:
|
|
if (i < argc) {
|
|
pa = argv[i++];
|
|
if ('-' == pa[0]) {
|
|
if ((0 == strcmp(pa, "--rom"))
|
|
|| (0 == strcmp(pa, "-r")))
|
|
{
|
|
if (i < argc) {
|
|
rom_path = argv[i++];
|
|
goto label_retry;
|
|
}
|
|
} else
|
|
if (0 == strcmp(pa, "-n"))
|
|
{
|
|
if (i < argc) {
|
|
n_arg = argv[i++];
|
|
goto label_retry;
|
|
}
|
|
} else
|
|
if (0 == strcmp(pa, "-d"))
|
|
{
|
|
if (i < argc) {
|
|
d_arg = argv[i++];
|
|
goto label_retry;
|
|
}
|
|
} else
|
|
if (('p' == pa[1]) && ('s' == pa[2]) && ('n' == pa[3]))
|
|
{
|
|
/* seen in OS X. ignore */
|
|
goto label_retry;
|
|
} else
|
|
{
|
|
MacMsg(kStrBadArgTitle, kStrBadArgMessage, false);
|
|
#if dbglog_HAVE
|
|
dbglog_writeln("bad command line argument");
|
|
dbglog_writeln(pa);
|
|
#endif
|
|
}
|
|
} else {
|
|
(void) Sony_Insert1(pa, false);
|
|
goto label_retry;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/* --- main program flow --- */
|
|
|
|
GLOBALOSGLUFUNC bool ExtraTimeNotOver(void)
|
|
{
|
|
UpdateTrueEmulatedTime();
|
|
return TrueEmulatedTime == OnTrueTime;
|
|
}
|
|
|
|
LOCALPROC WaitForTheNextEvent(void)
|
|
{
|
|
SDL_Event event;
|
|
|
|
if (SDL_WaitEvent(&event)) {
|
|
HandleTheEvent(&event);
|
|
}
|
|
}
|
|
|
|
LOCALPROC CheckForSystemEvents(void)
|
|
{
|
|
SDL_Event event;
|
|
int i = 10;
|
|
|
|
while ((--i >= 0) && SDL_PollEvent(&event)) {
|
|
HandleTheEvent(&event);
|
|
}
|
|
}
|
|
|
|
GLOBALOSGLUPROC WaitForNextTick(void)
|
|
{
|
|
label_retry:
|
|
CheckForSystemEvents();
|
|
CheckForSavedTasks();
|
|
|
|
if (ForceMacOff) {
|
|
return;
|
|
}
|
|
|
|
if (CurSpeedStopped) {
|
|
DoneWithDrawingForTick();
|
|
WaitForTheNextEvent();
|
|
goto label_retry;
|
|
}
|
|
|
|
if (ExtraTimeNotOver()) {
|
|
(void) SDL_Delay(NextIntTime - LastTime);
|
|
goto label_retry;
|
|
}
|
|
|
|
if (CheckDateTime()) {
|
|
#if SoundEnabled
|
|
Sound_SecondNotify();
|
|
#endif
|
|
}
|
|
|
|
if ((! gBackgroundFlag)
|
|
#if UseMotionEvents
|
|
&& (! CaughtMouse)
|
|
#endif
|
|
)
|
|
{
|
|
CheckMouseState();
|
|
}
|
|
|
|
OnTrueTime = TrueEmulatedTime;
|
|
|
|
#if dbglog_TimeStuff
|
|
dbglog_writelnNum("WaitForNextTick, OnTrueTime", OnTrueTime);
|
|
#endif
|
|
}
|
|
|
|
/* --- platform independent code can be thought of as going here --- */
|
|
|
|
#include "PROGMAIN.h"
|
|
|
|
LOCALPROC ZapOSGLUVars(void)
|
|
{
|
|
InitDrives();
|
|
ZapWinStateVars();
|
|
}
|
|
|
|
LOCALPROC ReserveAllocAll(void)
|
|
{
|
|
#if dbglog_HAVE
|
|
dbglog_ReserveAlloc();
|
|
#endif
|
|
ReserveAllocOneBlock(&ROM, kROM_Size, 5, false);
|
|
|
|
ReserveAllocOneBlock(&screencomparebuff,
|
|
vMacScreenNumBytes, 5, true);
|
|
#if UseControlKeys
|
|
ReserveAllocOneBlock(&CntrlDisplayBuff,
|
|
vMacScreenNumBytes, 5, false);
|
|
#endif
|
|
|
|
ReserveAllocOneBlock(&CLUT_final, CLUT_finalsz, 5, false);
|
|
#if SoundEnabled
|
|
ReserveAllocOneBlock((uint8_t * *)&TheSoundBuffer,
|
|
dbhBufferSize, 5, false);
|
|
#endif
|
|
|
|
EmulationReserveAlloc();
|
|
}
|
|
|
|
LOCALFUNC bool AllocMemory(void)
|
|
{
|
|
uimr n;
|
|
bool IsOk = false;
|
|
|
|
ReserveAllocOffset = 0;
|
|
ReserveAllocBigBlock = nullpr;
|
|
ReserveAllocAll();
|
|
n = ReserveAllocOffset;
|
|
ReserveAllocBigBlock = (uint8_t *)calloc(1, n);
|
|
if (NULL == ReserveAllocBigBlock) {
|
|
MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, true);
|
|
} else {
|
|
ReserveAllocOffset = 0;
|
|
ReserveAllocAll();
|
|
if (n != ReserveAllocOffset) {
|
|
/* oops, program error */
|
|
} else {
|
|
IsOk = true;
|
|
}
|
|
}
|
|
|
|
return IsOk;
|
|
}
|
|
|
|
LOCALPROC UnallocMemory(void)
|
|
{
|
|
if (nullpr != ReserveAllocBigBlock) {
|
|
free((char *)ReserveAllocBigBlock);
|
|
}
|
|
}
|
|
|
|
#if CanGetAppPath
|
|
LOCALFUNC bool InitWhereAmI(void)
|
|
{
|
|
app_parent = SDL_GetBasePath();
|
|
|
|
pref_dir = SDL_GetPrefPath("gryphel", "minivmac");
|
|
|
|
return true; /* keep going regardless */
|
|
}
|
|
#endif
|
|
|
|
#if CanGetAppPath
|
|
LOCALPROC UninitWhereAmI(void)
|
|
{
|
|
SDL_free(pref_dir);
|
|
|
|
SDL_free(app_parent);
|
|
}
|
|
#endif
|
|
|
|
LOCALFUNC bool InitOSGLU(void)
|
|
{
|
|
if (AllocMemory())
|
|
#if CanGetAppPath
|
|
if (InitWhereAmI())
|
|
#endif
|
|
#if dbglog_HAVE
|
|
if (dbglog_open())
|
|
#endif
|
|
if (ScanCommandLine())
|
|
if (LoadMacRom())
|
|
if (LoadInitialImages())
|
|
if (InitLocationDat())
|
|
#if SoundEnabled
|
|
if (Sound_Init())
|
|
#endif
|
|
if (Screen_Init())
|
|
if (CreateMainWindow())
|
|
if (WaitForRom())
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
LOCALPROC UnInitOSGLU(void)
|
|
{
|
|
if (MacMsgDisplayed) {
|
|
MacMsgDisplayOff();
|
|
}
|
|
|
|
RestoreKeyRepeat();
|
|
#if MayFullScreen
|
|
UngrabMachine();
|
|
#endif
|
|
#if SoundEnabled
|
|
Sound_Stop();
|
|
#endif
|
|
#if SoundEnabled
|
|
Sound_UnInit();
|
|
#endif
|
|
#if IncludePbufs
|
|
UnInitPbufs();
|
|
#endif
|
|
UnInitDrives();
|
|
|
|
ForceShowCursor();
|
|
|
|
#if dbglog_HAVE
|
|
dbglog_close();
|
|
#endif
|
|
|
|
#if CanGetAppPath
|
|
UninitWhereAmI();
|
|
#endif
|
|
UnallocMemory();
|
|
|
|
CheckSavedMacMsg();
|
|
|
|
CloseMainWindow();
|
|
|
|
SDL_Quit();
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
argc = argc;
|
|
argv = argv;
|
|
|
|
ZapOSGLUVars();
|
|
if (InitOSGLU()) {
|
|
ProgramMain();
|
|
}
|
|
UnInitOSGLU();
|
|
|
|
return 0;
|
|
}
|