2024-03-19 22:24:30 +01:00
|
|
|
/*
|
|
|
|
* engine.c
|
|
|
|
*
|
|
|
|
* This file is part of Emu48
|
|
|
|
*
|
|
|
|
* Copyright (C) 1995 Sebastien Carlier
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
#include "pch.h"
|
|
|
|
#include "Emu48.h"
|
2024-03-19 22:25:45 +01:00
|
|
|
#include "Opcodes.h"
|
|
|
|
#include "io.h" // 24.10.99 cg, renamed from Serial.h
|
|
|
|
#include "debugger.h"
|
2024-03-19 22:24:30 +01:00
|
|
|
|
2024-03-19 22:25:45 +01:00
|
|
|
#define SAMPLE 16384 // speed adjust sample frequency
|
2024-03-19 22:24:30 +01:00
|
|
|
|
2024-03-19 22:25:45 +01:00
|
|
|
BOOL bInterrupt = FALSE;
|
|
|
|
UINT nState = 1;
|
|
|
|
UINT nNextState = 0;
|
|
|
|
BOOL bRealSpeed = FALSE; // 11.12.99 cg, moved from Emu48.c
|
|
|
|
BOOL bKeySlow = FALSE; // slow down for key emulation
|
|
|
|
CHIPSET Chipset;
|
2024-03-19 22:24:30 +01:00
|
|
|
|
2024-03-19 22:25:45 +01:00
|
|
|
char szSerialWire[16]; // evicename for wire port
|
|
|
|
char szSerialIr[16]; // devicename for IR port
|
2024-03-19 22:24:30 +01:00
|
|
|
|
2024-03-19 22:25:45 +01:00
|
|
|
DWORD dwSXCycles = 82; // SX cpu cycles in interval
|
|
|
|
DWORD dwGXCycles = 123; // GX cpu cycles in interval
|
2024-03-19 22:24:30 +01:00
|
|
|
|
2024-03-19 22:25:45 +01:00
|
|
|
static BOOL bCommInit = FALSE; // COM port not open
|
|
|
|
static BOOL bCpuSlow = FALSE; // 11.12.99 cg, renamed, enable/disable real speed
|
2024-03-19 22:24:30 +01:00
|
|
|
|
2024-03-19 22:25:45 +01:00
|
|
|
static DWORD dwOldCyc; // cpu cycles at last event
|
|
|
|
static DWORD dwSpeedRef; // timer value at last event
|
|
|
|
static DWORD dwTickRef; // sample timer ticks
|
2024-03-19 22:24:30 +01:00
|
|
|
|
|
|
|
#include "Ops.h"
|
|
|
|
|
2024-03-19 22:25:45 +01:00
|
|
|
static __inline VOID CheckDisp(BOOL bSync)
|
|
|
|
{
|
|
|
|
if (disp == 0) return; // no display update need
|
2024-03-19 22:24:30 +01:00
|
|
|
|
2024-03-19 22:25:45 +01:00
|
|
|
// update display when drawing top line or display is off
|
|
|
|
if (bSync && GetLineCounter() != 0x3F && (Chipset.IORam[0x00]&8))
|
|
|
|
return;
|
2024-03-19 22:24:30 +01:00
|
|
|
|
2024-03-19 22:25:45 +01:00
|
|
|
_ASSERT((disp & DISP_POINTER) == 0); // display pointer already updated
|
|
|
|
if (disp & DISP_MAIN) UpdateMainDisplay();
|
|
|
|
if (disp & DISP_MENUE) UpdateMenuDisplay();
|
|
|
|
_ASSERT((disp & DISP_ANNUN) == 0); // annunciators already updated
|
|
|
|
disp = 0; // display updated
|
|
|
|
return;
|
|
|
|
}
|
2024-03-19 22:24:30 +01:00
|
|
|
|
2024-03-19 22:25:45 +01:00
|
|
|
static __inline VOID CheckSerial(VOID)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
if (ioc_acc) // IOC changed
|
|
|
|
{
|
|
|
|
ioc_acc = FALSE;
|
|
|
|
|
|
|
|
// COM port closed and serial on
|
2024-03-19 22:25:45 +01:00
|
|
|
if (bCommInit == FALSE && (Chipset.IORam[IOC] & SON) != 0)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
CommOpen(szSerialWire,szSerialIr); // open COM ports
|
|
|
|
bCommInit = CommConnect() != PORT_CLOSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// COM port opend and serial off
|
2024-03-19 22:25:45 +01:00
|
|
|
if (bCommInit == TRUE && (Chipset.IORam[IOC] & SON) == 0)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
CommClose(); // close COM port
|
|
|
|
bCommInit = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Interrupt on recv buffer full and receive buffer full
|
2024-03-19 22:25:45 +01:00
|
|
|
if ((Chipset.IORam[IOC] & ERBF) && (Chipset.IORam[RCS] & RBF))
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
Chipset.Shutdn = FALSE;
|
|
|
|
INTERRUPT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-19 22:25:45 +01:00
|
|
|
static __inline VOID AdjustSpeed(VOID) // adjust emulation speed
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
2024-03-19 22:25:45 +01:00
|
|
|
if (bCpuSlow || bKeySlow) // 11.12.99 cg, changed, emulation slow down
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
// cycles elapsed for next check
|
2024-03-19 22:25:45 +01:00
|
|
|
// 22.11.99 cg, changed, DWORD casting of Chipset.cycles
|
|
|
|
if ((DWORD) (Chipset.cycles & 0xFFFFFFFF)-dwOldCyc >= (DWORD) T2CYCLES)
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
LARGE_INTEGER lAct;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
BOOL bErr = QueryPerformanceCounter(&lAct);
|
|
|
|
_ASSERT(bErr); // no high-resolution performance counter
|
|
|
|
}
|
|
|
|
while(lAct.LowPart-dwSpeedRef <= dwTickRef);
|
|
|
|
|
|
|
|
dwOldCyc += T2CYCLES; // adjust cycles reference
|
|
|
|
dwSpeedRef += dwTickRef; // adjust reference time
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-03-19 22:25:45 +01:00
|
|
|
VOID AdjKeySpeed(VOID) // slow down key repeat
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
WORD i;
|
|
|
|
BOOL bKey;
|
|
|
|
|
2024-03-19 22:25:45 +01:00
|
|
|
if (bCpuSlow) return; // 11.12.99 cg, changed, no need to slow down
|
2024-03-19 22:24:30 +01:00
|
|
|
|
|
|
|
bKey = FALSE; // search for a pressed key
|
|
|
|
for (i = 0;i < sizeof(Chipset.Keyboard_Row) / sizeof(Chipset.Keyboard_Row[0]) && !bKey;++i)
|
|
|
|
bKey = (Chipset.Keyboard_Row[i] != 0);
|
|
|
|
|
|
|
|
if (!bKeySlow && bKey) // key pressed, init variables
|
|
|
|
{
|
|
|
|
LARGE_INTEGER lTime; // sample timer ticks
|
2024-03-19 22:25:45 +01:00
|
|
|
// save reference cycles
|
|
|
|
// 22.11.99 cg, changed, DWORD casting
|
|
|
|
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
2024-03-19 22:24:30 +01:00
|
|
|
QueryPerformanceCounter(&lTime); // get timer ticks
|
|
|
|
dwSpeedRef = lTime.LowPart; // save reference time
|
|
|
|
}
|
|
|
|
bKeySlow = bKey; // save new state
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-03-19 22:25:45 +01:00
|
|
|
VOID SetSpeed(BOOL bAdjust) // set emulation speed
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
2024-03-19 22:25:45 +01:00
|
|
|
if (bAdjust) // switch to real speed
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
LARGE_INTEGER lTime; // sample timer ticks
|
2024-03-19 22:25:45 +01:00
|
|
|
// save reference cycles
|
|
|
|
// 22.11.99 cg, changed, DWORD casting
|
|
|
|
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
2024-03-19 22:24:30 +01:00
|
|
|
QueryPerformanceCounter(&lTime); // get timer ticks
|
|
|
|
dwSpeedRef = lTime.LowPart; // save reference time
|
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
bCpuSlow = bAdjust; // 11.12.99 cg, changed, save emulation speed
|
2024-03-19 22:24:30 +01:00
|
|
|
}
|
|
|
|
|
2024-03-19 22:25:45 +01:00
|
|
|
VOID UpdateKdnBit(VOID) // update KDN bit
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
2024-03-19 22:25:45 +01:00
|
|
|
// 22.11.99 cg, changed, DWORD casting of Chipset.cycles
|
|
|
|
if (Chipset.intk && (DWORD) (Chipset.cycles & 0xFFFFFFFFF) - Chipset.dwKdnCycles > (DWORD) T2CYCLES * 16)
|
2024-03-19 22:24:30 +01:00
|
|
|
IOBit(0x19,8,Chipset.in != 0);
|
|
|
|
}
|
|
|
|
|
2024-03-19 22:25:45 +01:00
|
|
|
BOOL WaitForSleepState(VOID) // wait for cpu SHUTDN then sleep state
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
|
|
|
DWORD dwRefTime = timeGetTime();
|
|
|
|
|
|
|
|
// wait for the SHUTDN command with 1.5 sec timeout
|
|
|
|
while (timeGetTime() - dwRefTime < 1500L && !Chipset.Shutdn)
|
|
|
|
Sleep(0);
|
|
|
|
|
|
|
|
if (Chipset.Shutdn) // not timeout, cpu is down
|
|
|
|
SwitchToState(3); // go to sleep state
|
|
|
|
|
|
|
|
return 3 != nNextState; // state not changed, emulator was busy
|
|
|
|
}
|
|
|
|
|
|
|
|
UINT SwitchToState(UINT nNewState)
|
|
|
|
{
|
|
|
|
UINT nOldState = nState;
|
|
|
|
|
|
|
|
if (nState == nNewState) return nOldState;
|
|
|
|
switch (nState)
|
|
|
|
{
|
|
|
|
case 0: // Run
|
2024-03-19 22:25:45 +01:00
|
|
|
if (hDlgDebug) // debugger running
|
|
|
|
{
|
|
|
|
DestroyWindow(hDlgDebug); // then close debugger to renter emulation
|
|
|
|
hDlgDebug = NULL;
|
|
|
|
}
|
2024-03-19 22:24:30 +01:00
|
|
|
switch (nNewState)
|
|
|
|
{
|
|
|
|
case 1: // -> Invalid
|
|
|
|
nNextState = 1;
|
|
|
|
if (Chipset.Shutdn)
|
2024-03-19 22:25:45 +01:00
|
|
|
SetEvent(hEventShutdn);
|
2024-03-19 22:24:30 +01:00
|
|
|
else
|
|
|
|
bInterrupt = TRUE;
|
|
|
|
while (nState!=nNextState) Sleep(0);
|
|
|
|
UpdateWindowStatus();
|
|
|
|
break;
|
|
|
|
case 2: // -> Return
|
|
|
|
nNextState = 1;
|
|
|
|
if (Chipset.Shutdn)
|
2024-03-19 22:25:45 +01:00
|
|
|
SetEvent(hEventShutdn);
|
2024-03-19 22:24:30 +01:00
|
|
|
else
|
|
|
|
bInterrupt = TRUE;
|
|
|
|
while (nState!=nNextState) Sleep(0);
|
|
|
|
nNextState = 2;
|
2024-03-19 22:25:45 +01:00
|
|
|
SetEvent(hEventShutdn);
|
2024-03-19 22:24:30 +01:00
|
|
|
while (nState!=nNextState) Sleep(0);
|
|
|
|
UpdateWindowStatus();
|
|
|
|
break;
|
|
|
|
case 3: // -> Sleep
|
|
|
|
nNextState = 3;
|
|
|
|
if (Chipset.Shutdn)
|
2024-03-19 22:25:45 +01:00
|
|
|
SetEvent(hEventShutdn);
|
2024-03-19 22:24:30 +01:00
|
|
|
else
|
|
|
|
bInterrupt = TRUE;
|
|
|
|
while (nState!=nNextState) Sleep(0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 1: // Invalid
|
|
|
|
switch (nNewState)
|
|
|
|
{
|
|
|
|
case 0: // -> Run
|
|
|
|
nNextState = 0;
|
|
|
|
bInterrupt = FALSE;
|
2024-03-19 22:25:45 +01:00
|
|
|
SetEvent(hEventShutdn);
|
2024-03-19 22:24:30 +01:00
|
|
|
while (nState!=nNextState) Sleep(0);
|
|
|
|
UpdateWindowStatus();
|
|
|
|
break;
|
|
|
|
case 2: // -> Return
|
|
|
|
nNextState = 2;
|
2024-03-19 22:25:45 +01:00
|
|
|
SetEvent(hEventShutdn);
|
2024-03-19 22:24:30 +01:00
|
|
|
while (nState!=nNextState) Sleep(0);
|
|
|
|
break;
|
|
|
|
case 3: // -> Sleep
|
|
|
|
nNextState = 3;
|
2024-03-19 22:25:45 +01:00
|
|
|
SetEvent(hEventShutdn);
|
2024-03-19 22:24:30 +01:00
|
|
|
while (nState!=nNextState) Sleep(0);
|
|
|
|
UpdateWindowStatus();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 3: // Sleep
|
|
|
|
switch (nNewState)
|
|
|
|
{
|
|
|
|
case 0: // -> Run
|
|
|
|
nNextState = 0;
|
|
|
|
if (Chipset.Shutdn) bInterrupt=TRUE;
|
2024-03-19 22:25:45 +01:00
|
|
|
SetEvent(hEventShutdn);
|
2024-03-19 22:24:30 +01:00
|
|
|
break;
|
|
|
|
case 1: // -> Invalid
|
|
|
|
nNextState = 1;
|
2024-03-19 22:25:45 +01:00
|
|
|
SetEvent(hEventShutdn);
|
2024-03-19 22:24:30 +01:00
|
|
|
while (nState!=nNextState) Sleep(0);
|
|
|
|
UpdateWindowStatus();
|
|
|
|
break;
|
|
|
|
case 2: // -> Return
|
|
|
|
nNextState = 1;
|
2024-03-19 22:25:45 +01:00
|
|
|
SetEvent(hEventShutdn);
|
2024-03-19 22:24:30 +01:00
|
|
|
while (nState!=nNextState) Sleep(0);
|
|
|
|
nNextState = 2;
|
2024-03-19 22:25:45 +01:00
|
|
|
SetEvent(hEventShutdn);
|
2024-03-19 22:24:30 +01:00
|
|
|
while (nState!=nNextState) Sleep(0);
|
|
|
|
UpdateWindowStatus();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return nOldState;
|
|
|
|
}
|
|
|
|
|
|
|
|
UINT WorkerThread(LPVOID pParam)
|
|
|
|
{
|
2024-03-19 22:25:45 +01:00
|
|
|
LARGE_INTEGER lDummyInt; // sample timer ticks
|
|
|
|
QueryPerformanceFrequency(&lDummyInt); // init timer ticks
|
|
|
|
lDummyInt.QuadPart /= SAMPLE; // calculate sample ticks
|
|
|
|
dwTickRef = lDummyInt.LowPart; // sample timer ticks
|
|
|
|
_ASSERT(dwTickRef); // tick resolution error
|
2024-03-19 22:24:30 +01:00
|
|
|
|
|
|
|
loop:
|
|
|
|
while (nNextState == 1) // go into invalid state
|
|
|
|
{
|
2024-03-19 22:25:45 +01:00
|
|
|
CommClose(); // close COM port
|
|
|
|
bCommInit = FALSE; // COM port not open
|
2024-03-19 22:24:30 +01:00
|
|
|
nState = 1; // in invalid state
|
2024-03-19 22:25:45 +01:00
|
|
|
WaitForSingleObject(hEventShutdn,INFINITE);
|
2024-03-19 22:24:30 +01:00
|
|
|
if (nNextState == 2) // go into return state
|
|
|
|
{
|
|
|
|
nState = 2; // in return state
|
|
|
|
return 0; // kill thread
|
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
ioc_acc = TRUE; // test if UART on
|
2024-03-19 22:24:30 +01:00
|
|
|
}
|
|
|
|
while (nNextState == 0)
|
|
|
|
{
|
|
|
|
if (nState!=0)
|
|
|
|
{
|
|
|
|
nState = 0;
|
2024-03-19 22:25:45 +01:00
|
|
|
// clear port2 status bits
|
|
|
|
Chipset.cards_status &= ~(PORT2_PRESENT | PORT2_WRITE);
|
|
|
|
if (pbyPort2 || Chipset.Port2) // card plugged in port2
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
2024-03-19 22:25:45 +01:00
|
|
|
Chipset.cards_status |= PORT2_PRESENT;
|
|
|
|
|
|
|
|
if (bPort2Writeable) // is card writeable
|
|
|
|
Chipset.cards_status |= PORT2_WRITE;
|
2024-03-19 22:24:30 +01:00
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
RomSwitch(Chipset.Bank_FF); // select HP49G ROM bank and update memory mapping
|
2024-03-19 22:24:30 +01:00
|
|
|
UpdateDisplayPointers();
|
|
|
|
UpdateMainDisplay();
|
|
|
|
UpdateMenuDisplay();
|
|
|
|
UpdateAnnunciators();
|
2024-03-19 22:25:45 +01:00
|
|
|
// init speed reference
|
|
|
|
// 22.11.99 cg, changed, DWORD casting
|
|
|
|
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
2024-03-19 22:24:30 +01:00
|
|
|
QueryPerformanceCounter(&lDummyInt);
|
|
|
|
dwSpeedRef = lDummyInt.LowPart;
|
2024-03-19 22:25:45 +01:00
|
|
|
SetHP48Time(); // update HP48 time & date
|
2024-03-19 22:24:30 +01:00
|
|
|
StartTimers();
|
|
|
|
}
|
|
|
|
PCHANGED;
|
|
|
|
while (!bInterrupt)
|
|
|
|
{
|
2024-03-19 22:25:45 +01:00
|
|
|
LPBYTE I = FASTPTR(Chipset.pc);
|
|
|
|
|
|
|
|
if (bDbgEnable) // debugger active
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
2024-03-19 22:25:45 +01:00
|
|
|
BOOL bStopEmulation;
|
|
|
|
|
|
|
|
// 13.11.99 cg, changed, check for step into
|
|
|
|
bStopEmulation = (nDbgState == DBG_STEPINTO);
|
|
|
|
|
|
|
|
// check for step over
|
|
|
|
bStopEmulation |= (nDbgState == DBG_STEPOVER) && dwDbgRstkp == Chipset.rstkp;
|
|
|
|
|
|
|
|
// 13.11.99 cg, new, check for step out, something was popped from hardware stack
|
|
|
|
if (nDbgState == DBG_STEPOUT && dwDbgRstkp == Chipset.rstkp)
|
|
|
|
{
|
|
|
|
_ASSERT(bStopEmulation == FALSE);
|
|
|
|
if ((bStopEmulation = (Chipset.pc == dwDbgRstk)) == FALSE)
|
|
|
|
{
|
|
|
|
// it was C=RSTK, check for next object popped from hardware stack
|
|
|
|
dwDbgRstkp = (Chipset.rstkp-1)&7;
|
|
|
|
dwDbgRstk = Chipset.rstk[dwDbgRstkp];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// 13.11.99 cg, end of step out implementation
|
|
|
|
|
|
|
|
// check for breakpoints
|
|
|
|
bStopEmulation |= CheckBreakpoint(Chipset.pc);
|
|
|
|
|
|
|
|
// NOP3, opcode #420 (GOC)
|
|
|
|
if (bDbgNOP3 && I[0] == 0x4 && I[1] == 0x2 && I[2] == 0x0)
|
|
|
|
bStopEmulation = TRUE;
|
|
|
|
|
|
|
|
if (bStopEmulation) // stop condition
|
|
|
|
{
|
|
|
|
StopTimers(); // hold timer values when emulator is stopped
|
|
|
|
|
|
|
|
OutputDebugString("Emulator stopped...\n");
|
|
|
|
NotifyDebugger(); // 10.11.99 cg, changed, update registers
|
|
|
|
WaitForSingleObject(hEventDebug,INFINITE);
|
|
|
|
OutputDebugString("Emulator running...\n");
|
|
|
|
|
|
|
|
|
|
|
|
// @todo add timer emulation
|
|
|
|
|
|
|
|
|
|
|
|
StartTimers(); // continue timers
|
|
|
|
|
|
|
|
Chipset.Shutdn = FALSE;
|
|
|
|
Chipset.bShutdnWake = FALSE;
|
|
|
|
|
|
|
|
// init slow down part
|
|
|
|
// 22.11.99 cg, changed, DWORD casting
|
|
|
|
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
|
|
|
QueryPerformanceCounter(&lDummyInt);
|
|
|
|
dwSpeedRef = lDummyInt.LowPart;
|
|
|
|
}
|
2024-03-19 22:24:30 +01:00
|
|
|
}
|
|
|
|
|
2024-03-19 22:25:45 +01:00
|
|
|
EvalOpcode(I);
|
|
|
|
|
|
|
|
CheckDisp(!Chipset.Shutdn); // check for display update
|
|
|
|
CheckSerial(); // serial support
|
|
|
|
AdjustSpeed(); // adjust emulation speed
|
2024-03-19 22:24:30 +01:00
|
|
|
}
|
2024-03-19 22:25:45 +01:00
|
|
|
bInterrupt = FALSE; // be sure to reenter opcode loop
|
|
|
|
|
|
|
|
// enter SHUTDN handler only in RUN mode
|
|
|
|
if (Chipset.Shutdn && !(nDbgState == DBG_STEPINTO || nDbgState == DBG_STEPOVER))
|
2024-03-19 22:24:30 +01:00
|
|
|
{
|
2024-03-19 22:25:45 +01:00
|
|
|
WaitForSingleObject(hEventShutdn,INFINITE);
|
|
|
|
|
|
|
|
if (Chipset.bShutdnWake) // waked up by timer, keyboard or serial
|
|
|
|
{
|
|
|
|
Chipset.bShutdnWake = FALSE;
|
|
|
|
Chipset.Shutdn = FALSE;
|
|
|
|
// init speed reference
|
|
|
|
// 22.11.99 cg, changed, DWORD casting
|
|
|
|
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
|
|
|
QueryPerformanceCounter(&lDummyInt);
|
|
|
|
dwSpeedRef = lDummyInt.LowPart;
|
|
|
|
}
|
2024-03-19 22:24:30 +01:00
|
|
|
}
|
|
|
|
if (Chipset.SoftInt)
|
|
|
|
{
|
|
|
|
Chipset.SoftInt = FALSE;
|
|
|
|
if (Chipset.inte)
|
|
|
|
{
|
|
|
|
Chipset.inte = FALSE;
|
|
|
|
rstkpush(Chipset.pc);
|
|
|
|
Chipset.pc = 0xf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (nNextState != 0)
|
|
|
|
{
|
|
|
|
StopTimers();
|
|
|
|
Chipset.cards_status &= (Chipset.type=='S')?0x5:0xA;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (nNextState == 3) // go into sleep state
|
|
|
|
{
|
|
|
|
nState = 3; // in sleep state
|
2024-03-19 22:25:45 +01:00
|
|
|
WaitForSingleObject(hEventShutdn,INFINITE);
|
2024-03-19 22:24:30 +01:00
|
|
|
}
|
|
|
|
goto loop;
|
|
|
|
UNREFERENCED_PARAMETER(pParam);
|
|
|
|
}
|