Index: /trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
===================================================================
--- /trunk/src/VBox/Devices/Audio/DevIchAc97.cpp	(revision 73620)
+++ /trunk/src/VBox/Devices/Audio/DevIchAc97.cpp	(revision 73621)
@@ -324,4 +324,31 @@
 
 /**
+ * Structure containing AC'97 stream debug stuff, configurable at runtime.
+ */
+typedef struct AC97STREAMDBGINFORT
+{
+    /** Whether debugging is enabled or not. */
+    bool                     fEnabled;
+    uint8_t                  Padding[7];
+    /** File for dumping stream reads / writes.
+     *  For input streams, this dumps data being written to the device FIFO,
+     *  whereas for output streams this dumps data being read from the device FIFO. */
+    R3PTRTYPE(PPDMAUDIOFILE) pFileStream;
+    /** File for dumping DMA reads / writes.
+     *  For input streams, this dumps data being written to the device DMA,
+     *  whereas for output streams this dumps data being read from the device DMA. */
+    R3PTRTYPE(PPDMAUDIOFILE) pFileDMA;
+} AC97STREAMDBGINFORT, *PAC97STREAMDBGINFORT;
+
+/**
+ * Structure containing AC'97 stream debug information.
+ */
+typedef struct AC97STREAMDBGINFO
+{
+    /** Runtime debug info. */
+    AC97STREAMDBGINFORT      Runtime;
+} AC97STREAMDBGINFO ,*PAC97STREAMDBGINFO;
+
+/**
  * Structure for an AC'97 stream.
  */
@@ -329,10 +356,12 @@
 {
     /** Stream number (SDn). */
-    uint8_t         u8SD;
-    uint8_t         abPadding[7];
+    uint8_t           u8SD;
+    uint8_t           abPadding[7];
     /** Bus master registers of this stream. */
-    AC97BMREGS      Regs;
+    AC97BMREGS        Regs;
     /** Internal state of this stream. */
-    AC97STREAMSTATE State;
+    AC97STREAMSTATE   State;
+    /** Debug information. */
+    AC97STREAMDBGINFO Dbg;
 } AC97STREAM, *PAC97STREAM;
 AssertCompileSizeAlignment(AC97STREAM, 8);
@@ -399,4 +428,13 @@
     AC97DRIVERSTREAM                   Out;
 } AC97DRIVER, *PAC97DRIVER;
+
+typedef struct AC97STATEDBGINFO
+{
+    /** Whether debugging is enabled or not. */
+    bool                               fEnabled;
+    /** Path where to dump the debug output to.
+     *  Defaults to VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH. */
+    char                               szOutPath[RTPATH_MAX + 1];
+} AC97STATEDBGINFO, *PAC97STATEDBGINFO;
 
 /**
@@ -478,4 +516,5 @@
     /** The base interface for LUN\#0. */
     PDMIBASE                IBase;
+    AC97STATEDBGINFO        Dbg;
 } AC97STATE;
 AssertCompileMemberAlignment(AC97STATE, StreamLineIn, 8);
@@ -621,6 +660,7 @@
 static void               ichac97R3StreamAsyncIOEnable(PAC97STREAM pStream, bool fEnable);
 # endif
+
+DECLINLINE(PDMAUDIODIR)   ichac97GetDirFromSD(uint8_t uSD);
 #endif /* IN_RING3 */
-
 
 static void ichac97WarmReset(PAC97STATE pThis)
@@ -803,4 +843,20 @@
 
         rc = ichac97R3StreamOpen(pThis, pStream);
+        if (RT_SUCCESS(rc))
+        {
+            if (!DrvAudioHlpFileIsOpen(pStream->Dbg.Runtime.pFileStream))
+            {
+                int rc2 = DrvAudioHlpFileOpen(pStream->Dbg.Runtime.pFileStream, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS,
+                                              &pStream->State.Cfg.Props);
+                AssertRC(rc2);
+            }
+
+            if (!DrvAudioHlpFileIsOpen(pStream->Dbg.Runtime.pFileDMA))
+            {
+                int rc2 = DrvAudioHlpFileOpen(pStream->Dbg.Runtime.pFileDMA, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS,
+                                              &pStream->State.Cfg.Props);
+                AssertRC(rc2);
+            }
+        }
     }
     else
@@ -891,4 +947,39 @@
         rc = RTCircBufCreate(&pStream->State.pCircBuf, _4K); /** @todo Make this configurable. */
 
