uvmac/src/UI/_deprecated/XPLAT/OSGLUSDL.c

2318 lines
46 KiB
C

/*
OSGLUSDL.c
Copyright (C) 2012 Paul C. Pratt
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 library
All operating system dependent code for the
SDL Library should go here.
*/
#include "CNFGRAPI.h"
#include "SYSDEPNS.h"
#include "UTIL/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 "LANG/INTLCHAR.h"
/* --- sending debugging info to file --- */
#if dbglog_HAVE
#define dbglog_ToStdErr 0
#if ! dbglog_ToStdErr
LOCALVAR FILE *dbglog_File = NULL;
#endif
LOCALFUNC bool dbglog_open0(void)
{
#if dbglog_ToStdErr
return true;
#else
dbglog_File = fopen("dbglog.txt", "w");
return (NULL != dbglog_File);
#endif
}
LOCALPROC dbglog_write0(char *s, uimr L)
{
#if dbglog_ToStdErr
(void) fwrite(s, 1, L, stderr);
#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 "UI/COMOSGLU.h"
#include "UTILS/PBUFSTDC.h"
#include "UI/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
LOCALVAR FILE *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 MacErr_t vSonyTransfer(bool IsWrite, uint8_t * Buffer,
tDrive Drive_No, uint32_t Sony_Start, uint32_t Sony_Count,
uint32_t *Sony_ActCount)
{
MacErr_t err = mnvm_miscErr;
FILE *refnum = Drives[Drive_No];
uint32_t NewSony_Count = 0;
if (0 == fseek(refnum, Sony_Start, SEEK_SET)) {
if (IsWrite) {
NewSony_Count = fwrite(Buffer, 1, Sony_Count, refnum);
} else {
NewSony_Count = fread(Buffer, 1, Sony_Count, refnum);
}
if (NewSony_Count == Sony_Count) {
err = mnvm_noErr;
}
}
if (nullpr != Sony_ActCount) {
*Sony_ActCount = NewSony_Count;
}
return err; /*& figure out what really to return &*/
}
GLOBALOSGLUFUNC MacErr_t vSonyGetSize(tDrive Drive_No, uint32_t *Sony_Count)
{
MacErr_t err = mnvm_miscErr;
FILE *refnum = Drives[Drive_No];
long v;
if (0 == fseek(refnum, 0, SEEK_END)) {
v = ftell(refnum);
if (v >= 0) {
*Sony_Count = v;
err = mnvm_noErr;
}
}
return err; /*& figure out what really to return &*/
}
LOCALFUNC MacErr_t vSonyEject0(tDrive Drive_No, bool deleteit)
{
FILE *refnum = Drives[Drive_No];
DiskEjectedNotify(Drive_No);
fclose(refnum);
Drives[Drive_No] = NotAfileRef; /* not really needed */
return mnvm_noErr;
}
GLOBALOSGLUFUNC MacErr_t 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(FILE *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) {
fclose(refnum);
}
return IsOk;
}
LOCALFUNC bool Sony_Insert1(char *drivepath, bool silentfail)
{
bool locked = false;
/* printf("Sony_Insert1 %s\n", drivepath); */
FILE *refnum = fopen(drivepath, "rb+");
if (NULL == refnum) {
locked = true;
refnum = fopen(drivepath, "rb");
}
if (NULL == refnum) {
if (! silentfail) {
MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, false);
}
} else {
return Sony_Insert0(refnum, locked, drivepath);
}
return false;
}
LOCALFUNC MacErr_t LoadMacRomFrom(char *path)
{
MacErr_t err;
FILE *ROM_File;
int File_Size;
ROM_File = fopen(path, "rb");
if (NULL == ROM_File) {
err = mnvm_fnfErr;
} else {
File_Size = fread(ROM, 1, kROM_Size, ROM_File);
if (File_Size != kROM_Size) {
if (feof(ROM_File)) {
MacMsgOverride(kStrShortROMTitle,
kStrShortROMMessage);
err = mnvm_eofErr;
} else {
MacMsgOverride(kStrNoReadROMTitle,
kStrNoReadROMMessage);
err = mnvm_miscErr;
}
} else {
err = ROM_IsValid();
}
fclose(ROM_File);
}
return err;
}
#if 0 /* no drag and drop to make use of this */
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;
}
#endif
LOCALFUNC bool Sony_Insert2(char *s)
{
return Sony_Insert1(s, true);
}
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;
LOCALFUNC bool LoadMacRom(void)
{
MacErr_t err;
if ((NULL == rom_path)
|| (mnvm_fnfErr == (err = LoadMacRomFrom(rom_path))))
if (mnvm_fnfErr == (err = LoadMacRomFrom(RomFileName)))
{
}
return true; /* keep launching Mini vMac, regardless */
}
/* --- video out --- */
#if 1
LOCALVAR bool UseFullScreen = (WantInitFullScreen != 0);
#endif
#if 1
LOCALVAR bool UseMagnify = (WantInitMagnify != 0);
#endif
LOCALVAR bool gBackgroundFlag = false;
LOCALVAR bool gTrueBackgroundFlag = false;
LOCALVAR bool CurSpeedStopped = true;
#if 1
#define MaxScale WindowScale
#else
#define MaxScale 1
#endif
LOCALVAR SDL_Surface *surface = nullpr;
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 1
*/
#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 "HW/SCREEN/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 "HW/SCREEN/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 "HW/SCREEN/SCRNMAPR.h"
#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 "HW/SCREEN/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 "HW/SCREEN/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 "HW/SCREEN/SCRNMAPR.h"
#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 "HW/SCREEN/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 "HW/SCREEN/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 "HW/SCREEN/SCRNMAPR.h"
#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 "HW/SCREEN/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 "HW/SCREEN/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 "HW/SCREEN/SCRNMAPR.h"
#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 = top;
uint32_t left2 = left;
uint32_t bottom2 = bottom;
uint32_t right2 = right;
#if 1
if (UseMagnify) {
top2 *= WindowScale;
left2 *= WindowScale;
bottom2 *= WindowScale;
right2 *= WindowScale;
}
#endif
if (SDL_MUSTLOCK(surface)) {
if (SDL_LockSurface(surface) < 0) {
return;
}
}
{
int bpp = surface->format->BytesPerPixel;
uint32_t ExpectedPitch = vMacScreenWidth * bpp;
#if 1
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(surface->format,
CLUT_reds[i] >> 8,
CLUT_greens[i] >> 8,
CLUT_blues[i] >> 8);
}
#endif
} else
#endif
{
BWLUT_pixel[1] = SDL_MapRGB(surface->format, 0, 0, 0);
/* black */
BWLUT_pixel[0] = SDL_MapRGB(surface->format, 255, 255, 255);
/* white */
}
if ((0 == ((bpp - 1) & bpp)) /* a power of 2 */
&& (surface->pitch == ExpectedPitch)
#if (vMacScreenDepth > 3)
&& ! UseColorMode
#endif
)
{
int k;
Uint32 v;
#if 1
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 1
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 *)surface->pixels;
#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
if (UseColorMode) {
#if 1
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 1
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 *)surface->pixels
+ i * surface->pitch + j * bpp;
#if 1
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(surface->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(surface->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;
}
}
}
}
}
if (SDL_MUSTLOCK(surface)) {
SDL_UnlockSurface(surface);
}
SDL_UpdateRect(surface, left2, top2,
right2 - left2, bottom2 - top2);
}
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 */
LOCALFUNC bool MoveMouse(int16_t h, int16_t v)
{
#if 1
if (UseMagnify) {
h *= WindowScale;
v *= WindowScale;
}
#endif
SDL_WarpMouse(h, v);
return true;
}
/* cursor state */
LOCALPROC MousePositionNotify(int NewMousePosh, int NewMousePosv)
{
bool ShouldHaveCursorHidden = true;
#if 1
if (UseMagnify) {
NewMousePosh /= WindowScale;
NewMousePosv /= WindowScale;
}
#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 1
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;
}
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 SDLKey2MacKeyCode(SDLKey i)
{
uint8_t v = MKC_None;
switch (i) {
case SDLK_BACKSPACE: v = MKC_BackSpace; break;
case SDLK_TAB: v = MKC_Tab; break;
case SDLK_CLEAR: v = MKC_Clear; break;
case SDLK_RETURN: v = MKC_Return; break;
case SDLK_PAUSE: v = MKC_Pause; break;
case SDLK_ESCAPE: v = MKC_formac_Escape; break;
case SDLK_SPACE: v = MKC_Space; break;
case SDLK_EXCLAIM: /* ? */ break;
case SDLK_QUOTEDBL: /* ? */ break;
case SDLK_HASH: /* ? */ break;
case SDLK_DOLLAR: /* ? */ break;
case SDLK_AMPERSAND: /* ? */ break;
case SDLK_QUOTE: v = MKC_SingleQuote; break;
case SDLK_LEFTPAREN: /* ? */ break;
case SDLK_RIGHTPAREN: /* ? */ break;
case SDLK_ASTERISK: /* ? */ break;
case SDLK_PLUS: /* ? */ break;
case SDLK_COMMA: v = MKC_Comma; break;
case SDLK_MINUS: v = MKC_Minus; break;
case SDLK_PERIOD: v = MKC_Period; break;
case SDLK_SLASH: v = MKC_formac_Slash; break;
case SDLK_0: v = MKC_0; break;
case SDLK_1: v = MKC_1; break;
case SDLK_2: v = MKC_2; break;
case SDLK_3: v = MKC_3; break;
case SDLK_4: v = MKC_4; break;
case SDLK_5: v = MKC_5; break;
case SDLK_6: v = MKC_6; break;
case SDLK_7: v = MKC_7; break;
case SDLK_8: v = MKC_8; break;
case SDLK_9: v = MKC_9; break;
case SDLK_COLON: /* ? */ break;
case SDLK_SEMICOLON: v = MKC_SemiColon; break;
case SDLK_LESS: /* ? */ break;
case SDLK_EQUALS: v = MKC_Equal; break;
case SDLK_GREATER: /* ? */ break;
case SDLK_QUESTION: /* ? */ break;
case SDLK_AT: /* ? */ break;
case SDLK_LEFTBRACKET: v = MKC_LeftBracket; break;
case SDLK_BACKSLASH: v = MKC_formac_BackSlash; break;
case SDLK_RIGHTBRACKET: v = MKC_RightBracket; break;
case SDLK_CARET: /* ? */ break;
case SDLK_UNDERSCORE: /* ? */ break;
case SDLK_BACKQUOTE: v = MKC_formac_Grave; break;
case SDLK_a: v = MKC_A; break;
case SDLK_b: v = MKC_B; break;
case SDLK_c: v = MKC_C; break;
case SDLK_d: v = MKC_D; break;
case SDLK_e: v = MKC_E; break;
case SDLK_f: v = MKC_F; break;
case SDLK_g: v = MKC_G; break;
case SDLK_h: v = MKC_H; break;
case SDLK_i: v = MKC_I; break;
case SDLK_j: v = MKC_J; break;
case SDLK_k: v = MKC_K; break;
case SDLK_l: v = MKC_L; break;
case SDLK_m: v = MKC_M; break;
case SDLK_n: v = MKC_N; break;
case SDLK_o: v = MKC_O; break;
case SDLK_p: v = MKC_P; break;
case SDLK_q: v = MKC_Q; break;
case SDLK_r: v = MKC_R; break;
case SDLK_s: v = MKC_S; break;
case SDLK_t: v = MKC_T; break;
case SDLK_u: v = MKC_U; break;
case SDLK_v: v = MKC_V; break;
case SDLK_w: v = MKC_W; break;
case SDLK_x: v = MKC_X; break;
case SDLK_y: v = MKC_Y; break;
case SDLK_z: v = MKC_Z; break;
case SDLK_KP0: v = MKC_KP0; break;
case SDLK_KP1: v = MKC_KP1; break;
case SDLK_KP2: v = MKC_KP2; break;
case SDLK_KP3: v = MKC_KP3; break;
case SDLK_KP4: v = MKC_KP4; break;
case SDLK_KP5: v = MKC_KP5; break;
case SDLK_KP6: v = MKC_KP6; break;
case SDLK_KP7: v = MKC_KP7; break;
case SDLK_KP8: v = MKC_KP8; break;
case SDLK_KP9: v = MKC_KP9; break;
case SDLK_KP_PERIOD: v = MKC_Decimal; break;
case SDLK_KP_DIVIDE: v = MKC_KPDevide; break;
case SDLK_KP_MULTIPLY: v = MKC_KPMultiply; break;
case SDLK_KP_MINUS: v = MKC_KPSubtract; break;
case SDLK_KP_PLUS: v = MKC_KPAdd; break;
case SDLK_KP_ENTER: v = MKC_formac_Enter; break;
case SDLK_KP_EQUALS: v = MKC_KPEqual; break;
case SDLK_UP: v = MKC_Up; break;
case SDLK_DOWN: v = MKC_Down; break;
case SDLK_RIGHT: v = MKC_Right; break;
case SDLK_LEFT: v = MKC_Left; break;
case SDLK_INSERT: v = MKC_formac_Help; break;
case SDLK_HOME: v = MKC_formac_Home; break;
case SDLK_END: v = MKC_formac_End; break;
case SDLK_PAGEUP: v = MKC_formac_PageUp; break;
case SDLK_PAGEDOWN: v = MKC_formac_PageDown; break;
case SDLK_F1: v = MKC_formac_F1; break;
case SDLK_F2: v = MKC_formac_F2; break;
case SDLK_F3: v = MKC_formac_F3; break;
case SDLK_F4: v = MKC_formac_F4; break;
case SDLK_F5: v = MKC_formac_F5; break;
case SDLK_F6: v = MKC_F6; break;
case SDLK_F7: v = MKC_F7; break;
case SDLK_F8: v = MKC_F8; break;
case SDLK_F9: v = MKC_F9; break;
case SDLK_F10: v = MKC_F10; break;
case SDLK_F11: v = MKC_F11; break;
case SDLK_F12: v = MKC_F12; break;
case SDLK_F13: /* ? */ break;
case SDLK_F14: /* ? */ break;
case SDLK_F15: /* ? */ break;
case SDLK_NUMLOCK: v = MKC_formac_ForwardDel; break;
case SDLK_CAPSLOCK: v = MKC_formac_CapsLock; break;
case SDLK_SCROLLOCK: v = MKC_ScrollLock; break;
case SDLK_RSHIFT: v = MKC_formac_RShift; break;
case SDLK_LSHIFT: v = MKC_formac_Shift; break;
case SDLK_RCTRL: v = MKC_formac_RControl; break;
case SDLK_LCTRL: v = MKC_formac_Control; break;
case SDLK_RALT: v = MKC_formac_RCommand; break;
case SDLK_LALT: v = MKC_formac_Command; break;
case SDLK_RMETA: v = MKC_formac_RCommand; break;
case SDLK_LMETA: v = MKC_formac_Command; break;
case SDLK_LSUPER: v = MKC_formac_Option; break;
case SDLK_RSUPER: v = MKC_formac_ROption; break;
case SDLK_MODE: /* ? */ break;
case SDLK_COMPOSE: /* ? */ break;
case SDLK_HELP: v = MKC_formac_Help; break;
case SDLK_PRINT: v = MKC_Print; break;
case SDLK_SYSREQ: /* ? */ break;
case SDLK_BREAK: /* ? */ break;
case SDLK_MENU: /* ? */ break;
case SDLK_POWER: /* ? */ break;
case SDLK_EURO: /* ? */ break;
case SDLK_UNDO: /* ? */ break;
default:
break;
}
return v;
}
LOCALPROC DoKeyCode(SDL_keysym *r, bool down)
{
uint8_t v = SDLKey2MacKeyCode(r->sym);
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);
fprintf(stderr, "%s\n", briefMsg0);
fprintf(stderr, "%s\n", longMsg0);
SavedBriefMsg = nullpr;
}
}
/* --- clipboard --- */
#define UseMotionEvents 1
#if UseMotionEvents
LOCALVAR bool CaughtMouse = false;
#endif
/* --- event handling for main window --- */
LOCALPROC HandleTheEvent(SDL_Event *event)
{
switch (event->type) {
case SDL_QUIT:
RequestMacOff = true;
break;
case SDL_ACTIVEEVENT:
switch (event->active.state) {
case SDL_APPINPUTFOCUS:
gTrueBackgroundFlag = (0 == event->active.gain);
#if 0 && UseMotionEvents
if (! gTrueBackgroundFlag) {
CheckMouseState();
}
#endif
break;
case SDL_APPMOUSEFOCUS:
CaughtMouse = (0 != event->active.gain);
break;
}
break;
case SDL_MOUSEMOTION:
MousePositionNotify(
event->motion.x, event->motion.y);
break;
case SDL_MOUSEBUTTONDOWN:
/* any mouse button, we don't care which */
MousePositionNotify(
event->button.x, event->button.y);
MouseButtonSet(true);
break;
case SDL_MOUSEBUTTONUP:
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;
#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 {
SDL_WM_SetCaption(kStrAppName, NULL);
v = true;
}
return v;
}
#if MayFullScreen
LOCALVAR bool GrabMachine = false;
#endif
#if MayFullScreen
LOCALPROC GrabTheMachine(void)
{
#if GrabKeysFullScreen
(void) SDL_WM_GrabInput(SDL_GRAB_ON);
#endif
#if EnableFSMouseMotion
/*
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;
}
#endif
}
#endif
#if MayFullScreen
LOCALPROC UngrabMachine(void)
{
#if EnableFSMouseMotion
if (HaveMouseMotion) {
(void) MoveMouse(CurMouseH, CurMouseV);
HaveMouseMotion = false;
}
#endif
#if GrabKeysFullScreen
(void) SDL_WM_GrabInput(SDL_GRAB_OFF);
#endif
}
#endif
#if EnableFSMouseMotion
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
LOCALFUNC bool CreateMainWindow(void)
{
int NewWindowHeight = vMacScreenHeight;
int NewWindowWidth = vMacScreenWidth;
Uint32 flags = SDL_SWSURFACE;
bool v = false;
#if 1 && 1
if (UseMagnify) {
NewWindowHeight *= WindowScale;
NewWindowWidth *= WindowScale;
}
#endif
#if 1
if (UseFullScreen)
#endif
#if MayFullScreen
{
flags |= SDL_FULLSCREEN;
}
#endif
ViewHStart = 0;
ViewVStart = 0;
ViewHSize = vMacScreenWidth;
ViewVSize = vMacScreenHeight;
surface = SDL_SetVideoMode(NewWindowWidth, NewWindowHeight,
#if 0 != vMacScreenDepth
32,
#else
/* 32 */ /* 24 */ /* 16 */ 8,
#endif
flags);
if (NULL == surface) {
fprintf(stderr, "SDL_SetVideoMode fails: %s\n",
SDL_GetError());
} else {
#if 0 != vMacScreenDepth
ColorModeWorks = true;
#endif
v = true;
}
return v;
}
#if EnableRecreateW
LOCALFUNC bool ReCreateMainWindow(void)
{
ForceShowCursor(); /* hide/show cursor api is per window */
#if MayFullScreen
if (GrabMachine) {
GrabMachine = false;
UngrabMachine();
}
#endif
#if 1
UseMagnify = WantMagnify;
#endif
#if 1
UseFullScreen = WantFullScreen;
#endif
(void) CreateMainWindow();
if (HaveCursorHidden) {
(void) MoveMouse(CurMouseH, CurMouseV);
}
return true;
}
#endif
LOCALPROC ZapWinStateVars(void)
{
}
#if 1
LOCALPROC ToggleWantFullScreen(void)
{
WantFullScreen = ! WantFullScreen;
}
#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
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)))
{
CurSpeedStopped = ! CurSpeedStopped;
if (CurSpeedStopped) {
EnterSpeedStopped();
} else {
LeaveSpeedStopped();
}
}
if ((nullpr != SavedBriefMsg) & ! MacMsgDisplayed) {
MacMsgDisplayOn();
}
#if EnableRecreateW
if (0
#if 1
|| (UseMagnify != WantMagnify)
#endif
#if 1
|| (UseFullScreen != WantFullScreen)
#endif
)
{
(void) ReCreateMainWindow();
}
#endif
#if MayFullScreen
if (GrabMachine != (
#if 1
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
{
MacMsg(kStrBadArgTitle, kStrBadArgMessage, false);
}
} 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);
}
}
LOCALFUNC bool InitOSGLU(void)
{
if (AllocMemory())
#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
UnallocMemory();
CheckSavedMacMsg();
SDL_Quit();
}
int main(int argc, char **argv)
{
argc = argc;
argv = argv;
ZapOSGLUVars();
if (InitOSGLU()) {
ProgramMain();
}
UnInitOSGLU();
return 0;
}