- Enable experimental sound support (only PC speaker for the moment, aka. uses beep.sys).
- Introduce a #define WORKING_TIMER which aim is to disable the currently problematic approximate performance counter value calculation done in order not to call QueryPerformanceCounter each time.
  The problem is that we then compute a number of clock ticks for the PIT, which becomes negative, and therefore everything starts to hang.
  Disabling this code and calling each time QueryPerformanceCounter, fixes everything; we gain in precision but we loose in performance...
  A definitive fix must be found, [TheFlash] !!

This fixes sound (and hangs) in Advanced NetWars, Dangerous Dave, ElitePlus and Rescue Rover (the games that I've tested so far).

svn path=/branches/ntvdm/; revision=61875
This commit is contained in:
Hermès Bélusca-Maïto 2014-01-29 00:25:43 +00:00
parent f2a98176d6
commit d25d9ea618
4 changed files with 30 additions and 6 deletions

View file

@ -134,6 +134,7 @@ static BYTE WINAPI Port61hRead(ULONG Port)
static VOID WINAPI Port61hWrite(ULONG Port, BYTE Data) static VOID WINAPI Port61hWrite(ULONG Port, BYTE Data)
{ {
// BOOLEAN SpeakerChange = FALSE;
BYTE OldPort61hState = Port61hState; BYTE OldPort61hState = Port61hState;
/* Only the four lowest bytes can be written */ /* Only the four lowest bytes can be written */
@ -141,7 +142,8 @@ static VOID WINAPI Port61hWrite(ULONG Port, BYTE Data)
if ((OldPort61hState ^ Port61hState) & 0x01) if ((OldPort61hState ^ Port61hState) & 0x01)
{ {
DPRINT1("PIT 2 Gate %s\n", Port61hState & 0x01 ? "on" : "off"); DPRINT("PIT 2 Gate %s\n", Port61hState & 0x01 ? "on" : "off");
// SpeakerChange = TRUE;
} }
PitSetGate(2, !!(Port61hState & 0x01)); PitSetGate(2, !!(Port61hState & 0x01));
@ -149,8 +151,11 @@ static VOID WINAPI Port61hWrite(ULONG Port, BYTE Data)
if ((OldPort61hState ^ Port61hState) & 0x02) if ((OldPort61hState ^ Port61hState) & 0x02)
{ {
/* There were some change for the speaker... */ /* There were some change for the speaker... */
DPRINT1("Speaker %s\n", Port61hState & 0x02 ? "on" : "off"); DPRINT("Speaker %s\n", Port61hState & 0x02 ? "on" : "off");
// SpeakerChange = TRUE;
} }
// if (SpeakerChange) SpeakerChange();
SpeakerChange();
} }
static VOID WINAPI PitChan0Out(LPVOID Param, BOOLEAN State) static VOID WINAPI PitChan0Out(LPVOID Param, BOOLEAN State)
@ -183,6 +188,8 @@ static VOID WINAPI PitChan1Out(LPVOID Param, BOOLEAN State)
static VOID WINAPI PitChan2Out(LPVOID Param, BOOLEAN State) static VOID WINAPI PitChan2Out(LPVOID Param, BOOLEAN State)
{ {
// BYTE OldPort61hState = Port61hState;
#if 0 #if 0
if (State) if (State)
{ {
@ -197,6 +204,9 @@ static VOID WINAPI PitChan2Out(LPVOID Param, BOOLEAN State)
#else #else
Port61hState = (Port61hState & 0xDF) | (State << 5); Port61hState = (Port61hState & 0xDF) | (State << 5);
#endif #endif
DPRINT("Speaker PIT out\n");
// if ((OldPort61hState ^ Port61hState) & 0x20)
// SpeakerChange();
} }
/* PUBLIC FUNCTIONS ***********************************************************/ /* PUBLIC FUNCTIONS ***********************************************************/

View file

@ -31,7 +31,7 @@ static HANDLE hBeep = NULL;
/* PUBLIC FUNCTIONS ***********************************************************/ /* PUBLIC FUNCTIONS ***********************************************************/
VOID SpeakerPool(VOID) VOID SpeakerChange(VOID)
{ {
BYTE Port61hState = IOReadB(CONTROL_SYSTEM_PORT61H); BYTE Port61hState = IOReadB(CONTROL_SYSTEM_PORT61H);
BOOLEAN IsConnectedToPITChannel2 = !!(Port61hState & 0x01); BOOLEAN IsConnectedToPITChannel2 = !!(Port61hState & 0x01);

View file

@ -17,7 +17,7 @@
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
VOID SpeakerPool(VOID); VOID SpeakerChange(VOID);
VOID SpeakerInitialize(VOID); VOID SpeakerInitialize(VOID);
VOID SpeakerCleanup(VOID); VOID SpeakerCleanup(VOID);

View file

@ -26,7 +26,17 @@
*/ */
#define TESTING #define TESTING
#define IPS_DISPLAY /*
* Activate IPS_DISPLAY if you want to display the
* number of instructions per second, as well as
* the computed number of ticks for the PIT.
*/
// #define IPS_DISPLAY
/*
* Activate WORKING_TIMER when the PIT timing problem is fixed.
*/
// #define WORKING_TIMER
/* PUBLIC VARIABLES ***********************************************************/ /* PUBLIC VARIABLES ***********************************************************/
@ -257,12 +267,15 @@ INT wmain(INT argc, WCHAR *argv[])
/* Main loop */ /* Main loop */
while (VdmRunning) while (VdmRunning)
{ {
#ifdef WORKING_TIMER
DWORD PitResolution = PitGetResolution(); DWORD PitResolution = PitGetResolution();
#endif
DWORD RtcFrequency = RtcGetTicksPerSecond(); DWORD RtcFrequency = RtcGetTicksPerSecond();
/* Get the current number of ticks */ /* Get the current number of ticks */
CurrentTickCount = GetTickCount(); CurrentTickCount = GetTickCount();
#ifdef WORKING_TIMER
if ((PitResolution <= 1000) && (RtcFrequency <= 1000)) if ((PitResolution <= 1000) && (RtcFrequency <= 1000))
{ {
/* Calculate the approximate performance counter value instead */ /* Calculate the approximate performance counter value instead */
@ -271,6 +284,7 @@ INT wmain(INT argc, WCHAR *argv[])
* (Frequency.QuadPart / 1000); * (Frequency.QuadPart / 1000);
} }
else else
#endif
{ {
/* Get the current performance counter value */ /* Get the current performance counter value */
QueryPerformanceCounter(&Counter); QueryPerformanceCounter(&Counter);
@ -331,7 +345,7 @@ INT wmain(INT argc, WCHAR *argv[])
#ifdef IPS_DISPLAY #ifdef IPS_DISPLAY
if ((CurrentTickCount - LastCyclePrintout) >= 1000) if ((CurrentTickCount - LastCyclePrintout) >= 1000)
{ {
DPRINT1("NTVDM: %lu Instructions Per Second; TimerTicks = %lu\n", Cycles, TimerTicks); DPRINT1("NTVDM: %lu Instructions Per Second; TimerTicks = %I64d\n", Cycles, TimerTicks);
LastCyclePrintout = CurrentTickCount; LastCyclePrintout = CurrentTickCount;
Cycles = 0; Cycles = 0;
} }