+    pStream->Dbg.Runtime.fEnabled = pThis->Dbg.fEnabled;
+
+    if (pStream->Dbg.Runtime.fEnabled)
+    {
+        char szFile[64];
+
+        if (ichac97GetDirFromSD(pStream->u8SD) == PDMAUDIODIR_IN)
+            RTStrPrintf(szFile, sizeof(szFile), "ac97StreamWriteSD%RU8", pStream->u8SD);
+        else
+            RTStrPrintf(szFile, sizeof(szFile), "ac97StreamReadSD%RU8", pStream->u8SD);
+
+        char szPath[RTPATH_MAX + 1];
+        int rc2 = DrvAudioHlpFileNameGet(szPath, sizeof(szPath), pThis->Dbg.szOutPath, szFile,
+                                         0 /* uInst */, PDMAUDIOFILETYPE_WAV, PDMAUDIOFILENAME_FLAG_NONE);
+        AssertRC(rc2);
+        rc2 = DrvAudioHlpFileCreate(PDMAUDIOFILETYPE_WAV, szPath, PDMAUDIOFILE_FLAG_NONE, &pStream->Dbg.Runtime.pFileStream);
+        AssertRC(rc2);
+
+        if (ichac97GetDirFromSD(pStream->u8SD) == PDMAUDIODIR_IN)
+            RTStrPrintf(szFile, sizeof(szFile), "ac97DMAWriteSD%RU8", pStream->u8SD);
+        else
+            RTStrPrintf(szFile, sizeof(szFile), "ac97DMAReadSD%RU8", pStream->u8SD);
+
+        rc2 = DrvAudioHlpFileNameGet(szPath, sizeof(szPath), pThis->Dbg.szOutPath, szFile,
+                                     0 /* uInst */, PDMAUDIOFILETYPE_WAV, PDMAUDIOFILENAME_FLAG_NONE);
+        AssertRC(rc2);
+
+        rc2 = DrvAudioHlpFileCreate(PDMAUDIOFILETYPE_WAV, szPath, PDMAUDIOFILE_FLAG_NONE, &pStream->Dbg.Runtime.pFileDMA);
+        AssertRC(rc2);
+
+        /* Delete stale debugging files from a former run. */
+        DrvAudioHlpFileDelete(pStream->Dbg.Runtime.pFileStream);
+        DrvAudioHlpFileDelete(pStream->Dbg.Runtime.pFileDMA);
+    }
+
     return rc;
 }
@@ -921,4 +1012,13 @@
 # endif
 
+    if (pStream->Dbg.Runtime.fEnabled)
+    {
+        DrvAudioHlpFileDestroy(pStream->Dbg.Runtime.pFileStream);
+        pStream->Dbg.Runtime.pFileStream = NULL;
+
+        DrvAudioHlpFileDestroy(pStream->Dbg.Runtime.pFileDMA);
+        pStream->Dbg.Runtime.pFileDMA = NULL;
+    }
+
     LogFlowFuncLeave();
 }
@@ -1008,11 +1108,6 @@
         AssertRC(rc2);
 
-# ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
-        RTFILE fh;
-        RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "ichac97StreamWrite.pcm",
-                   RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
-        RTFileWrite(fh, pvDst, cbRead, NULL);
-        RTFileClose(fh);
-# endif
+        if (pDstStream->Dbg.Runtime.fEnabled)
+            DrvAudioHlpFileWrite(pDstStream->Dbg.Runtime.pFileStream, pvDst, cbRead, 0 /* fFlags */);
     }
 
@@ -1062,11 +1157,7 @@
         if (cbSrc)
         {
-# ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
-            RTFILE fh;
-            RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "ac97StreamRead.pcm",
-                       RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
-            RTFileWrite(fh, pvSrc, cbSrc, NULL);
-            RTFileClose(fh);
-# endif
+            if (pSrcStream->Dbg.Runtime.fEnabled)
+                DrvAudioHlpFileWrite(pSrcStream->Dbg.Runtime.pFileStream, pvSrc, cbSrc, 0 /* fFlags */);
+
             rc = AudioMixerSinkWrite(pDstMixSink, AUDMIXOP_COPY, pvSrc, (uint32_t)cbSrc, &cbWritten);
             if (RT_SUCCESS(rc))
@@ -2022,4 +2113,21 @@
 }
 
+/**
+ * Returns the audio direction of a specified stream descriptor.
+ *
+ * @return  Audio direction.
+ */
+DECLINLINE(PDMAUDIODIR) ichac97GetDirFromSD(uint8_t uSD)
+{
+    switch (uSD)
+    {
+        case AC97SOUNDSOURCE_PI_INDEX: return PDMAUDIODIR_IN;
+        case AC97SOUNDSOURCE_PO_INDEX: return PDMAUDIODIR_OUT;
+        case AC97SOUNDSOURCE_MC_INDEX: return PDMAUDIODIR_IN;
+    }
+
+    return PDMAUDIODIR_UNKNOWN;
+}
+
 #endif /* IN_RING3 */
 
