MSXにSFG-01やSFG-05を繋いで、自作のサウンドドライバを使って曲を演奏させているのですが、挙動の違いで困っていることがあります。
SFG-01/05は資料も少なく、また、OPMについても私自身あまり明るくないので、もしご存知の方がいればぜひアドバイスをいただきたいです…。
…という質問をtwitterでつぶやいたところ
回答をいただきました!
こちらのページに書かれておりました。
http://map.grauw.nl/resources/sound/yamaha_ym2164.php
SFG-01はOPM、SFG-05はOPPが搭載されているのですが、OPPはTimerBの挙動がOPMと違っており、セットする値も変えなければならないようです。
これでスッキリしました。
次回ドライバを作るときには、正式に両対応したいと思います!
こちらの動画は、TimerA・TimerB ともにタイマー割り込みを10ms(1/100秒)に設定し、割り込み10回(1/10秒)ごとに文字を表示して、さらに10文字(1秒)ごとにキャラクターを変更して表示位置をリセットしています。
しかし、SFG-05の TimerB のみ、割り込み回数が1/2になってしまうのです…。
TimerBを使用したサウンドドライバを作りたいのですが、この挙動の違いが解決できず、困っております。
;================================================== ; SFG-01/SFG-05 タイマー割り込みテストプログラム ;================================================== ;------------------------------------ ;SFG REGISTER ;------------------------------------ OPMSTAT EQU 3FF1H OPMADDR EQU 3FF0H OPMDATA EQU 3FF1H ;------------------------------------ ;VDP PORT ;------------------------------------ VDPPORT0 EQU 098H VDPPORT1 EQU 099H ;------------------------------------ ;情報表示用VRAMアドレス ;------------------------------------ SFGVRAM EQU 1806H TMAVRAM EQU 1900H TMBVRAM EQU 1A00H ;------------------------------------ ;ワークエリア ;------------------------------------ WORK EQU 0C800H WORKTMA EQU WORK WORKTMB EQU WORK+4 ;------------------------------------ ;SFGスロット ;------------------------------------ SFGSLTBS EQU 2 ;SFGの基本スロットを書く SFGSLTEX EQU 0 ;SFGの拡張スロットを書く ;------------------------------------ ;TIMER A ;------------------------------------ ;Taを割り込み時間(msec)とすると以下の式で計算できる ;CLKA = 1024 - Ta * 3579.545 / 64 ;10msec(1/100sec)の場合 CLKA = 465 = 01D1H CLKA EQU 01D1H ;全10ビット CLKAH EQU (CLKA/4) ;上位8ビット CLKAL EQU CLKA-(CLKAH*4) ;下位2ビット ;------------------------------------ ;TIMER B ;------------------------------------ ;Tbを割り込み時間(msec)とすると以下の式で計算できる ;CLKB = 256 - Tb * 3579.545 / 1024 ;10msec(1/100sec)の場合 CLKB = 221 = 00DDH CLKB EQU 00DDH ;全8ビット ;------------------------------------ HEADER: DB 0FEH DW PRGSTART DW PRGEND-1 DW PRGSTART ORG 0A000H PRGSTART: LD A,1 CALL 005FH ;CHGMOD スクリーン1に変更 LD HL,TXTSFG LD DE,SFGVRAM LD BC,20 CALL 005CH ;LDIRVM ;SFGのバージョンを調べる LD A,SFGSLTBS+SFGSLTEX*4+80H ;スロット番号 LD HL,0073H CALL 000CH ;RDSLT ;SFG-01: "1983 by YAMAHA" ;SFG-05: "1984 by YAMAHA" ; ^ ここの文字をチェック(0073H) CP '3' JR Z,SFG01 CP '4' JR Z,SFG05 RET SFG01: LD HL,TXTSFG01 JR SFGINFO SFG05: LD HL,TXTSFG05 SFGINFO: LD DE,SFGVRAM+13 LD BC,7 CALL 005CH ;LDIRVM LD HL,TXTTMRA LD DE,TMAVRAM+12 LD BC,6 CALL 005CH ;LDIRVM LD HL,TXTTMRB LD DE,TMBVRAM+12 LD BC,6 CALL 005CH ;LDIRVM DI ;SFGを表に出す CALL CHGSLOT ;ワークエリア初期化 LD HL,WORKINI LD DE,WORK LD BC,8 LDIR ;TimerA 割り込みセット LD D,10H ;レジスタ10H LD E,CLKAH CALL OUTSFG LD D,11H ;レジスタ11H LD E,CLKAL CALL OUTSFG ;TimerB 割り込みセット LD D,12H ;レジスタ12H LD E,CLKB CALL OUTSFG ;割り込み開始 LD D,14H ;レジスタ14H ;--------------------------------------------------------------- ;bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 ;- - TmBリセ TmAリセ TmB許可 TmA許可 TmB開始 TmA開始 ;--------------------------------------------------------------- LD E,3FH ;TimerA, TimerB 両方を許可&リセット CALL OUTSFG WAIT: ;ステータスを読む LD A,(OPMSTAT) ;--------------------------------------------------------------- ;bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 ;BUSY - - - - - TimerB TimerA ;--------------------------------------------------------------- BIT 7,A JR NZ,WAIT ;BUSY ;TimerA割り込みチェック BIT 0,A PUSH AF CALL NZ,TMAFUNC POP AF ;TimerB割り込みチェック BIT 1,A CALL NZ,TMBFUNC JR WAIT ;------------------------------------ ;OPMレジスタ書き込み ;入力: D レジスタ ; E データ ;------------------------------------ OUTSFG: LD HL,OPMADDR LD (HL),D LD HL,OPMDATA LD (HL),E RET ;------------------------------------ ;TimerA割り込み時処理 ;------------------------------------ TMAFUNC: LD IX,WORKTMA ;TimerA用ワーク CALL TMCNTUP ;カウントアップとキャラ表示処理 LD D,14H ;レジスタ14H LD E,1FH ;TimerAのみリセット CALL OUTSFG RET ;------------------------------------ ;TimerB割り込み時処理 ;------------------------------------ TMBFUNC: LD IX,WORKTMB ;TimerB用ワーク CALL TMCNTUP ;カウントアップとキャラ表示処理 LD D,14H ;レジスタ14H LD E,2FH ;TimerBのみリセット CALL OUTSFG RET ;------------------------------------ ;割り込み回数をカウントする ;10回割り込みが入るごとに画面にキャラクターを表示 ;100回割り込みが入ると表示位置を左端にリセット ;入力: IX ワークエリア先頭 ;------------------------------------ TMCNTUP: LD A,(IX+0) ;割り込み回数カウンタ INC A CP 10 JR C,TMCNTUPR ;10回割り込みが入ったか LD A,(IX+2) OUT (VDPPORT1),A ;キャラクター表示アドレスセットL PUSH AF LD A,(IX+3) OR 40H OUT (VDPPORT1),A ;キャラクター表示アドレスセットH LD A,(IX+1) OUT (VDPPORT0),A ;キャラクター表示 POP AF INC A CP 10 JR C,TMCNTUPV ;キャラクターを10個表示したか INC (IX+1) ;表示キャラクターを変更 XOR A ;表示位置を左端にリセット TMCNTUPV: LD (IX+2),A XOR A ;割り込み回数カウンタをリセット TMCNTUPR: LD (IX+0),A ;割り込み回数カウンタアップデート RET ;------------------------------------ ;PAGE0をSFGのスロットに切り替える ;------------------------------------ CHGSLOT: IN A,(0A8H) AND 0FCH OR SFGSLTBS ;PAGE0の基本スロットをSFGに切り替える LD B,A AND 3FH OR SFGSLTBS*64 OUT (0A8H),A ;拡張スロット切り替えのために一時的にPAGE3も切り替える LD A,(0FFFFH) CPL AND 0FCH OR SFGSLTEX LD (0FFFFH),A ;拡張スロットをSFGのスロットに切り替える LD A,B OUT (0A8H),A ;PAGE3は戻す RET ;------------------------------------ ;ワークエリア初期値 ;------------------------------------ WORKINI: ;Timer A DB 0 ;TimerAの割り込みが入るとカウントアップ DB 0 ;TimerAチェック用に表示するキャラクター DW TMAVRAM ;TimerAチェック用キャラを表示するアドレス ;Timer B DB 0 ;TimerBの割り込みが入るとカウントアップ DB 0 ;TimerBチェック用に表示するキャラクター DW TMBVRAM ;TimerBチェック用キャラを表示するアドレス ;------------------------------------ ;テキスト ;------------------------------------ TXTSFG: DB 'This slot is not SFG' TXTSFG01: DB 'SFG-01 ' TXTSFG05: DB 'SFG-05 ' TXTTMRA: DB 'TimerA' TXTTMRB: DB 'TimerB' ;------------------------------------ PRGEND: ;------------------------------------ END |
blueMSX、openMSXともに、Timer割り込みのタイミングが遅く、TimerA、TimerBを使っているドライバーは演奏速度が1/2になってしまいます。
いつか修正されることを期待しています。