ここでは cdemuのインストールについて 注意点等を記載します
libdaemon と
libmirage については
ソースコードを展開して ./configure → make → make install (root権限で)
でインストールできました
vhba-module については
ソースコードを展開後 以下の手順でインストールします
$ make modules
$ su
# make module_install
ただし (Linuxの古いバージョン等) 以下のエラーが発生する場合
CC [M] 〜/vhba-module-1.0.0/vhba.o
〜/vhba-module-1.0.0/vhba.c:793:51: error: マクロ "INIT_WORK" は引数を 3 要求しますが、2 個しか与えられていません
INIT_WORKマクロの仕様が linuxカーネル側で修正になっているので vhba.c 793行目 を修正します
INIT_WORK(&vhost->scan_devices, vhba_scan_devices);
↓
INIT_WORK(&vhost->scan_devices, vhba_scan_devices, &vhost->scan_devices);
また 少なくとも kernel-2.6.24 以降では CFLAGSの設定でエラーが出るようです
make -C /lib/modules/`uname -r`/build M=/home/admin/vhba-module-1.0.0 modules
make[1]: Entering directory `/usr/src/linux-2.6.24'
scripts/Makefile.build:46: *** CFLAGS was changed in "/home/admin/vhba-module-1.0.0/Makefile". Fix it to use EXTRA_CFLAGS。中止。
make[1]: *** [_module_/home/admin/vhba-module-1.0.0] エラー 2
make[1]: Leaving directory `/usr/src/linux-2.6.24'
make: *** [modules] エラー 2
CFLAGS を EXTRA_CFLAGS に変えてくださいとのエラーのように見えます Makefile を以下のように修正します
2 PACKAGE = vhba-module-$(VHBA_VERSION)
3
4 CFLAGS += -DVHBA_VERSION=\"$(VHBA_VERSION)\"
5
6 obj-m += vhba.o
↓
2 PACKAGE = vhba-module-$(VHBA_VERSION)
3
4 EXTRA_CFLAGS += -DVHBA_VERSION=\"$(VHBA_VERSION)\"
5
6 obj-m += vhba.o
さらに以下のようなエラーが出る場合
make -C /lib/modules/`uname -r`/build M=/home/admin/vhba-module-1.0.0 modules
make[1]: Entering directory `/usr/src/linux-2.6.24'
CC [M] /home/admin/vhba-module-1.0.0/vhba.o
/home/admin/vhba-module-1.0.0/vhba.c: In function 'do_response':
/home/admin/vhba-module-1.0.0/vhba.c:523: error: 'struct scatterlist' has no member named 'page'
make[2]: *** [/home/admin/vhba-module-1.0.0/vhba.o] エラー 1
make[1]: *** [_module_/home/admin/vhba-module-1.0.0] エラー 2
make[1]: Leaving directory `/usr/src/linux-2.6.24'
make: *** [modules] エラー 2
少なくともカーネル 2.4.24以降の struct scatter_list のメンバ要素が仕様修正されてるようで vhba.c に以下の修正を加えました
522
523 kaddr = kmap_atomic(sg[i].page , KM_USER0);
524 memcpy(kaddr + sg[i].offset, kbuf, len);
525 kunmap_atomic(kaddr, KM_USER0);
526
↓
522
523 kaddr = kmap_atomic(sg[i].page_link , KM_USER0);
524 memcpy(kaddr + sg[i].offset, kbuf, len);
525 kunmap_atomic(kaddr, KM_USER0);
526
また udevのルール設定に追加が必要です 次のような 1行を追加しておきます
KERNEL=="vhba_ctl", NAME="%k", MODE="0660", OWNER="root", GROUP="users"
インストールがうまくいったら モジュールがロードできるようになります
# insmod /lib/modules/〜/extra/vhba.ko
# lsmod
Module Size Used by
vhba 7168 0
nvidia 6816276 22
vhba.ko は Linuxのシステム起動時に自動的に読み込まれるように設定しておくと便利です
次に cdemu-daemon 本体をインストールします ソースコードを展開後
$ ./configure --with-dbus-system-dir=/usr/local/etc/dbus-1/system.d
〜
cdemu-daemon 1.2.0 configure summary:
Prefix: /usr/local
dbus-1 system.d dir: /usr/local/etc/dbus-1/system.d
C Compiler: gcc -std=gnu99
CFLAGS: -g -O2
$ make
$ su
# make install
–with-dbus-system-dir の設定は環境によっては /etc/dbus-1/system.d かもしれません
インストールが完了すれば cdemud のコマンドが使えるようになっています
最後に cdemu-client をインストールします ソースコードを展開後
$ make
$ su
# make install
インストール後は cdemu コマンドが使えるようになります
利用方法
まず 前提が 2つあり
1つ目は VHBAのカーネルモジュールがロードされている必要があるということです
(lsmodで確認 なければ modprobe vhba コマンドでロード完了です)
2つ目は D-Busも正しく起動して常駐されている必要があるということです
(ps -axで確認 なければ root権限にて dbus-daemon –system で起動されるか試してください)
いよいよ本番ですが cdemud を常駐させます rootのコンソールを 1枚立ち上げて
# cdemud -a alsa
- num devices: 1
- ctl device: /dev/vhba_ctl
- audio driver: alsa
- bus type: system
とりあえず フロントエンドで常駐した状態になります
num_devices は cdemud に -n オプションを付けることで指定できる
バックエンドで常駐するには -d をつければよいはずですが 手元の環境では確認できませんでした
audio_backend は -a オプションで指定します libaoが適切に導入されている必要があります
cdemudが起動することで /dev/sr0 が 仮想CDデバイスとして見えるようになるはずです
以降は主に cdemu コマンドで CDイメージを操作することになります
まずは イメージのロードから
# cdemu load 0 ~/test.cue
#
上記コマンドでは test.cue のキューシートを指定して読み込む指定です
何事もエラーがでなければ OKです /dev/sr0 に CDイメージがセットされているはずです
仮想CDデバイスの利用状況は以下のように確認できます
# cdemu status
Devices status:
DEV LOADED TYPE FILENAME
0 1 PARSER-CUE /root/test.cue
では 実際にロードしたイメージが 通常のCDデバイスと同じく扱えるか確認してみます
# mount -t iso9660 -o ro /dev/sr0 /mnt/cdrom
# ls /mnt/cdrom
AUTORUN.INF Setup.exe congrats.avi layout.bin
Autorun.exe _INST32I.EX_ credits.avi lemmings.box
DATA.TAG _ISDel.exe data1.cab os.dat
DirectX7.0a _Setup.dll data1.hdr setup.bmp
Intel Indeo Readme.txt _sys1.cab delreg.exe setup.ins
Lemmings Revolution.exe _sys1.hdr failed.avi setup.lid
Patch.box _user1.cab frontend.avi splash256.bmp
SETUP.INI _user1.hdr gameover.avi
SavedGame.dat complete.avi lang.dat
Windows用のゲームの CD-ROMをマウントした結果 正しくファイルシステムが見えていることが分かります
イメージを利用し終えたら /dev/sr0 での利用を次のように解除します
# umount /mnt/cdrom
# cdemu unload 0
以上が CDemuの基本的な流れとなります
cdemu load と cdemu unload コマンドで LinuxにおいてもCDイメージが扱え非常に便利です
注意点としては cdemu load する時のイメージパスに日本語を含む場合は EUC-JP でなく UTF-8 で指定しないと受け付けてもらえず EUC-JPの環境では苦労することです
CDemuの問題について
検証環境にて CDemuを利用して遭遇した問題点について 解決できたのがあるので紹介します
問題点については以下のとおりです
CD-DAオーディオの問題 cdda-playerによる演奏がうまく鳴らない現象
データトラックへアクセスできない不具合 PC-EngineのCD-ROMなど特殊な構成で発生
まず CD-DAオーディオの問題ですが
下記のように cdda-player コマンドによる CD-DA演奏でどのトラックも音が鳴らず一瞬でトラック終了に達してしまいます
実際は 一瞬音が鳴るのですが すぐに停止状態になってしまいます
ちなみに cdda-playerは libcdioパッケージの付属ツールです コマンドラインからCD演奏できます
cdemu-daemonでは 実際の CDデバイスに対する ioctl()処理をエミュレートする機能がありますが
その動作を解析した結果 問題箇所と回避策を見つけました
cdda-playerでは 演奏開始直後に CDデバイスに対して MODE SENSEコマンドを発行していたのです
MODE SENSEとは CDドライブの能力情報をドライブから取得するコマンドです
cdemuにおいては 下記のソースコード(cdemu-device.c)で
2770 } packet_commands[] = {
2771 { PC_GET_EVENT_STATUS_NOTIFICATION,
2772 "GET EVENT/STATUS NOTIFICATION",
2773 __cdemud_device_pc_get_event_status_notification,
2774 FALSE },
2775 { PC_GET_CONFIGURATION,
2776 "GET CONFIGURATION",
2777 __cdemud_device_pc_get_configuration,
2778 TRUE, },
2779 { PC_INQUIRY,
2780 "INQUIRY",
2781 __cdemud_device_pc_inquiry,
2782 FALSE },
2783 { PC_MODE_SELECT_6,
2784 "MODE SELECT (6)",
2785 __cdemud_device_pc_mode_select,
2786 TRUE },
2787 { PC_MODE_SELECT_10,
2788 "MODE SELECT (10)",
2789 __cdemud_device_pc_mode_select,
2790 TRUE },
2791 { PC_MODE_SENSE_6,
2792 "MODE SENSE (6)",
2793 __cdemud_device_pc_mode_sense,
2794 TRUE },
2795 { PC_MODE_SENSE_10,
2796 "MODE SENSE (10)",
2797 __cdemud_device_pc_mode_sense,
2798 TRUE },
2799 { PC_PAUSE_RESUME,
2800 "PAUSE/RESUME",
2801 __cdemud_device_pc_pause_resume,
2802 FALSE /* Well, it does... but in it's own, unique way :P */ },
各コマンドの 処理方法を定義していますが
それぞれ TRUE FALSE とある部分が コマンドを処理するときに CD-DAを停止するかどうかのフラグで
MODE_SENSE においては TRUE つまり 停止となっています
2792 "MODE SENSE (6)",
2793 __cdemud_device_pc_mode_sense,
2794 FALSE },
2795 { PC_MODE_SENSE_10,
2796 "MODE SENSE (10)",
2797 __cdemud_device_pc_mode_sense,
2798 FALSE },
上記のように FALSEに設定することで cdda-playerが正常に演奏されるようになりました
(実際のデバイスの振舞いと一致しているかどうかは未確認です
また cdda-player以外の再生環境では問題はでないかもしれません)
ちなみに CDemuでは 音声ファイルを libsndfileに任せているので
sndfile-play コマンドで演奏できるフォーマットは CUEシートに入力できます
FILE "test1.ogg" WAVE
TRACK 1 AUDIO
INDEX 1 00:00:00
FILE "test2.ogg" WAVE
TRACK 2 AUDIO
INDEX 1 00:00:00
上記のようなCUEシートで Oggのような圧縮音声形式もCDイメージ化でき大変コンパクトに収まります
(残念ながら mp3 は sndfileで扱ってなかったので 検証環境でCDイメージ化は不可でした)
次に データトラックへのアクセスの問題です
現象としては Mednafen (マルチゲームエミュレータ) + 「アルナムの牙」 (PC-Engine CD-ROM2ゲーム)の CUEシートで全く動作しないという問題です
CUEシートは 以下のとおりです
FILE "track_01.wav" WAVE
TRACK 1 AUDIO
INDEX 1 00:00:00
FILE "track_02.bin" BINARY
TRACK 2 MODE1/2352
INDEX 1 00:00:00
FILE "track_03.wav" WAVE
TRACK 3 AUDIO
INDEX 1 00:00:00
FILE "track_04.wav" WAVE
TRACK 4 AUDIO
INDEX 1 00:00:00
FILE "track_05.wav" WAVE
TRACK 5 AUDIO
INDEX 1 00:00:00
FILE "track_06.wav" WAVE
TRACK 6 AUDIO
INDEX 1 00:00:00
FILE "track_07.wav" WAVE
TRACK 7 AUDIO
INDEX 1 00:00:00
FILE "track_08.wav" WAVE
TRACK 8 AUDIO
INDEX 1 00:00:00
FILE "track_09.wav" WAVE
TRACK 9 AUDIO
INDEX 1 00:00:00
FILE "track_10.wav" WAVE
TRACK 10 AUDIO
INDEX 1 00:00:00
FILE "track_11.wav" WAVE
TRACK 11 AUDIO
INDEX 1 00:00:00
FILE "track_12.wav" WAVE
TRACK 12 AUDIO
INDEX 1 00:00:00
FILE "track_13.wav" WAVE
TRACK 13 AUDIO
INDEX 1 00:00:00
FILE "track_14.wav" WAVE
TRACK 14 AUDIO
INDEX 1 00:00:00
FILE "track_15.wav" WAVE
TRACK 15 AUDIO
INDEX 1 00:00:00
FILE "track_16.wav" WAVE
TRACK 16 AUDIO
INDEX 1 00:00:00
FILE "track_17.wav" WAVE
TRACK 17 AUDIO
INDEX 1 00:00:00
FILE "track_18.wav" WAVE
TRACK 18 AUDIO
INDEX 1 00:00:00
FILE "track_19.wav" WAVE
TRACK 19 AUDIO
INDEX 1 00:00:00
FILE "track_20.wav" WAVE
TRACK 20 AUDIO
INDEX 1 00:00:00
FILE "track_21.wav" WAVE
TRACK 21 AUDIO
INDEX 1 00:00:00
FILE "track_22.wav" WAVE
TRACK 22 AUDIO
INDEX 1 00:00:00
FILE "track_23.wav" WAVE
TRACK 23 AUDIO
INDEX 1 00:00:00
FILE "track_24.wav" WAVE
TRACK 24 AUDIO
INDEX 1 00:00:00
FILE "track_25.wav" WAVE
TRACK 25 AUDIO
INDEX 1 00:00:00
FILE "track_26.wav" WAVE
TRACK 26 AUDIO
INDEX 1 00:00:00
FILE "track_27.wav" WAVE
TRACK 27 AUDIO
INDEX 1 00:00:00
FILE "track_28.wav" WAVE
TRACK 28 AUDIO
INDEX 1 00:00:00
FILE "track_29.wav" WAVE
TRACK 29 AUDIO
INDEX 1 00:00:00
FILE "track_30.wav" WAVE
TRACK 30 AUDIO
INDEX 1 00:00:00
FILE "track_31.wav" WAVE
TRACK 31 AUDIO
INDEX 1 00:00:00
FILE "track_32.wav" WAVE
TRACK 32 AUDIO
INDEX 1 00:00:00
FILE "track_33.wav" WAVE
TRACK 33 AUDIO
INDEX 1 00:00:00
FILE "track_34.wav" WAVE
TRACK 34 AUDIO
INDEX 1 00:00:00
FILE "track_35.wav" WAVE
TRACK 35 AUDIO
INDEX 1 00:00:00
FILE "track_36.wav" WAVE
TRACK 36 AUDIO
INDEX 1 00:00:00
FILE "track_37.wav" WAVE
TRACK 37 AUDIO
INDEX 1 00:00:00
FILE "track_38.wav" WAVE
TRACK 38 AUDIO
INDEX 1 00:00:00
FILE "track_39.wav" WAVE
TRACK 39 AUDIO
INDEX 1 00:00:00
FILE "track_40.wav" WAVE
TRACK 40 AUDIO
INDEX 1 00:00:00
FILE "track_41.wav" WAVE
TRACK 41 AUDIO
INDEX 1 00:00:00
FILE "track_42.wav" WAVE
TRACK 42 AUDIO
INDEX 1 00:00:00
PC-Engineの CDトラック構成は特殊で
1トラック目が音声(警告用) 2トラック目がデータ(プログラム) それ以降は 音声(CD-DA)
となっています ゲームによっては データトラックが最後に入ってくることもあります
Mednafenの起動時に固まってしまう問題で 問題のでないゲームもあり調査に時間がかかりました
結果 上記特殊トラック構成を扱う上での Linux(カーネル?)との相性問題にまで及んでいました
CUEシートのトラック構成は libmirageが扱っていますが 各トラックの開始セクタは次のようになっています
track01 start=-150 length=3743(sectors) AUDIO (2352bytes/sector)
track02 start=3593 length=45336(sectors) BINARY (2352bytes/sector)
track03 start=48929 length=2925(sectors) AUDIO (2352bytes/sector)
〜
track01 の 開始セクタが -150 と負の値になっているのは プリギャップを加味してるためでここは問題ありません
問題となっているのは track02 です
現行の CDemudでは 2048bytes/sector しかデータトラックの読み出しをサポートしていません
ソースコードでは cdemud-device.c にあたります
1462 /* READ 10/12 should support only sectors with 2048-byte user data */
1463 gint tmp_len = 0;
1464 guint8 *tmp_buf = NULL;
1465 guint8 *cache_ptr = _priv->buffer+_priv->buffer_size;
1466
1467 mirage_sector_get_data(MIRAGE_SECTOR(cur_sector), &tmp_buf, &tmp_le n, NULL);
1468 if (tmp_len != 2048) {
1469 CDEMUD_DEBUG(self, DAEMON_DEBUG_MMC, "%s: sector 0x%X does not have 2048-byte user data (%i)\n", __debug__, sector, tmp_len);
1470 g_object_unref(cur_sector);
1471 __cdemud_device_write_sense_full(self, SK_ILLEGAL_REQUEST, ILLE GAL_MODE_FOR_THIS_TRACK, 1, sector);
1472 return FALSE;
1473 }
1474
mirage_sector_get_data() でデータを読みだした結果 2048バイトでないとエラーとなります
ここを 以下のように修正しました
1462 /* READ 10/12 should support only sectors with 2048-byte user data */
1463 gint tmp_len = 0;
1464 guint8 *tmp_buf = NULL;
1465 guint8 *cache_ptr = _priv->buffer+_priv->buffer_size;
1466 gint tmp_type = 0;
1467
1468 mirage_sector_get_data(MIRAGE_SECTOR(cur_sector), &tmp_buf, &tmp_len, NULL) ;
1469 /*
1470 Add support some 2352bytes/sector format.
1471 */
1472 switch (tmp_len) {
1473 case 2048: /* MODE1 */
1474 memcpy(cache_ptr, tmp_buf, 2048);
1475 _priv->buffer_size += 2048;
1476 break;
1477 case 2352: /* MODE2 FORM1 etc.*/
1478 mirage_sector_get_sector_type(MIRAGE_SECTOR(cur_sector), &tmp_type, NULL);
1479 if ((tmp_type == MIRAGE_MODE_MODE1) || (tmp_type==MIRAGE_MODE_MODE2_FORM1)) {
1480 memcpy(cache_ptr, tmp_buf + 16, 2048);
1481 _priv->buffer_size += 2048;
1482 break;
1483 }
1484 /* Otherwise, I dont know where 2048-byte user data is in. */
1485 default:
1486 CDEMUD_DEBUG(self, DAEMON_DEBUG_MMC, "%s: sector 0x%X does not have 2048-byte user data (%i)\n", __debug__, sector, tmp_len);
1487 g_object_unref(cur_sector);
1488 __cdemud_device_write_sense_full(self, SK_ILLEGAL_REQUEST, ILLEGAL_MODE_FOR_THIS_TRACK, 1, sector);
1489 return FALSE;
1490 }
1491
CD-ROMのデータトラックは 通常 1セクタあたり 2048バイトのデータ構成となっていますが
実際は ヘッダ情報や CRCなどの付加情報が前後に含まれています
上記コードは 2352バイトのフォーマットにおいても データ部分 2048バイトを抜き出す対応を追加したものです
ただし MODE1 など 一部のフォーマットのみの対応なので完全ではありません
そもそも CD-ROMからイメージを抜き出す際に MODE1(2048bytes/sector)を指定すれば ここの問題は発生しません
で 問題はさらに続きます
Mednafenで PC-Engineの処理を解析した結果 次の不具合が確認されました
「Mednafenでは データトラックの読み込み開始で 開始セクタ=3593 を指定しているのに
CDemuにおいては 開始セクタ=3592 のセクタリードが要求されている」
Mednafenとしてのデバイスアクセス ioctl() 開始セクタ=3593 で要求
↓
Linuxカーネルのデバイスドライバ処理
↓
VHBA (仮想ドライバ)
↓
CDemu 開始セクタ=3592 の要求をイベントとして受ける
Linuxカーネルを経由することで セクタ番号がずれているように思われます
Linuxカーネルの内部動作まで確認しきれませんので いろいろ検証した結果以下の対応としました
「(Linuxでは?)CDトラックの開始セクタが 偶数セクタ番号となっているため
libmirageに調整処理を追加して トラックの開始セクタ番号が必ず偶数となるように合わせる」
これが一番 手短な改修でした libmirage のソースコード mirage-session.c に追加しました
91 cur_track_address += track_length;
92
93 /* track start address may be even-number.
94 I found a troube at following environment.
95 (MIXED-MODE)
96 track01 start=-150 length=3743(sectors) AUDIO (2352bytes/sector)
97 track02 start=3593 length=45336(sectors) BINARY (2048bytes/sector)
98 track03 start=48929 length=2925(sectors) AUDIO (2352bytes/sector)
99 ...
100 track02(DATA) start sector is just 3593, but Linux? set ioctl() start a ddress 3592 (-1).
101 So, CDemu is going to access to "track01" and fails.
102 (Because CDemu fails to access to 2352bytes/sector at current version.)
103 */
104 if ( cur_track_address % 2 ) cur_track_address++;
105 }
106
107 return TRUE;
CUEシートからトラック情報を読み取る処理 に追加し 開始セクタ位置を調整しました
以上の作業で ようやく 「アルナムの牙」が動作しました
パソコンで PC-Engineのゲームができるようになるとは いい時代です
残りの CD-ROMゲームも吸い出してしまおう
Post navigation