[NTVDM]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Wed, 29 Jan 2014 00:25:43 +0000 (00:25 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Wed, 29 Jan 2014 00:25:43 +0000 (00:25 +0000)
- 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

subsystems/ntvdm/emulator.c
subsystems/ntvdm/hardware/speaker.c
subsystems/ntvdm/hardware/speaker.h
subsystems/ntvdm/ntvdm.c

index bc3f101..4e8f9e8 100644 (file)
@@ -134,6 +134,7 @@ static BYTE WINAPI Port61hRead(ULONG Port)
 
 static VOID WINAPI Port61hWrite(ULONG Port, BYTE Data)
 {
+    // BOOLEAN SpeakerChange = FALSE;
     BYTE OldPort61hState = Port61hState;
 
     /* Only the four lowest bytes can be written */
@@ -141,7 +142,8 @@ static VOID WINAPI Port61hWrite(ULONG Port, BYTE Data)
 
     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));
@@ -149,8 +151,11 @@ static VOID WINAPI Port61hWrite(ULONG Port, BYTE Data)
     if ((OldPort61hState ^ Port61hState) & 0x02)
     {
         /* 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)
@@ -183,6 +188,8 @@ static VOID WINAPI PitChan1Out(LPVOID Param, BOOLEAN State)
 
 static VOID WINAPI PitChan2Out(LPVOID Param, BOOLEAN State)
 {
+    // BYTE OldPort61hState = Port61hState;
+
 #if 0
     if (State)
     {
@@ -197,6 +204,9 @@ static VOID WINAPI PitChan2Out(LPVOID Param, BOOLEAN State)
 #else
     Port61hState = (Port61hState & 0xDF) | (State << 5);
 #endif
+    DPRINT("Speaker PIT out\n");
+    // if ((OldPort61hState ^ Port61hState) & 0x20)
+        // SpeakerChange();
 }
 
 /* PUBLIC FUNCTIONS ***********************************************************/
index 26af44d..03bf25c 100644 (file)
@@ -31,7 +31,7 @@ static HANDLE hBeep = NULL;
 
 /* PUBLIC FUNCTIONS ***********************************************************/
 
-VOID SpeakerPool(VOID)
+VOID SpeakerChange(VOID)
 {
     BYTE    Port61hState = IOReadB(CONTROL_SYSTEM_PORT61H);
     BOOLEAN IsConnectedToPITChannel2 = !!(Port61hState & 0x01);
index 207b501..94c9fc0 100644 (file)
@@ -17,7 +17,7 @@
 
 /* FUNCTIONS ******************************************************************/
 
-VOID SpeakerPool(VOID);
+VOID SpeakerChange(VOID);
 
 VOID SpeakerInitialize(VOID);
 VOID SpeakerCleanup(VOID);
index 004c42e..91bccf7 100644 (file)
  */
 #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 ***********************************************************/
 
@@ -257,12 +267,15 @@ INT wmain(INT argc, WCHAR *argv[])
     /* Main loop */
     while (VdmRunning)
     {
+#ifdef WORKING_TIMER
         DWORD PitResolution = PitGetResolution();
+#endif
         DWORD RtcFrequency = RtcGetTicksPerSecond();
 
         /* Get the current number of ticks */
         CurrentTickCount = GetTickCount();
 
+#ifdef WORKING_TIMER
         if ((PitResolution <= 1000) && (RtcFrequency <= 1000))
         {
             /* Calculate the approximate performance counter value instead */
@@ -271,6 +284,7 @@ INT wmain(INT argc, WCHAR *argv[])
                                * (Frequency.QuadPart / 1000);
         }
         else
+#endif
         {
             /* Get the current performance counter value */
             QueryPerformanceCounter(&Counter);
@@ -331,7 +345,7 @@ INT wmain(INT argc, WCHAR *argv[])
 #ifdef IPS_DISPLAY
         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;
             Cycles = 0;
         }