@@ -2471,11 +2579,6 @@
                     AssertRC(rc2);
 
-# ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
-                    RTFILE fh;
-                    RTFileOpen(&fh,  VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "ac97DMARead.pcm",
-                               RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
-                    RTFileWrite(fh, pvDst, cbDst, NULL);
-                    RTFileClose(fh);
-# endif
+                    if (pStream->Dbg.Runtime.fEnabled)
+                        DrvAudioHlpFileWrite(pStream->Dbg.Runtime.pFileDMA, pvDst, cbDst, 0 /* fFlags */);
                 }
 
@@ -2501,11 +2604,6 @@
                     AssertRC(rc2);
 
-# ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
-                    RTFILE fh;
-                    RTFileOpen(&fh,  VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "ac97DMAWrite.pcm",
-                               RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
-                    RTFileWrite(fh, pvSrc, cbSrc, NULL);
-                    RTFileClose(fh);
-# endif
+                    if (pStream->Dbg.Runtime.fEnabled)
+                        DrvAudioHlpFileWrite(pStream->Dbg.Runtime.pFileDMA, pvSrc, cbSrc, 0 /* fFlags */);
                 }
 
@@ -3813,8 +3911,9 @@
      * Validations.
      */
-    if (!CFGMR3AreValuesValid(pCfg,
-                              "RZEnabled\0"
-                              "Codec\0"
-                              "TimerHz\0"))
+    if (!CFGMR3AreValuesValid(pCfg, "RZEnabled\0"
+                                    "Codec\0"
+                                    "TimerHz\0"
+                                    "DebugEnabled\0"
+                                    "DebugPathOut\0"))
         return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
                                 N_("Invalid configuration for the AC'97 device"));
@@ -3826,5 +3925,5 @@
     if (RT_FAILURE(rc))
         return PDMDEV_SET_ERROR(pDevIns, rc,
-                                N_("HDA configuration error: failed to read RCEnabled as boolean"));
+                                N_("AC'97 configuration error: failed to read RCEnabled as boolean"));
 
     char szCodec[20];
@@ -3840,5 +3939,25 @@
         return PDMDEV_SET_ERROR(pDevIns, rc,
                                 N_("AC'97 configuration error: failed to read Hertz (Hz) rate as unsigned integer"));
+
+    if (uTimerHz != AC97_TIMER_HZ)
+        LogRel(("AC97: Using custom device timer rate (%RU16Hz)\n", uTimerHz));
 # endif
+
+    rc = CFGMR3QueryBoolDef(pCfg, "DebugEnabled", &pThis->Dbg.fEnabled, false);
+    if (RT_FAILURE(rc))
+        return PDMDEV_SET_ERROR(pDevIns, rc,
+                                N_("AC97 configuration error: failed to read debugging enabled flag as boolean"));
+
+    rc = CFGMR3QueryStringDef(pCfg, "DebugPathOut", pThis->Dbg.szOutPath, sizeof(pThis->Dbg.szOutPath),
+                              VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH);
+    if (RT_FAILURE(rc))
+        return PDMDEV_SET_ERROR(pDevIns, rc,
+                                N_("AC97 configuration error: failed to read debugging output path flag as string"));
+
+    if (!strlen(pThis->Dbg.szOutPath))
+        RTStrPrintf(pThis->Dbg.szOutPath, sizeof(pThis->Dbg.szOutPath), VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH);
+
+    if (pThis->Dbg.fEnabled)
+        LogRel2(("AC97: Debug output will be saved to '%s'\n", pThis->Dbg.szOutPath));
 
     /*
@@ -4151,11 +4270,4 @@
         PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesWritten, STAMTYPE_COUNTER, "/Devices/AC97/BytesWritten", STAMUNIT_BYTES,          "Bytes written to AC97 emulation.");
     }
-# endif
-
-# ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
-    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "ac97DMARead.pcm");
-    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "ac97DMAWrite.pcm");
-    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "ac97StreamRead.pcm");
-    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "ac97StreamWrite.pcm");
 # endif
 
Index: /trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp	(revision 73620)
+++ /trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp	(revision 73621)
@@ -2835,4 +2835,6 @@
                         default: AssertFailedBreak();
                     }
+                    InsertConfigInteger(pCfg, "DebugEnabled", fDebugEnabled);
+                    InsertConfigString (pCfg, "DebugPathOut", strDebugPathOut);
                     break;
                 }
