minivmac4ios/Mini vMac/mnvm_core/COMOSGLU.h

1 line
23 KiB
C
Executable File

/*
COMOSGLU.h
Copyright (C) 2009 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.
*/
/*
COMmon code for Operating System GLUe
*/
GLOBALVAR ui3p ROM = nullpr;
GLOBALVAR ui5b vSonyWritableMask = 0;
GLOBALVAR ui5b vSonyInsertedMask = 0;
#if IncludeSonyRawMode
GLOBALVAR blnr vSonyRawMode = falseblnr;
#endif
#if IncludeSonyNew
GLOBALVAR blnr vSonyNewDiskWanted = falseblnr;
GLOBALVAR ui5b vSonyNewDiskSize;
#endif
#if IncludeSonyNameNew
GLOBALVAR tPbuf vSonyNewDiskName = NotAPbuf;
#endif
GLOBALVAR ui5b CurMacDateInSeconds = 0;
GLOBALVAR ui5b CurMacLatitude = 0;
GLOBALVAR ui5b CurMacLongitude = 0;
GLOBALVAR ui5b CurMacDelta = 0;
#if 0 != vMacScreenDepth
GLOBALVAR blnr UseColorMode = falseblnr;
GLOBALVAR blnr ColorModeWorks = falseblnr;
#endif
#if 0 != vMacScreenDepth
GLOBALVAR blnr ColorMappingChanged = falseblnr;
#endif
#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
GLOBALVAR ui4r CLUT_reds[CLUT_size];
GLOBALVAR ui4r CLUT_greens[CLUT_size];
GLOBALVAR ui4r CLUT_blues[CLUT_size];
#endif
LOCALVAR blnr RequestMacOff = falseblnr;
GLOBALVAR blnr ForceMacOff = falseblnr;
GLOBALVAR blnr WantMacInterrupt = falseblnr;
GLOBALVAR blnr WantMacReset = falseblnr;
GLOBALVAR ui3b SpeedValue = WantInitSpeedValue;
#if EnableAutoSlow
GLOBALVAR blnr WantNotAutoSlow = (WantInitNotAutoSlow != 0);
#endif
GLOBALVAR ui4b CurMouseV = 0;
GLOBALVAR ui4b CurMouseH = 0;
#if EnableMouseMotion && MayFullScreen
LOCALVAR blnr HaveMouseMotion = falseblnr;
#endif
#if EnableAutoSlow
GLOBALVAR ui5r QuietTime = 0;
GLOBALVAR ui5r QuietSubTicks = 0;
#endif
#if IncludePbufs
LOCALVAR ui5b PbufAllocatedMask;
LOCALVAR ui5b PbufSize[NumPbufs];
#endif
#if IncludePbufs
#define PbufIsAllocated(i) ((PbufAllocatedMask & ((ui5b)1 << (i))) != 0)
#endif
#if IncludePbufs
LOCALFUNC blnr FirstFreePbuf(tPbuf *r)
{
tPbuf i;
for (i = 0; i < NumPbufs; ++i) {
if (! PbufIsAllocated(i)) {
*r = i;
return trueblnr;
}
}
return falseblnr;
}
#endif
#if IncludePbufs
LOCALPROC PbufNewNotify(tPbuf Pbuf_No, ui5b count)
{
PbufSize[Pbuf_No] = count;
PbufAllocatedMask |= ((ui5b)1 << Pbuf_No);
}
#endif
#if IncludePbufs
LOCALPROC PbufDisposeNotify(tPbuf Pbuf_No)
{
PbufAllocatedMask &= ~ ((ui5b)1 << Pbuf_No);
}
#endif
#if IncludePbufs
GLOBALFUNC tMacErr CheckPbuf(tPbuf Pbuf_No)
{
tMacErr result;
if (Pbuf_No >= NumPbufs) {
result = mnvm_nsDrvErr;
} else if (! PbufIsAllocated(Pbuf_No)) {
result = mnvm_offLinErr;
} else {
result = mnvm_noErr;
}
return result;
}
#endif
#if IncludePbufs
GLOBALFUNC tMacErr PbufGetSize(tPbuf Pbuf_No, ui5r *Count)
{
tMacErr result = CheckPbuf(Pbuf_No);
if (mnvm_noErr == result) {
*Count = PbufSize[Pbuf_No];
}
return result;
}
#endif
LOCALFUNC blnr FirstFreeDisk(tDrive *Drive_No)
{
tDrive i;
for (i = 0; i < NumDrives; ++i) {
if (! vSonyIsInserted(i)) {
*Drive_No = i;
return trueblnr;
}
}
return falseblnr;
}
GLOBALFUNC blnr AnyDiskInserted(void)
{
#if 0
tDrive i;
for (i = 0; i < NumDrives; ++i) {
if (vSonyIsInserted(i)) {
return trueblnr;
}
}
return falseblnr;
#endif
return 0 != vSonyInsertedMask;
}
GLOBALPROC DiskRevokeWritable(tDrive Drive_No)
{
vSonyWritableMask &= ~ ((ui5b)1 << Drive_No);
}
LOCALPROC DiskInsertNotify(tDrive Drive_No, blnr locked)
{
vSonyInsertedMask |= ((ui5b)1 << Drive_No);
if (! locked) {
vSonyWritableMask |= ((ui5b)1 << Drive_No);
}
QuietEnds();
}
LOCALPROC DiskEjectedNotify(tDrive Drive_No)
{
vSonyWritableMask &= ~ ((ui5b)1 << Drive_No);
vSonyInsertedMask &= ~ ((ui5b)1 << Drive_No);
}
/*
block type - for operating on multiple ui3b elements
at a time.
*/
#if LittleEndianUnaligned || BigEndianUnaligned
#define uibb ui5b
#define uibr ui5r
#define ln2uiblockn 2
#if 0
#define uibb long long
#define uibr long long
#define ln2uiblockn 3
#endif
#else
#define uibb ui3b
#define uibr ui3r
#define ln2uiblockn 0
#endif
#define uiblockn (1 << ln2uiblockn)
#define ln2uiblockbitsn (3 + ln2uiblockn)
#define uiblockbitsn (8 * uiblockn)
LOCALFUNC blnr FindFirstChangeInLVecs(uibb *ptr1, uibb *ptr2,
uimr L, uimr *j)
{
/*
find index of first difference
*/
uibb *p1 = ptr1;
uibb *p2 = ptr2;
uimr i;
for (i = L; i != 0; --i) {
if (*p1++ != *p2++) {
--p1;
*j = p1 - ptr1;
return trueblnr;
}
}
return falseblnr;
}
LOCALPROC FindLastChangeInLVecs(uibb *ptr1, uibb *ptr2,
uimr L, uimr *j)
{
/*
find index of last difference, assuming there is one
*/
uibb *p1 = ptr1 + L;
uibb *p2 = ptr2 + L;
while (*--p1 == *--p2) {
}
*j = p1 - ptr1;
}
LOCALPROC FindLeftRightChangeInLMat(uibb *ptr1, uibb *ptr2,
uimr width, uimr top, uimr bottom,
uimr *LeftMin0, uibr *LeftMask0,
uimr *RightMax0, uibr *RightMask0)
{
uimr i;
uimr j;
uibb *p1;
uibb *p2;
uibr x;
ui5r offset = top * width;
uibb *p10 = (uibb *)ptr1 + offset;
uibb *p20 = (uibb *)ptr2 + offset;
uimr LeftMin = *LeftMin0;
uimr RightMax = *RightMax0;
uibr LeftMask = 0;
uibr RightMask = 0;
for (i = top; i < bottom; ++i) {
p1 = p10;
p2 = p20;
for (j = 0; j < LeftMin; ++j) {
x = *p1++ ^ *p2++;
if (0 != x) {
LeftMin = j;
LeftMask = x;
goto Label_3;
}
}
LeftMask |= (*p1 ^ *p2);
Label_3:
p1 = p10 + RightMax;
p2 = p20 + RightMax;
RightMask |= (*p1++ ^ *p2++);
for (j = RightMax + 1; j < width; ++j) {
x = *p1++ ^ *p2++;
if (0 != x) {
RightMax = j;
RightMask = x;
}
}
p10 += width;
p20 += width;
}
*LeftMin0 = LeftMin;
*RightMax0 = RightMax;
*LeftMask0 = LeftMask;
*RightMask0 = RightMask;
}
LOCALVAR ui3p screencomparebuff = nullpr;
LOCALVAR uimr NextDrawRow = 0;
#if BigEndianUnaligned
#define FlipCheckMonoBits (uiblockbitsn - 1)
#else
#define FlipCheckMonoBits 7
#endif
#define FlipCheckBits (FlipCheckMonoBits >> vMacScreenDepth)
#ifndef WantColorTransValid
#define WantColorTransValid 0
#endif
#if WantColorTransValid
LOCALVAR blnr ColorTransValid = falseblnr;
#endif
LOCALFUNC blnr ScreenFindChanges(ui3p screencurrentbuff,
si3b TimeAdjust, si4b *top, si4b *left, si4b *bottom, si4b *right)
{
uimr j0;
uimr j1;
uimr j0h;
uimr j1h;
uimr j0v;
uimr j1v;
uimr copysize;
uimr copyoffset;
uimr copyrows;
uimr LimitDrawRow;
uimr MaxRowsDrawnPerTick;
uimr LeftMin;
uimr RightMax;
uibr LeftMask;
uibr RightMask;
int j;
if (TimeAdjust < 4) {
MaxRowsDrawnPerTick = vMacScreenHeight;
} else if (TimeAdjust < 6) {
MaxRowsDrawnPerTick = vMacScreenHeight / 2;
} else {
MaxRowsDrawnPerTick = vMacScreenHeight / 4;
}
#if 0 != vMacScreenDepth
if (UseColorMode) {
if (ColorMappingChanged) {
ColorMappingChanged = falseblnr;
j0h = 0;
j1h = vMacScreenWidth;
j0v = 0;
j1v = vMacScreenHeight;
#if WantColorTransValid
ColorTransValid = falseblnr;
#endif
} else {
if (! FindFirstChangeInLVecs(
(uibb *)screencurrentbuff
+ NextDrawRow * (vMacScreenBitWidth / uiblockbitsn),
(uibb *)screencomparebuff
+ NextDrawRow * (vMacScreenBitWidth / uiblockbitsn),
((uimr)(vMacScreenHeight - NextDrawRow)
* (uimr)vMacScreenBitWidth) / uiblockbitsn,
&j0))
{
NextDrawRow = 0;
return falseblnr;
}
j0v = j0 / (vMacScreenBitWidth / uiblockbitsn);
j0h = j0 - j0v * (vMacScreenBitWidth / uiblockbitsn);
j0v += NextDrawRow;
LimitDrawRow = j0v + MaxRowsDrawnPerTick;
if (LimitDrawRow >= vMacScreenHeight) {
LimitDrawRow = vMacScreenHeight;
NextDrawRow = 0;
} else {
NextDrawRow = LimitDrawRow;
}
FindLastChangeInLVecs((uibb *)screencurrentbuff,
(uibb *)screencomparebuff,
((uimr)LimitDrawRow
* (uimr)vMacScreenBitWidth) / uiblockbitsn,
&j1);
j1v = j1 / (vMacScreenBitWidth / uiblockbitsn);
j1h = j1 - j1v * (vMacScreenBitWidth / uiblockbitsn);
j1v++;
if (j0h < j1h) {
LeftMin = j0h;
RightMax = j1h;
} else {
LeftMin = j1h;
RightMax = j0h;
}
FindLeftRightChangeInLMat((uibb *)screencurrentbuff,
(uibb *)screencomparebuff,
(vMacScreenBitWidth / uiblockbitsn),
j0v, j1v, &LeftMin, &LeftMask, &RightMax, &RightMask);
#if vMacScreenDepth > ln2uiblockbitsn
j0h = (LeftMin >> (vMacScreenDepth - ln2uiblockbitsn));
#elif ln2uiblockbitsn > vMacScreenDepth
for (j = 0; j < (1 << (ln2uiblockbitsn - vMacScreenDepth));
++j)
{
if (0 != (LeftMask
& (((((uibr)1) << (1 << vMacScreenDepth)) - 1)
<< ((j ^ FlipCheckBits) << vMacScreenDepth))))
{
goto Label_1c;
}
}
Label_1c:
j0h = (LeftMin << (ln2uiblockbitsn - vMacScreenDepth)) + j;
#else
j0h = LeftMin;
#endif
#if vMacScreenDepth > ln2uiblockbitsn
j1h = (RightMax >> (vMacScreenDepth - ln2uiblockbitsn)) + 1;
#elif ln2uiblockbitsn > vMacScreenDepth
for (j = (uiblockbitsn >> vMacScreenDepth); --j >= 0; ) {
if (0 != (RightMask
& (((((uibr)1) << (1 << vMacScreenDepth)) - 1)
<< ((j ^ FlipCheckBits) << vMacScreenDepth))))
{
goto Label_2c;
}
}
Label_2c:
j1h = (RightMax << (ln2uiblockbitsn - vMacScreenDepth))
+ j + 1;
#else
j1h = RightMax + 1;
#endif
}
copyrows = j1v - j0v;
copyoffset = j0v * vMacScreenByteWidth;
copysize = copyrows * vMacScreenByteWidth;
} else
#endif
{
#if 0 != vMacScreenDepth
if (ColorMappingChanged) {
ColorMappingChanged = falseblnr;
j0h = 0;
j1h = vMacScreenWidth;
j0v = 0;
j1v = vMacScreenHeight;
#if WantColorTransValid
ColorTransValid = falseblnr;
#endif
} else
#endif
{
if (! FindFirstChangeInLVecs(
(uibb *)screencurrentbuff
+ NextDrawRow * (vMacScreenWidth / uiblockbitsn),
(uibb *)screencomparebuff
+ NextDrawRow * (vMacScreenWidth / uiblockbitsn),
((uimr)(vMacScreenHeight - NextDrawRow)
* (uimr)vMacScreenWidth) / uiblockbitsn,
&j0))
{
NextDrawRow = 0;
return falseblnr;
}
j0v = j0 / (vMacScreenWidth / uiblockbitsn);
j0h = j0 - j0v * (vMacScreenWidth / uiblockbitsn);
j0v += NextDrawRow;
LimitDrawRow = j0v + MaxRowsDrawnPerTick;
if (LimitDrawRow >= vMacScreenHeight) {
LimitDrawRow = vMacScreenHeight;
NextDrawRow = 0;
} else {
NextDrawRow = LimitDrawRow;
}
FindLastChangeInLVecs((uibb *)screencurrentbuff,
(uibb *)screencomparebuff,
((uimr)LimitDrawRow
* (uimr)vMacScreenWidth) / uiblockbitsn,
&j1);
j1v = j1 / (vMacScreenWidth / uiblockbitsn);
j1h = j1 - j1v * (vMacScreenWidth / uiblockbitsn);
j1v++;
if (j0h < j1h) {
LeftMin = j0h;
RightMax = j1h;
} else {
LeftMin = j1h;
RightMax = j0h;
}
FindLeftRightChangeInLMat((uibb *)screencurrentbuff,
(uibb *)screencomparebuff,
(vMacScreenWidth / uiblockbitsn),
j0v, j1v, &LeftMin, &LeftMask, &RightMax, &RightMask);
for (j = 0; j < uiblockbitsn; ++j) {
if (0 != (LeftMask
& (((uibr)1) << (j ^ FlipCheckMonoBits))))
{
goto Label_1;
}
}
Label_1:
j0h = LeftMin * uiblockbitsn + j;
for (j = uiblockbitsn; --j >= 0; ) {
if (0 != (RightMask
& (((uibr)1) << (j ^ FlipCheckMonoBits))))
{
goto Label_2;
}
}
Label_2:
j1h = RightMax * uiblockbitsn + j + 1;
}
copyrows = j1v - j0v;
copyoffset = j0v * vMacScreenMonoByteWidth;
copysize = copyrows * vMacScreenMonoByteWidth;
}
MyMoveBytes((anyp)screencurrentbuff + copyoffset,
(anyp)screencomparebuff + copyoffset,
copysize);
*top = j0v;
*left = j0h;
*bottom = j1v;
*right = j1h;
return trueblnr;
}
GLOBALVAR blnr EmVideoDisable = falseblnr;
GLOBALVAR si3b EmLagTime = 0;
GLOBALVAR ui5b OnTrueTime = 0;
/*
The time slice we are currently dealing
with, in the same units as TrueEmulatedTime.
*/
LOCALVAR si4b ScreenChangedTop;
LOCALVAR si4b ScreenChangedLeft;
LOCALVAR si4b ScreenChangedBottom;
LOCALVAR si4b ScreenChangedRight;
LOCALPROC ScreenClearChanges(void)
{
ScreenChangedTop = vMacScreenHeight;
ScreenChangedBottom = 0;
ScreenChangedLeft = vMacScreenWidth;
ScreenChangedRight = 0;
}
LOCALPROC ScreenChangedAll(void)
{
ScreenChangedTop = 0;
ScreenChangedBottom = vMacScreenHeight;
ScreenChangedLeft = 0;
ScreenChangedRight = vMacScreenWidth;
}
#if EnableAutoSlow
LOCALVAR si4b ScreenChangedQuietTop = vMacScreenHeight;
LOCALVAR si4b ScreenChangedQuietLeft = vMacScreenWidth;
LOCALVAR si4b ScreenChangedQuietBottom = 0;
LOCALVAR si4b ScreenChangedQuietRight = 0;
#endif
GLOBALPROC Screen_OutputFrame(ui3p screencurrentbuff)
{
si4b top;
si4b left;
si4b bottom;
si4b right;
if (! EmVideoDisable) {
if (ScreenFindChanges(screencurrentbuff, EmLagTime,
&top, &left, &bottom, &right))
{
if (top < ScreenChangedTop) {
ScreenChangedTop = top;
}
if (bottom > ScreenChangedBottom) {
ScreenChangedBottom = bottom;
}
if (left < ScreenChangedLeft) {
ScreenChangedLeft = left;
}
if (right > ScreenChangedRight) {
ScreenChangedRight = right;
}
#if EnableAutoSlow
if (top < ScreenChangedQuietTop) {
ScreenChangedQuietTop = top;
}
if (bottom > ScreenChangedQuietBottom) {
ScreenChangedQuietBottom = bottom;
}
if (left < ScreenChangedQuietLeft) {
ScreenChangedQuietLeft = left;
}
if (right > ScreenChangedQuietRight) {
ScreenChangedQuietRight = right;
}
if (((ScreenChangedQuietRight - ScreenChangedQuietLeft) > 1)
|| ((ScreenChangedQuietBottom
- ScreenChangedQuietTop) > 32))
{
ScreenChangedQuietTop = vMacScreenHeight;
ScreenChangedQuietLeft = vMacScreenWidth;
ScreenChangedQuietBottom = 0;
ScreenChangedQuietRight = 0;
QuietEnds();
}
#endif
}
}
}
#if MayFullScreen
LOCALVAR ui4r ViewHSize;
LOCALVAR ui4r ViewVSize;
LOCALVAR ui4r ViewHStart = 0;
LOCALVAR ui4r ViewVStart = 0;
#if EnableMouseMotion
LOCALVAR si4b SavedMouseH;
LOCALVAR si4b SavedMouseV;
#endif
#endif
#ifndef WantAutoScrollBorder
#define WantAutoScrollBorder 0
#endif
#if EnableMouseMotion && MayFullScreen
LOCALPROC AutoScrollScreen(void)
{
si4b Shift;
si4b Limit;
/*
Scroll in multiples of two pixels, so as to
work better with the common gray pattern.
ViewHSize and ViewVSize are constrained
to a multiple of two.
Mac OS (some versions at least) constrains
the mouse position to be less than the screen
height and width, not allowing equal to it.
Can still scroll to see last pixel because
scroll in multiples of two pixels.
*/
if (vMacScreenWidth != ViewHSize) {
Shift = 0;
Limit = ViewHStart
#if WantAutoScrollBorder
+ (ViewHSize / 16)
#endif
;
if (CurMouseH < Limit) {
Shift = (Limit - CurMouseH + 1) & (~ 1);
Limit = ViewHStart;
if (Shift >= Limit) {
Shift = Limit;
}
Shift = - Shift;
} else {
Limit = ViewHStart + ViewHSize
#if WantAutoScrollBorder
- (ViewHSize / 16)
#endif
;
if (CurMouseH > Limit) {
Shift = (CurMouseH - Limit + 1) & (~ 1);
Limit = vMacScreenWidth - ViewHSize - ViewHStart;
if (Shift >= Limit) {
Shift = Limit;
}
}
}
if (Shift != 0) {
ViewHStart += Shift;
SavedMouseH += Shift;
ScreenChangedAll();
}
}
if (vMacScreenHeight != ViewVSize) {
Shift = 0;
Limit = ViewVStart
#if WantAutoScrollBorder
+ (ViewVSize / 16)
#endif
;
if (CurMouseV < Limit) {
Shift = (Limit - CurMouseV + 1) & (~ 1);
Limit = ViewVStart;
if (Shift >= Limit) {
Shift = Limit;
}
Shift = - Shift;
} else {
Limit = ViewVStart + ViewVSize
#if WantAutoScrollBorder
- (ViewVSize / 16)
#endif
;
if (CurMouseV > Limit) {
Shift = (CurMouseV - Limit + 1) & (~ 1);
Limit = vMacScreenHeight - ViewVSize - ViewVStart;
if (Shift >= Limit) {
Shift = Limit;
}
}
}
if (Shift != 0) {
ViewVStart += Shift;
SavedMouseV += Shift;
ScreenChangedAll();
}
}
}
#endif
LOCALPROC SetLongs(ui5b *p, long n)
{
long i;
for (i = n; --i >= 0; ) {
*p++ = (ui5b) -1;
}
}
LOCALVAR uimr ReserveAllocOffset;
LOCALVAR ui3p ReserveAllocBigBlock = nullpr;
#define PowOf2(p) ((uimr)1 << (p))
#define Pow2Mask(p) (PowOf2(p) - 1)
#define ModPow2(i, p) ((i) & Pow2Mask(p))
#define FloorDivPow2(i, p) ((i) >> (p))
#define FloorPow2Mult(i, p) ((i) & (~ Pow2Mask(p)))
#define CeilPow2Mult(i, p) FloorPow2Mult((i) + Pow2Mask(p), (p))
/* warning - CeilPow2Mult evaluates p twice */
GLOBALPROC ReserveAllocOneBlock(ui3p *p, uimr n,
ui3r align, blnr FillOnes)
{
ReserveAllocOffset = CeilPow2Mult(ReserveAllocOffset, align);
if (nullpr == ReserveAllocBigBlock) {
*p = nullpr;
} else {
*p = ReserveAllocBigBlock + ReserveAllocOffset;
if (FillOnes) {
SetLongs((ui5b *)*p, n / 4);
}
}
ReserveAllocOffset += n;
}
/* --- sending debugging info to file --- */
#if dbglog_HAVE
#define dbglog_bufsz PowOf2(dbglog_buflnsz)
LOCALVAR uimr dbglog_bufpos = 0;
LOCALVAR char *dbglog_bufp = nullpr;
LOCALPROC dbglog_ReserveAlloc(void)
{
ReserveAllocOneBlock((ui3p *)&dbglog_bufp, dbglog_bufsz,
5, falseblnr);
}
#define dbglog_open dbglog_open0
LOCALPROC dbglog_close(void)
{
uimr n = ModPow2(dbglog_bufpos, dbglog_buflnsz);
if (n != 0) {
dbglog_write0(dbglog_bufp, n);
}
dbglog_close0();
}
LOCALPROC dbglog_write(char *p, uimr L)
{
uimr r;
uimr bufposmod;
uimr curbufdiv;
uimr newbufpos = dbglog_bufpos + L;
uimr newbufdiv = FloorDivPow2(newbufpos, dbglog_buflnsz);
label_retry:
curbufdiv = FloorDivPow2(dbglog_bufpos, dbglog_buflnsz);
bufposmod = ModPow2(dbglog_bufpos, dbglog_buflnsz);
if (newbufdiv != curbufdiv) {
r = dbglog_bufsz - bufposmod;
MyMoveBytes((anyp)p, (anyp)(dbglog_bufp + bufposmod), r);
dbglog_write0(dbglog_bufp, dbglog_bufsz);
L -= r;
p += r;
dbglog_bufpos += r;
goto label_retry;
}
MyMoveBytes((anyp)p, (anyp)dbglog_bufp + bufposmod, L);
dbglog_bufpos = newbufpos;
}
LOCALFUNC uimr CStrLength(char *s)
{
char *p = s;
while (*p++ != 0) {
}
return p - s - 1;
}
GLOBALPROC dbglog_writeCStr(char *s)
{
/* fprintf(DumpFile, "%s", s); */
dbglog_write(s, CStrLength(s));
}
GLOBALPROC dbglog_writeReturn(void)
{
dbglog_writeCStr("\n");
/* fprintf(DumpFile, "\n"); */
}
GLOBALPROC dbglog_writeHex(uimr x)
{
ui3r v;
char s[16];
char *p = s + 16;
uimr n = 0;
do {
v = x & 0x0F;
if (v < 10) {
*--p = '0' + v;
} else {
*--p = 'A' + v - 10;
}
x >>= 4;
++n;
} while (x != 0);
dbglog_write(p, n);
/* fprintf(DumpFile, "%d", (int)x); */
}
GLOBALPROC dbglog_writeNum(uimr x)
{
uimr newx;
char s[16];
char *p = s + 16;
uimr n = 0;
do {
newx = x / (uimr)10;
*--p = '0' + (x - newx * 10);
x = newx;
++n;
} while (x != 0);
dbglog_write(p, n);
/* fprintf(DumpFile, "%d", (int)x); */
}
GLOBALPROC dbglog_writeMacChar(ui3r x)
{
char s;
if ((x > 32) && (x < 127)) {
s = x;
} else {
s = '?';
}
dbglog_write(&s, 1);
}
LOCALPROC dbglog_writeSpace(void)
{
dbglog_writeCStr(" ");
}
GLOBALPROC dbglog_writeln(char *s)
{
dbglog_writeCStr(s);
dbglog_writeReturn();
}
GLOBALPROC dbglog_writelnNum(char *s, simr v)
{
dbglog_writeCStr(s);
dbglog_writeSpace();
dbglog_writeNum(v);
dbglog_writeReturn();
}
#endif
/* my event queue */
#define MyEvtQLg2Sz 4
#define MyEvtQSz (1 << MyEvtQLg2Sz)
#define MyEvtQIMask (MyEvtQSz - 1)
LOCALVAR MyEvtQEl MyEvtQA[MyEvtQSz];
LOCALVAR ui4r MyEvtQIn = 0;
LOCALVAR ui4r MyEvtQOut = 0;
GLOBALFUNC MyEvtQEl * MyEvtQOutP(void)
{
MyEvtQEl *p = nullpr;
if (MyEvtQIn != MyEvtQOut) {
p = &MyEvtQA[MyEvtQOut & MyEvtQIMask];
}
return p;
}
GLOBALPROC MyEvtQOutDone(void)
{
++MyEvtQOut;
}
LOCALVAR blnr MyEvtQNeedRecover = falseblnr;
/* events lost because of full queue */
LOCALFUNC MyEvtQEl * MyEvtQElPreviousIn(void)
{
MyEvtQEl *p = NULL;
if (MyEvtQIn - MyEvtQOut != 0) {
p = &MyEvtQA[(MyEvtQIn - 1) & MyEvtQIMask];
}
return p;
}
LOCALFUNC MyEvtQEl * MyEvtQElAlloc(void)
{
MyEvtQEl *p = NULL;
if (MyEvtQIn - MyEvtQOut >= MyEvtQSz) {
MyEvtQNeedRecover = trueblnr;
} else {
p = &MyEvtQA[MyEvtQIn & MyEvtQIMask];
++MyEvtQIn;
}
return p;
}
LOCALVAR ui5b theKeys[4];
LOCALPROC Keyboard_UpdateKeyMap(int key, blnr down)
{
int k = key & 127; /* just for safety */
int bit = 1 << (k & 7);
ui3b *kp = (ui3b *)theKeys;
ui3b *kpi = &kp[k / 8];
blnr CurDown = ((*kpi & bit) != 0);
if (CurDown != down) {
MyEvtQEl *p = MyEvtQElAlloc();
if (NULL != p) {
p->kind = MyEvtQElKindKey;
p->u.press.key = k;
p->u.press.down = down;
if (down) {
*kpi |= bit;
} else {
*kpi &= ~ bit;
}
}
QuietEnds();
}
}
LOCALVAR blnr MyMouseButtonState = falseblnr;
LOCALPROC MyMouseButtonSet(blnr down)
{
if (MyMouseButtonState != down) {
MyEvtQEl *p = MyEvtQElAlloc();
if (NULL != p) {
p->kind = MyEvtQElKindMouseButton;
p->u.press.down = down;
MyMouseButtonState = down;
}
QuietEnds();
}
}
#if EnableMouseMotion && MayFullScreen
LOCALPROC MyMousePositionSetDelta(ui4r dh, ui4r dv)
{
if ((dh != 0) || (dv != 0)) {
MyEvtQEl *p = MyEvtQElPreviousIn();
if ((NULL != p) && (MyEvtQElKindMouseDelta == p->kind)) {
p->u.pos.h += dh;
p->u.pos.v += dv;
} else {
p = MyEvtQElAlloc();
if (NULL != p) {
p->kind = MyEvtQElKindMouseDelta;
p->u.pos.h = dh;
p->u.pos.v = dv;
}
}
QuietEnds();
}
}
#endif
LOCALVAR ui4b MyMousePosCurV = 0;
LOCALVAR ui4b MyMousePosCurH = 0;
LOCALPROC MyMousePositionSet(ui4r h, ui4r v)
{
if ((h != MyMousePosCurH) || (v != MyMousePosCurV)) {
MyEvtQEl *p = MyEvtQElPreviousIn();
if ((NULL == p) || (MyEvtQElKindMousePos != p->kind)) {
p = MyEvtQElAlloc();
}
if (NULL != p) {
p->kind = MyEvtQElKindMousePos;
p->u.pos.h = h;
p->u.pos.v = v;
MyMousePosCurH = h;
MyMousePosCurV = v;
}
QuietEnds();
}
}
#if 0
#define Keyboard_TestKeyMap(key) \
((((ui3b *)theKeys)[(key) / 8] & (1 << ((key) & 7))) != 0)
#endif
LOCALPROC InitKeyCodes(void)
{
theKeys[0] = 0;
theKeys[1] = 0;
theKeys[2] = 0;
theKeys[3] = 0;
}
#define kKeepMaskControl (1 << 0)
#define kKeepMaskCapsLock (1 << 1)
#define kKeepMaskCommand (1 << 2)
#define kKeepMaskOption (1 << 3)
#define kKeepMaskShift (1 << 4)
LOCALPROC DisconnectKeyCodes(ui5b KeepMask)
{
/*
Called when may miss key ups,
so act is if all pressed keys have been released,
except maybe for control, caps lock, command,
option and shift.
*/
int j;
int b;
int key;
ui5b m;
for (j = 0; j < 16; ++j) {
ui3b k1 = ((ui3b *)theKeys)[j];
if (0 != k1) {
ui3b bit = 1;
for (b = 0; b < 8; ++b) {
if (0 != (k1 & bit)) {
key = j * 8 + b;
switch (key) {
case MKC_Control: m = kKeepMaskControl; break;
case MKC_CapsLock: m = kKeepMaskCapsLock; break;
case MKC_Command: m = kKeepMaskCommand; break;
case MKC_Option: m = kKeepMaskOption; break;
case MKC_Shift: m = kKeepMaskShift; break;
default: m = 0; break;
}
if (0 == (KeepMask & m)) {
Keyboard_UpdateKeyMap(key, falseblnr);
}
}
bit <<= 1;
}
}
}
}
LOCALPROC MyEvtQTryRecoverFromFull(void)
{
MyMouseButtonSet(falseblnr);
DisconnectKeyCodes(0);
}
/* MacMsg */
LOCALVAR char *SavedBriefMsg = nullpr;
LOCALVAR char *SavedLongMsg;
LOCALVAR blnr SavedFatalMsg;
LOCALPROC MacMsg(char *briefMsg, char *longMsg, blnr fatal)
{
if (nullpr != SavedBriefMsg) {
/*
ignore the new message, only display the
first error.
*/
} else {
SavedBriefMsg = briefMsg;
SavedLongMsg = longMsg;
SavedFatalMsg = fatal;
}
}
GLOBALPROC WarnMsgCorruptedROM(void)
{
MacMsg(kStrCorruptedROMTitle, kStrCorruptedROMMessage, falseblnr);
}
GLOBALPROC WarnMsgUnsupportedROM(void)
{
MacMsg(kStrUnsupportedROMTitle,
kStrUnsupportedROMMessage, falseblnr);
}
GLOBALPROC WarnMsgAbnormal(void)
{
MacMsg(kStrReportAbnormalTitle,
kStrReportAbnormalMessage, falseblnr);
}