似非OPMでSFG-05のBIOS ROMが動作しない件

当方からリリースしている似非OPM-ROMですが、FlashROMにSFG-05のBIOS ROMをインストールした際、CALL MUSICでフリーズするという報告がありました。

うっかりしていました。動作テストではSFG-01のBIOS ROMを使っていて、CALL MUSICで不具合が確認できなかったので油断していました。実際にSFG-05のBIOS ROMで確認してみると確かに下画像のような状態でフリーズします。

turboR(Z80モード)では、MSX2と同じ白画面でフリーズしました。本物のSFG-05をスロットアダプタ経由でこれらの機体に挿した場合は問題なくCALL MUSICできました。

ちなみにSFG-05より若いスロットにMSX-MUSICのFMBIOSが存在する場合(松下2+やtR等)はCALL MUSICするとMSX-MUSICの方が有効になってしまうので、SFG-BIOSで動かす場合はCALL MUSICAとか、MUSICの後に適当な文字が必要です。


原因追求

SFG-05のBIOS ROMを逆アセンブルして調べてみたところ、SFG-05のBIOSはZ80の割り込みモード2(IM2)を使っていることが明らかになりました。海外のサイトには以下の情報が出ており、この件については既知だったようです。

http://map.grauw.nl/resources/midi/ym2148.php

本来MSXではIM1しか使われないことになっており、MSXのメインROMもそのような構造になっています。しかし、SFG-05ではCALL MUSICでPage0のシステム領域をゴッソリSFG-05のROMに差し替えて、MSXとは別のシステムで動作しているような状態になっていました。当然MSXのBIOSコールは使えませんが、強引にIM2を使うような手法も採れるというわけです。

Z80のIM2はどのように使われるのか、Z80のデータシートを調べてみました。IM2の状態で割り込みが発生すると、Iレジスタに定義した上位8bitと、割り込みコントローラ(特別に用意されたハードウエアが)が発行する下位8bit(IRQベクタ)が示すテーブルに書かれているアドレスがCALLされるようです。

IRQベクタの下位8bitは、下のチャートが示すように/M1と、/IOREQがLレベルに落ちたタイミングで、割り込みコントローラが出力したデータを取り込むことになっています。

SFG-0xの回路図を見ると/IOREQと/M1がL時に/BUSDIRを立ち下げてコントローラ(YM2148)に入力しています。このタイミングでYM2148がデータバスにIRQベクタの下位8bitを発行していると思われます。

先程のGrauwさんのサイトを参照すると、SFG-0xのIRQベクタを書き込むアドレスはこのように定義されていました。

SFG-0xでは予め3FF3h、3FF4hにIRQベクタ(下位8bit)を書いておくと、割り込みが発生した時にYM2148がこの値をデータバスに出力する仕組みになっていると解釈できます。MIDI割り込みと外部割り込みの2種類がありますが、MIDI割り込みはYM2148自身が発行するものなので、このときは自動的に3FF3hの値を発行して素早く処理に移行しているのでしょう。おそらくMIDI割り込みの精度を高めるためにこのような仕組みにしたものと思われます。

外部割り込みとしてはOPMのタイマー割り込みと、VDPの割り込みがありますが、このときは3FF4hの外部IRQベクタを発行してソフトウエア的に識別しているようです。

似非OPMではMIDI割り込みが発行されることはないので、3FF3hのレジスタは無視して良さそうに見えます。CPLDで再現する場合は新たに3FF4hに8bitのレジスタを設けて、/M1と/IORQがLになったタイミングで/BUSDRをLに落とした上でデータバスに値を出力するように作ればSFG-05のBIOSも動作するかもしれません。


ハードウエア的に検証してみる

CPLDリソースの都合で似非OPMにIRQベクタを発行する機能を付加するのは難しいので、専用の基板を作成して検証してみます。

実験用に適当な試作機の基板から、Z80のアドレスバスとデータバスがすべてCPLDに繋がっているものを選択しました。/M1は適当な未使用ピンに繋げればいいでしょう。CPLDには下記のようなVHDLで書き込みました。

----------------------------------------------------------------
--  Title     : IM2test.vhd
--  Function  : EseOPM IM2 device for SFG-05 compatibility
--  Date      : 15th,Mar,2023
--  Revision  : 0.1
--  Author    : Niga.
----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

-- update history
--  15th,Mar,2023 by Niga. first release

entity IM2test is
  port(
    pSltRst_n   : in std_logic;                        -- /RESET
    pSltClk     : in std_logic;                        -- CPU clock
    pSltSltSl_n : in std_logic;                        -- /SLTSL
    pSltWr_n    : in std_logic;                        -- /WR
    pSltRd_n    : in std_logic;                        -- /RD
    pSltIorq    : in std_logic;                        -- /IORQ
    pSltAdr     : in std_logic_vector(15 downto 0);    -- Adr A0-A15
    pSltDat     : inout std_logic_vector(7 downto 0);  -- D0-D7
    pSltBusdir  : out std_logic;                       -- /BUSDIR
    pSltM1      : in std_logic                         -- Z80 /M1

 );
end IM2test;

architecture rtl of IM2test is
    signal IRQAd_ext  : std_logic_vector(7 downto 0);     -- Ext. IRQ address
    signal Busdir     : std_logic;

