Files
rix2midi/README.md
2026-08-22 05:54:36 +00:00

3.7 KiB
Raw Permalink Blame History

rix-midi —— 《大富翁 2》RIX → MIDI 轉換器by Qwen 3.8:27B

把 DOS 遊戲《大富翁 2》的 .RIX 音樂檔,轉成標準 .MIDI 樂譜。 可以一次轉單一個、也可以整個資料夾批次轉。

同一批 .RIXadplay / AdPlug 也可以轉成 WAV純音訊 這裡只處理「轉成 MIDI 樂譜」這件比較有挑戰的事。


為什麼 RIX 不能直接「拿出來」當 MIDI

.RIX 不是存音符的格式。它是 AdLib OPL 晶片的「機器碼」: 一段由「時鐘節拍tick」驅動的下載程式每個 tick 告訴 OPL 晶片 要寫哪些「暫存器」(頻率、開聲、音量……)。所以 RIX 裡只有 「要讓硬體發出什麼」的指令,沒有現成的音符——得「還原」出來。

原理(我們怎麼還原)

  1. 借用 AdPlug 來 decode + 模擬 OPL 晶片(它已把 RIX 的機器碼 正確地「跑成」一串 OPL 暫存器寫入)。
  2. 劫持 OPL 的 write()AdPlug 發聲前會走 Copl::write(reg,val) 我們繼承它的模擬器、順手把「每個 tick、每個聲道的 A / B 暫存器」記下。
  3. 暫存器 → 頻率 → 音符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
    
  4. 節奏一致:測出 RIX 是「70 tick / 秒」。把 MIDI 速度設成 tempo = 1e6 × 96 ÷ 70 ≈ 1,371,428 µs/quat96 ticks/quat 讓 1 個 RIX tick == 1 個 MIDI tick整首的時值就和原曲一致。
  5. 樂器OPL 不分旋律/和聲,依每個聲道音高的「中位數」粗略指派 GM 樂器(偏低→貝斯、其餘→方波 Lead。聽起來像原曲的務實選擇。

已驗證

對全部 23 首,MIDI 時長與同曲 WAV 時長比對22 首幾乎完全一致ratio 1.00、 1 首RICHX因 WAV 尾端多靜音而略短。音高也抽樣驗證正確(中音 C=60


編譯

依賴 AdPlugRIX/OPLlibbiniobuild.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/)。