More PROGMAIN cleanup

This commit is contained in:
InvisibleUp 2020-03-05 20:51:39 -05:00
parent ae159cb2d7
commit 4b9e429c82
2 changed files with 124 additions and 179 deletions

View File

@ -1,7 +1,7 @@
# Makefile # Makefile
# Currently only builds Mac Plus emulator for Windows x64 # Currently only builds Mac Plus emulator for Windows x64
CC := clang CC := gcc
CCFLAGS := -O2 -Wall -Wmissing-prototypes -Wno-uninitialized -Wundef -Wstrict-prototypes -Icfg/ -Isrc/ CCFLAGS := -O2 -Wall -Wmissing-prototypes -Wno-uninitialized -Wundef -Wstrict-prototypes -Icfg/ -Isrc/
.PHONY: linux windows clean .PHONY: linux windows clean

View File

@ -67,6 +67,7 @@ typedef struct DevMethods {
void (*reset)(void); void (*reset)(void);
void (*starttick)(void); void (*starttick)(void);
void (*endtick)(void); void (*endtick)(void);
void (*subtick)(int);
void (*timebegin)(void); void (*timebegin)(void);
void (*timeend)(void); void (*timeend)(void);
} DevMethods_t; } DevMethods_t;
@ -78,6 +79,7 @@ const DevMethods_t DEVICES[] = {
.reset = NULL, .reset = NULL,
.starttick = NULL, .starttick = NULL,
.endtick = NULL, .endtick = NULL,
.subtick = NULL,
.timebegin = NULL, .timebegin = NULL,
.timeend = NULL, .timeend = NULL,
}, },
@ -87,6 +89,7 @@ const DevMethods_t DEVICES[] = {
.reset = NULL, .reset = NULL,
.starttick = NULL, .starttick = NULL,
.endtick = NULL, .endtick = NULL,
.subtick = NULL,
.timebegin = NULL, .timebegin = NULL,
.timeend = NULL, .timeend = NULL,
}, },
@ -96,6 +99,7 @@ const DevMethods_t DEVICES[] = {
.reset = Memory_Reset, .reset = Memory_Reset,
.starttick = NULL, .starttick = NULL,
.endtick = NULL, .endtick = NULL,
.subtick = NULL,
.timebegin = NULL, .timebegin = NULL,
.timeend = NULL, .timeend = NULL,
}, },
@ -105,6 +109,7 @@ const DevMethods_t DEVICES[] = {
.reset = ICT_Zap, .reset = ICT_Zap,
.starttick = NULL, .starttick = NULL,
.endtick = NULL, .endtick = NULL,
.subtick = NULL,
.timebegin = NULL, .timebegin = NULL,
.timeend = NULL, .timeend = NULL,
}, },
@ -114,6 +119,7 @@ const DevMethods_t DEVICES[] = {
.reset = IWM_Reset, .reset = IWM_Reset,
.starttick = NULL, .starttick = NULL,
.endtick = NULL, .endtick = NULL,
.subtick = NULL,
.timebegin = NULL, .timebegin = NULL,
.timeend = NULL, .timeend = NULL,
}, },
@ -123,6 +129,7 @@ const DevMethods_t DEVICES[] = {
.reset = SCC_Reset, .reset = SCC_Reset,
.starttick = NULL, .starttick = NULL,
.endtick = NULL, .endtick = NULL,
.subtick = NULL,
.timebegin = NULL, .timebegin = NULL,
.timeend = NULL, .timeend = NULL,
}, },
@ -132,6 +139,7 @@ const DevMethods_t DEVICES[] = {
.reset = SCSI_Reset, .reset = SCSI_Reset,
.starttick = NULL, .starttick = NULL,
.endtick = NULL, .endtick = NULL,
.subtick = NULL,
.timebegin = NULL, .timebegin = NULL,
.timeend = NULL, .timeend = NULL,
}, },
@ -141,6 +149,7 @@ const DevMethods_t DEVICES[] = {
.reset = VIA1_Zap, .reset = VIA1_Zap,
.starttick = NULL, .starttick = NULL,
.endtick = NULL, .endtick = NULL,
.subtick = NULL,
.timebegin = VIA1_ExtraTimeBegin, .timebegin = VIA1_ExtraTimeBegin,
.timeend = VIA1_ExtraTimeEnd, .timeend = VIA1_ExtraTimeEnd,
}, },
@ -150,6 +159,7 @@ const DevMethods_t DEVICES[] = {
.reset = EmVIA2 ? VIA2_Zap : NULL, .reset = EmVIA2 ? VIA2_Zap : NULL,
.starttick = NULL, .starttick = NULL,
.endtick = NULL, .endtick = NULL,
.subtick = NULL,
.timebegin = EmVIA2 ? VIA2_ExtraTimeBegin : NULL, .timebegin = EmVIA2 ? VIA2_ExtraTimeBegin : NULL,
.timeend = EmVIA2 ? VIA2_ExtraTimeEnd : NULL, .timeend = EmVIA2 ? VIA2_ExtraTimeEnd : NULL,
}, },
@ -159,6 +169,7 @@ const DevMethods_t DEVICES[] = {
.reset = Sony_Reset, .reset = Sony_Reset,
.starttick = Sony_Update, .starttick = Sony_Update,
.endtick = NULL, .endtick = NULL,
.subtick = NULL,
.timebegin = NULL, .timebegin = NULL,
.timeend = NULL, .timeend = NULL,
}, },
@ -168,6 +179,7 @@ const DevMethods_t DEVICES[] = {
.reset = Extn_Reset, .reset = Extn_Reset,
.starttick = NULL, .starttick = NULL,
.endtick = NULL, .endtick = NULL,
.subtick = NULL,
.timebegin = NULL, .timebegin = NULL,
.timeend = NULL, .timeend = NULL,
}, },
@ -177,6 +189,7 @@ const DevMethods_t DEVICES[] = {
.reset = m68k_reset, .reset = m68k_reset,
.starttick = NULL, .starttick = NULL,
.endtick = NULL, .endtick = NULL,
.subtick = NULL,
.timebegin = NULL, .timebegin = NULL,
.timeend = NULL, .timeend = NULL,
}, },
@ -186,6 +199,7 @@ const DevMethods_t DEVICES[] = {
.reset = NULL, .reset = NULL,
.starttick = Mouse_Update, .starttick = Mouse_Update,
.endtick = Mouse_EndTickNotify, .endtick = Mouse_EndTickNotify,
.subtick = NULL,
.timebegin = NULL, .timebegin = NULL,
.timeend = NULL, .timeend = NULL,
}, },
@ -195,6 +209,7 @@ const DevMethods_t DEVICES[] = {
.reset = NULL, .reset = NULL,
.starttick = EmClassicKbrd ? KeyBoard_Update : NULL, .starttick = EmClassicKbrd ? KeyBoard_Update : NULL,
.endtick = NULL, .endtick = NULL,
.subtick = NULL,
.timebegin = NULL, .timebegin = NULL,
.timeend = NULL, .timeend = NULL,
}, },
@ -204,6 +219,7 @@ const DevMethods_t DEVICES[] = {
.reset = NULL, .reset = NULL,
.starttick = EmADB ? ADB_Update : NULL, .starttick = EmADB ? ADB_Update : NULL,
.endtick = NULL, .endtick = NULL,
.subtick = NULL,
.timebegin = NULL, .timebegin = NULL,
.timeend = NULL, .timeend = NULL,
}, },
@ -222,6 +238,7 @@ const DevMethods_t DEVICES[] = {
.reset = NULL, .reset = NULL,
.starttick = EmVidCard ? Vid_Update : NULL, .starttick = EmVidCard ? Vid_Update : NULL,
.endtick = NULL, .endtick = NULL,
.subtick = NULL,
.timebegin = NULL, .timebegin = NULL,
.timeend = NULL, .timeend = NULL,
}, },
@ -231,9 +248,30 @@ const DevMethods_t DEVICES[] = {
.reset = NULL, .reset = NULL,
.starttick = Sixtieth_PulseNtfy, // VBlank interrupt .starttick = Sixtieth_PulseNtfy, // VBlank interrupt
.endtick = Screen_EndTickNotify, .endtick = Screen_EndTickNotify,
.subtick = NULL,
.timebegin = NULL, .timebegin = NULL,
.timeend = NULL, .timeend = NULL,
}, },
// ASC
{
.init = NULL,
.reset = NULL,
.starttick = NULL,
.endtick = NULL,
.subtick = EmASC ? ASC_SubTick : NULL,
.timebegin = NULL,
.timeend = NULL
},
// Sound (non-ASC)
{
.init = NULL,
.reset = NULL,
.starttick = NULL,
.endtick = NULL,
.subtick = (SoundEnabled && (CurEmMd != kEmMd_PB100)) ? MacSound_SubTick : NULL,
.timebegin = NULL,
.timeend = NULL
}
}; };
LOCALPROC EmulatedHardwareZap(void) LOCALPROC EmulatedHardwareZap(void)
@ -252,11 +290,7 @@ LOCALPROC DoMacReset(void)
LOCALPROC InterruptReset_Update(void) LOCALPROC InterruptReset_Update(void)
{ {
SetInterruptButton(false); SetInterruptButton(false); // don't keep held over 1/60 sec
/*
in case has been set. so only stays set
for 60th of a second.
*/
if (WantMacInterrupt) { if (WantMacInterrupt) {
SetInterruptButton(true); SetInterruptButton(true);
@ -270,20 +304,10 @@ LOCALPROC InterruptReset_Update(void)
LOCALPROC SubTickNotify(int SubTick) LOCALPROC SubTickNotify(int SubTick)
{ {
#if 0 int i;
dbglog_writeCStr("ending sub tick "); for ( i = 0; i < ARRAY_SIZE(DEVICES); i++ ) {
dbglog_writeNum(SubTick); if (DEVICES[i].subtick != NULL) { DEVICES[i].subtick(SubTick); }
dbglog_writeReturn(); }
#endif
#if EmASC
ASC_SubTick(SubTick);
#else
#if SoundEnabled && (CurEmMd != kEmMd_PB100)
MacSound_SubTick(SubTick);
#else
UnusedParam(SubTick);
#endif
#endif
} }
#define CyclesScaledPerTick (130240UL * ClockMult * kCycleScale) #define CyclesScaledPerTick (130240UL * ClockMult * kCycleScale)
@ -320,9 +344,7 @@ LOCALPROC SubTickTaskEnd(void)
LOCALPROC SixtiethSecondNotify(void) LOCALPROC SixtiethSecondNotify(void)
{ {
int i; int i;
#if dbglog_HAVE && 0 // Begin new frame
dbglog_WriteNote("begin new Sixtieth");
#endif
InterruptReset_Update(); InterruptReset_Update();
for ( i = 0; i < ARRAY_SIZE(DEVICES); i++ ) { for ( i = 0; i < ARRAY_SIZE(DEVICES); i++ ) {
if (DEVICES[i].starttick != NULL) { DEVICES[i].starttick(); } if (DEVICES[i].starttick != NULL) { DEVICES[i].starttick(); }
@ -338,29 +360,23 @@ LOCALPROC SixtiethEndNotify(void)
for ( i = 0; i < ARRAY_SIZE(DEVICES); i++ ) { for ( i = 0; i < ARRAY_SIZE(DEVICES); i++ ) {
if (DEVICES[i].endtick != NULL) { DEVICES[i].endtick(); } if (DEVICES[i].endtick != NULL) { DEVICES[i].endtick(); }
} }
#if dbglog_HAVE && 0 // End frame
dbglog_WriteNote("end Sixtieth");
#endif
} }
LOCALPROC ExtraTimeBeginNotify(void) LOCALPROC ExtraTimeBeginNotify(void)
{ {
#if 0 int i;
dbglog_writeCStr("begin extra time"); for ( i = 0; i < ARRAY_SIZE(DEVICES); i++ ) {
dbglog_writeReturn(); if (DEVICES[i].timebegin != NULL) { DEVICES[i].timebegin(); }
#endif }
VIA1_ExtraTimeBegin();
if (_EmVIA2) { VIA2_ExtraTimeBegin(); }
} }
LOCALPROC ExtraTimeEndNotify(void) LOCALPROC ExtraTimeEndNotify(void)
{ {
VIA1_ExtraTimeEnd(); int i;
if (_EmVIA2) { VIA2_ExtraTimeEnd(); } for ( i = 0; i < ARRAY_SIZE(DEVICES); i++ ) {
#if 0 if (DEVICES[i].timeend != NULL) { DEVICES[i].timeend(); }
dbglog_writeCStr("end extra time"); }
dbglog_writeReturn();
#endif
} }
GLOBALPROC EmulationReserveAlloc(void) GLOBALPROC EmulationReserveAlloc(void)
@ -439,61 +455,35 @@ LOCALPROC ICT_DoTask(int taskid)
LOCALPROC ICT_DoCurrentTasks(void) LOCALPROC ICT_DoCurrentTasks(void)
{ {
int i = 0; int i;
uimr m = ICTactive; uimr m;
while (0 != m) { // For each ICT...
if (0 != (m & 1)) { for (m = ICTactive, i = 0; m != 0; m >>=1, i += 1) {
if (i >= kNumICTs) { // If no ICT here, continue
/* shouldn't happen */ if (0 == (m & 1)) { continue; }
ICTactive &= ((1 << kNumICTs) - 1); if (ICTwhen[i] != NextiCount) { continue; }
m = 0;
} else if (ICTwhen[i] == NextiCount) {
ICTactive &= ~ (1 << i);
#ifdef _VIA_Debug
fprintf(stderr, "doing task %d, %d\n", NextiCount, i);
#endif
ICT_DoTask(i);
/* /*
A Task may set the time of A Task may set the time of any task, including
any task, including itself. itself. But it cannot set any task to execute
But it cannot set any task immediately, so one pass is sufficient.
to execute immediately, so */
one pass is sufficient. ICTactive &= ~(1 << i); // Clear active bit
*/ ICT_DoTask(i);
}
}
++i;
m >>= 1;
} }
} }
LOCALFUNC uint32_t ICT_DoGetNext(uint32_t maxn) LOCALFUNC uint32_t ICT_DoGetNext(uint32_t maxn)
{ {
int i = 0; int i;
uimr m = ICTactive; uimr m;
uint32_t v = maxn; uint32_t v = maxn;
while (0 != m) { for (m = ICTactive, i = 0; m != 0; m >>=1, i += 1) {
if (0 != (m & 1)) { uint32_t d = ICTwhen[i] - NextiCount;
if (i >= kNumICTs) { if (0 == (m & 1)) { continue; }
/* shouldn't happen */ if (d < v) { v = d; }
m = 0;
} else {
uint32_t d = ICTwhen[i] - NextiCount;
/* at this point d must be > 0 */
if (d < v) {
#ifdef _VIA_Debug
fprintf(stderr, "coming task %d, %d, %d\n",
NextiCount, i, d);
#endif
v = d;
}
}
}
++i;
m >>= 1;
} }
return v; return v;
@ -506,16 +496,6 @@ LOCALPROC m68k_go_nCycles_1(uint32_t n)
do { do {
ICT_DoCurrentTasks(); ICT_DoCurrentTasks();
n2 = ICT_DoGetNext(n); n2 = ICT_DoGetNext(n);
#if dbglog_HAVE && 0
dbglog_StartLine();
dbglog_writeCStr("before m68k_go_nCycles, NextiCount:");
dbglog_writeHex(NextiCount);
dbglog_writeCStr(", n2:");
dbglog_writeHex(n2);
dbglog_writeCStr(", n:");
dbglog_writeHex(n);
dbglog_writeReturn();
#endif
NextiCount += n2; NextiCount += n2;
m68k_go_nCycles(n2); m68k_go_nCycles(n2);
n = StopiCount - NextiCount; n = StopiCount - NextiCount;
@ -527,30 +507,21 @@ LOCALVAR uint32_t ExtraSubTicksToDo = 0;
LOCALPROC DoEmulateOneTick(void) LOCALPROC DoEmulateOneTick(void)
{ {
#if EnableAutoSlow #if EnableAutoSlow
{ uint32_t NewQuietTime = QuietTime + 1;
uint32_t NewQuietTime = QuietTime + 1; uint32_t NewQuietSubTicks = QuietSubTicks + kNumSubTicks;
if (NewQuietTime > QuietTime) { if (NewQuietTime > QuietTime) {
/* if not overflow */ /* if not overflow */
QuietTime = NewQuietTime; QuietTime = NewQuietTime;
}
} }
#endif if (NewQuietSubTicks > QuietSubTicks) {
#if EnableAutoSlow /* if not overflow */
{ QuietSubTicks = NewQuietSubTicks;
uint32_t NewQuietSubTicks = QuietSubTicks + kNumSubTicks;
if (NewQuietSubTicks > QuietSubTicks) {
/* if not overflow */
QuietSubTicks = NewQuietSubTicks;
}
} }
#endif #endif
SixtiethSecondNotify(); SixtiethSecondNotify();
m68k_go_nCycles_1(CyclesScaledPerTick); m68k_go_nCycles_1(CyclesScaledPerTick);
SixtiethEndNotify(); SixtiethEndNotify();
if ((uint8_t) -1 == SpeedValue) { if ((uint8_t) -1 == SpeedValue) {
@ -587,29 +558,22 @@ LOCALFUNC bool MoreSubTicksToDo(void)
return v; return v;
} }
/*
DoEmulateExtraTime is used for anything over emulation speed of 1x. It
periodically calls ExtraTimeNotOver and stops when this returns false
(or it is finished with emulating the extra time).
*/
LOCALPROC DoEmulateExtraTime(void) LOCALPROC DoEmulateExtraTime(void)
{ {
/*
DoEmulateExtraTime is used for
anything over emulation speed
of 1x. It periodically calls
ExtraTimeNotOver and stops
when this returns false (or it
is finished with emulating the
extra time).
*/
if (MoreSubTicksToDo()) { if (MoreSubTicksToDo()) {
ExtraTimeBeginNotify(); ExtraTimeBeginNotify();
do { do {
#if EnableAutoSlow #if EnableAutoSlow
{ uint32_t NewQuietSubTicks = QuietSubTicks + 1;
uint32_t NewQuietSubTicks = QuietSubTicks + 1;
if (NewQuietSubTicks > QuietSubTicks) { if (NewQuietSubTicks > QuietSubTicks) {
/* if not overflow */ /* if not overflow */
QuietSubTicks = NewQuietSubTicks; QuietSubTicks = NewQuietSubTicks;
}
} }
#endif #endif
m68k_go_nCycles_1(CyclesScaledPerSubTick); m68k_go_nCycles_1(CyclesScaledPerSubTick);
@ -619,85 +583,66 @@ LOCALPROC DoEmulateExtraTime(void)
} }
} }
/*
The number of ticks that have been emulated so far.
That is, the number of times "DoEmulateOneTick" has been called.
*/
LOCALVAR uint32_t CurEmulatedTime = 0; LOCALVAR uint32_t CurEmulatedTime = 0;
/*
The number of ticks that have been
emulated so far.
That is, the number of times /*
"DoEmulateOneTick" has been called. The general idea is to call DoEmulateOneTick once per tick.
*/
But if emulation is lagging, we'll try to catch up by calling
DoEmulateOneTick multiple times, unless we're too far behind, in
which case we forget it.
If emulating one tick takes longer than a tick we don't want to sit
here forever. So the maximum number of calls to DoEmulateOneTick is
determined at the beginning, rather than just calling DoEmulateOneTick
until CurEmulatedTime >= TrueEmulatedTime.
*/
LOCALPROC RunEmulatedTicksToTrueTime(void) LOCALPROC RunEmulatedTicksToTrueTime(void)
{ {
/* int8_t lag = OnTrueTime - CurEmulatedTime;
The general idea is to call DoEmulateOneTick
once per tick.
But if emulation is lagging, we'll try to if (lag > 0) {
catch up by calling DoEmulateOneTick multiple
times, unless we're too far behind, in
which case we forget it.
If emulating one tick takes longer than
a tick we don't want to sit here
forever. So the maximum number of calls
to DoEmulateOneTick is determined at
the beginning, rather than just
calling DoEmulateOneTick until
CurEmulatedTime >= TrueEmulatedTime.
*/
int8_t n = OnTrueTime - CurEmulatedTime;
if (n > 0) {
DoEmulateOneTick(); DoEmulateOneTick();
++CurEmulatedTime; CurEmulatedTime += 1;
DoneWithDrawingForTick(); DoneWithDrawingForTick();
if (n > 8) { if (lag > 8) {
/* emulation not fast enough */ /* emulation not fast enough */
n = 8; lag = 8;
CurEmulatedTime = OnTrueTime - n; CurEmulatedTime = OnTrueTime - lag;
} else {
lag -= 1;
} }
if (ExtraTimeNotOver() && (--n > 0)) { while (ExtraTimeNotOver() && (lag > 0)) {
/* lagging, catch up */ /* Missed vblank due to lag; catch up */
EmVideoDisable = true; EmVideoDisable = true;
DoEmulateOneTick();
do { CurEmulatedTime += 1;
DoEmulateOneTick(); lag -= 1;
++CurEmulatedTime;
} while (ExtraTimeNotOver()
&& (--n > 0));
EmVideoDisable = false; EmVideoDisable = false;
} }
EmLagTime = n; EmLagTime = lag;
} }
} }
LOCALPROC MainEventLoop(void) LOCALPROC MainEventLoop(void)
{ {
for (; ; ) { while (true) {
WaitForNextTick(); WaitForNextTick();
if (ForceMacOff) { if (ForceMacOff) { return; }
return;
}
RunEmulatedTicksToTrueTime(); RunEmulatedTicksToTrueTime();
DoEmulateExtraTime(); DoEmulateExtraTime();
} }
} }
GLOBALPROC ProgramMain(void) GLOBALPROC ProgramMain(void)
{ {
if (InitEmulation()) if (InitEmulation() == false) {return;}
{ MainEventLoop();
MainEventLoop();
}
} }