begin
  ----------------------------------------------------------------
  -- BUSDIR output
  ----------------------------------------------------------------
   Busdir <= '0' when pSltM1 = '0' and pSltIorq = '0' else
             '1';

   pSltBusdir <= Busdir;

  ----------------------------------------------------------------
  -- 3FF4h IRQ vector Reset & Write 
  ----------------------------------------------------------------
  process(pSltRst_n, pSltClk)
  begin
      -- Reset
   if (pSltRst_n = '0') then
      IRQAd_ext  <= X"00";

      elsif (pSltClk' event and pSltClk = '0') then
        if pSltAdr(13 downto 0)= "11111111110100" and pSltSltsl_n = '0' and pSltWr_n = '0' then
            IRQAd_ext  <= pSltDat(7 downto 0);			 
        end if;
      end if;
  end process;

  ----------------------------------------------------------------
  -- IRQ vector output
  ----------------------------------------------------------------
   pSltDat <= IRQAd_ext when Busdir = '0' else
              (others => 'Z');

end rtl;

問題はこの基板にも似非OPMと同じ/SLTSLを与える必要があることですが、核スロのCPLDを書き換えて外部スロットをどちらも#X-0になるようにして実験しました。

その結果、似非OPMでもSFG-05のCALL MUSICが立ち上がりました。ただし、このソフトは外付けのミュージックキーボードを必要とするらしく、似非OPMで起動しても特に使い道はなさそうです。MusicCompoer2も起動はするようでした。しかし、MIDI割り込みについては未処理なので何らかの不具合は出るかもしれません。


似非OPMでの根本的な対処は不可能と結論

ということで、フリーズの原因はIM2の使用と断定しました。似非OPMでIM2に対応させるには、MegaROM対応を諦めてCPLDのピンアサインを変更して基板を作り直すレベルの話になりますが、コストやCPLDリソースを考慮すると、ちょっと現実的ではありません。

似非OPMはネットで出回っている楽曲データを生のFM音源で再生したり、OPM音源付きのMegaROMソフトを作れるというコンセプトで設計したものです。SFG-0xの互換性については、MIDIやミュージックキーボードの接続機能を排除していることから分かるように割り切っています。YAMAHAの作曲ソフト群についてはオマケで動けば…くらいに思っていました。

とはいえ、似非OPMは取説でSFG-0xとの互換性を謳っていましたので、優良誤認を誘っていると指摘されたら反論はできません。YAMAHAのソフトで使うことを目的に購入された方には、ご期待に添えずに申し訳ございません。本件を理由に返品をご希望される方がおられましたら応じますので、所有されている似非OPMにご自身のネットネームが書かれている紙片を重ねて写真を撮り、この記事のコメント欄にネットネームとメルアドを記入した上で画像ファイルを添付してください。折り返しメールで返送・返金についてご案内します。記入されたメルアドは管理者のみに通知され、外部には公開されません。勝手ながら期限は5月末日までと設定させていただきます。


似非OPMの活用事例

GrauwさんのVGMPlayやいとけんさんのMAmi-VSIFドライバ等、一般ユーザーが作成しているフリーソフトは、SFG-0xのROMの0080hに存在する識別文字列を読んでいるだけなので、SFG-05のBIOSをインストールした状態でも特に問題なくお使いいただけます。

TINY野郎さんがyoutubeで公開されているゲームミュージックデモは動画の概要欄のリンクからダウンロードできます。

https://www.youtube.com/@tiny_yarou/videos

例えばこういうのです。

海外でMSXゲームのOPMパッチが公開されているものがあり、これらで似非OPMを発音させることもできます。

https://github.com/ToughkidDev/mglOcm/tree/master/ArcadeEnhanced

ただし、これらの中にはOPMを3FF0-3FF1hではなくミラーアドレスの7FF0-7FF1hでアクセスしているものがあります。その場合は似非OPMの基板を取り出してJP1にハンダを盛ってショートしてください。JP1ショートで似非ROMは16kバンクモードになり、OPMは3FF0-3FF1hでも7FF0-7FF1hでもアクセスできるようになります。16kバンクモードではFlashROMの書き込みが正常にできませんので、書き込み時はJP1のハンダを除去して8kバンクに戻してください。


似非OPMの4MHzモードについて

GrauwさんのVGMPlayはOPMを3.58MHzで鳴らすことを前提に周波数を変換しています。変換されるのは常にPSG側であり、FM側は変換されません。例えば原曲が4MHzの曲を3.58MHzのOPMで再生した場合、OPMは周波数変換されず低いキーで再生され、PSGはそれに合わせて低いキーに変換されます。原曲が3.58MHzの場合はどちらも変換されずに原曲通りに鳴ります。

似非OPMには4MHz切り替えスイッチがありますが、VGMPlayではこれを識別できませんし、周波数指定するオプションも存在しません。よって4MHzモードで原曲4MHzの曲を再生すると、OPMは正しいキーで発音される一方で、MSX本体が出力するPSG音声が低いキーに変換されて不協が生じます。

この問題を回避するには、VGMplayにパッチを当ててOPM 4MHz用の実行ファイルを作る必要があります。具体的には下記のように書き換えてください。

■OPM(YM2151) 4MHz化 : VGMPlay msx (ver1.3)
68EAh [99 9E 36] → [00 09 3D]
6928h [99 9E 36] → [00 09 3D]

これで本体PSGと調和するはずです。ちなみに似非OPMではSFG-0xとは異なり、音声信号をMSX本体のスロットに出力しません。PSGとミキシングする場合は、MSX本体の音声出力を似非OPMの入力端子に接続してください。ミキシングバランスは似非OPM背面のVRで調整できます。

以上の件は調和しないという報告がありましたので一旦保留にします。