Wine:音が出ない件解決

再生できない音声はADPCM形式だった。つまりADPCMのドライバがMSACMに登録されていない事が原因。ドライバの登録をしているのは、dlls/msacm/internal.cのMSACM_RegisterAllDrivers()という関数。この関数内でmsadp32.acmを登録してやったら、これまで音関係で問題のあったゲームが動くようになった。

 --- dlls/msacm/internal.c       30 Jun 2004 18:11:39 -0000      1.19
 +++ dlls/msacm/internal.c       23 Aug 2004 21:43:30 -0000
 @@ -285,6 +285,8 @@
  {
      static const WCHAR msacm32 = {'m','s','a','c','m','3','2','.','d','l','l','\0'};
      static const WCHAR msacmW = {'M','S','A','C','M','.'};
 +    static const WCHAR msadp32 = {'m','s','a','d','p','3','2','.','a','c','m','\0'};
 +    static const WCHAR msadpW = {'m','s','a','c','m','.','m','s','a','d','p','c','m','\0'};
      static const WCHAR drv32 = {'d','r','i','v','e','r','s','3','2','\0'};
      static const WCHAR sys = {'s','y','s','t','e','m','.','i','n','i','\0'};
      static const WCHAR drvkey[] = {'S','o','f','t','w','a','r','e','\\',
 @@ -329,6 +331,7 @@
      }
 
      MSACM_RegisterDriver(msacm32, msacm32, 0);
 +    MSACM_RegisterDriver(msadpW, msadp32, 0);
  }
 
  /***********************************************************************

MSACM_RegisterAllDrivers()はレジストリ HKLM\Software\Microsoft\Windows NT\CurrentVersion\Drivers32 の下を読んでいるみたいだけど、こうした方が良いんじゃないかな?

 --- dlls/msacm/internal.c	30 Jun 2004 18:11:39 -0000	1.19
 +++ dlls/msacm/internal.c	23 Aug 2004 21:36:14 -0000
 @@ -294,7 +294,6 @@
  				   'D','r','i','v','e','r','s','3','2','\0'};
      DWORD i, cnt = 0, bufLen, lRet;
      WCHAR buf[2048], *name, *s;
 -    FILETIME lastWrite;
      HKEY hKey;
  
      /* FIXME: What if the user edits system.ini while the program is running?
 @@ -303,15 +302,17 @@
  
      lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, drvkey, 0, KEY_QUERY_VALUE, &hKey);
      if (lRet == ERROR_SUCCESS) {
 -	RegQueryInfoKeyW( hKey, 0, 0, 0, &cnt, 0, 0, 0, 0, 0, 0, 0);
 +	DWORD nameLen, type;
 +	WCHAR name[2048];
 +	lRet = RegQueryInfoKeyW( hKey, 0, 0, 0, 0, 0, 0, &cnt, 0, 0, 0, 0);
  	for (i = 0; i < cnt; i++) {
  	    bufLen = sizeof(buf) / sizeof(buf[0]);
 -	    lRet = RegEnumKeyExW(hKey, i, buf, &bufLen, 0, 0, 0, &lastWrite);
 +	    nameLen = sizeof(name) / sizeof(name[0]);
 +	    lRet = RegEnumValueW(hKey, i, name, &nameLen, 0, &type, (LPBYTE)buf, &bufLen);
  	    if (lRet != ERROR_SUCCESS) continue;
 -	    if (strncmpiW(buf, msacmW, sizeof(msacmW)/sizeof(msacmW[0]))) continue;
 -	    if (!(name = strchrW(buf, '='))) continue;
 -	    *name = 0;
 -	    MSACM_RegisterDriver(buf, name + 1, 0);
 +	    if (type != REG_SZ) continue;
 +	    if (strncmpiW(name, msacmW, sizeof(msacmW)/sizeof(msacmW[0]))) continue;
 +	    MSACM_RegisterDriver(name, buf, 0);
  	}
      	RegCloseKey( hKey );
      }

このパッチを当てると、~/.wine/system.regに以下のようなエントリを追加することで自動的にドライバが登録されるようになる(パッチを当てる前の動作は意味不明)。

[Software\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32]
"msacm.iac2"="C:\\WINNT\\system32\\iac25_32.ax"
"msacm.imaadpcm"="imaadp32.acm"
"msacm.l3acm"="C:\\WINNT\\system32\\l3codeca.acm"
"msacm.lhacm"="lhacm.acm"
"msacm.msadpcm"="msadp32.acm"
"msacm.msg711"="msg711.acm"
"msacm.msg723"="msg723.acm"
"msacm.msgsm610"="msgsm32.acm"
"msacm.trspch"="tssoft32.acm"

動いたゲーム

一気にTerraLunarの3タイトルが動作可能に。これで手持ちで動かないゲームは「沙耶の唄」「パルフェふぁんBOX」「痕リニューアル」それと認証で弾かれる「Fate/stay night」だけになった。
(TerraLunarのゲームは実はもう1本持ってるんだけど、黒歴史なので封印処分)