rix-midi —— 《大富翁 2》RIX → MIDI 轉換器(by Qwen 3.8:27B)
把 DOS 遊戲《大富翁 2》的 .RIX 音樂檔,轉成標準 .MIDI 樂譜。
可以一次轉單一個、也可以整個資料夾批次轉。
同一批
.RIX用 adplay / AdPlug 也可以轉成 WAV(純音訊), 這裡只處理「轉成 MIDI 樂譜」這件比較有挑戰的事。
為什麼 RIX 不能直接「拿出來」當 MIDI?
.RIX 不是存音符的格式。它是 AdLib OPL 晶片的「機器碼」:
一段由「時鐘節拍(tick)」驅動的下載程式,每個 tick 告訴 OPL 晶片
要寫哪些「暫存器」(頻率、開聲、音量……)。所以 RIX 裡只有
「要讓硬體發出什麼」的指令,沒有現成的音符——得「還原」出來。
原理(我們怎麼還原)
- 借用 AdPlug 來 decode + 模擬 OPL 晶片(它已把 RIX 的機器碼 正確地「跑成」一串 OPL 暫存器寫入)。
- 劫持 OPL 的 write():AdPlug 發聲前會走
Copl::write(reg,val), 我們繼承它的模擬器、順手把「每個 tick、每個聲道的 A / B 暫存器」記下。 - 暫存器 → 頻率 → 音符(OPL 的標準公式):
F-number = A暫存器(低8位) | B暫存器bit0-1(高2位) block = B暫存器 bit2-4 (決定八度倍頻) key-on = B暫存器 bit5 (1=開、0=關) 頻率Hz = F-number × 2^block × 3579545 / (72 × 2^24) × 8 MIDI音符 = round( 69 + 12×log2( 頻率 / 440 ) ) # 69 = A4, 60 = 中音C - 節奏一致:測出 RIX 是「70 tick / 秒」。把 MIDI 速度設成
tempo = 1e6 × 96 ÷ 70 ≈ 1,371,428 µs/quat(96 ticks/quat), 讓 1 個 RIX tick == 1 個 MIDI tick,整首的時值就和原曲一致。 - 樂器:OPL 不分旋律/和聲,依每個聲道音高的「中位數」粗略指派 GM 樂器(偏低→貝斯、其餘→方波 Lead)。聽起來像原曲的務實選擇。
已驗證
對全部 23 首,MIDI 時長與同曲 WAV 時長比對:22 首幾乎完全一致(ratio 1.00)、 1 首(RICHX)因 WAV 尾端多靜音而略短。音高也抽樣驗證正確(中音 C=60)。
編譯
依賴 AdPlug(RIX/OPL)與 libbinio。build.sh 會自動找/編它們,
再以靜態連結產出自給自足的執行檔(不用設 LD_LIBRARY_PATH):
./build.sh # 在本機 AdPlug=/tmp/AdPlug、libbinio=/tmp/libbinio 的前提下
想指定位置:
ADPLUG=/path/to/AdPlug BINIO=/path/to/libbinio ./build.sh
使用
./rix2midi --help
# 單一個 .RIX → 同名 .mid
./rix2midi ./RICHU.RIX # 產出 RICHU.mid
./rix2midi ./RICHU.RIX 我的.mid # 指定輸出檔名
# 批次:把「整個資料夾」裡所有 .RIX 轉到「輸出資料夾」
./rix2midi ../ ../mid # ../ 所有 .RIX → ../mid/*.mid
./rix2midi -v ../ ../mid # 加 -v 看 tick 數等詳細訊息
檔案
| 檔案 | 說明 |
|---|---|
rix2midi.cpp |
轉換器本體(含完整中文註解) |
build.sh |
一鍵編譯(找/編 AdPlug、靜態連結) |
rix2midi |
編譯出的執行檔 |
小限制(MIDI 本質)
- 只能還原 OPL「發聲的音色」層次的音高+時值,是旋律骨架, 不是完整編曲(沒有真正的和聲/鼓聲)——這是 RIX/OPL 格式的天花板。
- 樂器指派是「猜」的(依音域),不是原曲精確編配。
- 若你想要「聽起來就等於 DOS 原版」的 WAV,用 adplay 那一套(
../wav/)。
Description
Languages
C++
88.7%
Shell
11.3%