ユーザ用ツール

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン前のリビジョン
次のリビジョン
前のリビジョン
フルーツフィールド_for_pc-6001mkii [2020/12/09 02:35] – [感想] arakiフルーツフィールド_for_pc-6001mkii [2022/09/15 09:40] (現在) – [キー入力とジョイパッド] araki
行 137: 行 137:
   * 2020/11 初版   * 2020/11 初版
   * 2020/12/09 BGMを鳴らすようにした。   * 2020/12/09 BGMを鳴らすようにした。
 +  * 2020/12/10 ゲーム中の効果音もタイマー割込み側でならすように変更した。
 ===== 技術資料  ===== ===== 技術資料  =====
 ==== メモリーマップ  ==== ==== メモリーマップ  ====
行 163: 行 163:
 |グラフィックエリア|6000H-7FFFH| |グラフィックエリア|6000H-7FFFH|
 |キー入力|1061H|出力:A(ビットマップ)| |キー入力|1061H|出力:A(ビットマップ)|
 +|ジョイパッド入力|1CA6H|出力:A(ビットマップ)|
 |キー入力|0FBCH|出力:A=文字コード| |キー入力|0FBCH|出力:A=文字コード|
 |キーバッファクリア|1058H| |キーバッファクリア|1058H|
行 179: 行 180:
 |ロード用ファイル名エリア|FED1H-FED6H|6bytes| |ロード用ファイル名エリア|FED1H-FED6H|6bytes|
 |キークリック音|FA2DH|0:OFF/1:ON| |キークリック音|FA2DH|0:OFF/1:ON|
 +
 +==== 開発環境 ====
 +
 +フルーツフィールドは、ローダの書き込みにN60m-BASICを利用している以外は、すべてアセンブラで開発されています。
 +コードエディターはVisual Studio Codeを、アセンブラを含む開発ツール一式は、WSL2の上に展開したUbuntu上に用意しています。
 +アセンブラは[[https://github.com/Megatokio/zasm|ZASM]]です。
 +普通に、''git clone https://github.com/Megatokio/zasm.git'' して、ビルドしてあります。
 +MINGWなどで、Windows版を用意してもいいかと思いますが、WSL2は慣れるともう戻れないですね。
 +Windowsネイティブのバイナリが必要でないなら、WSL2で十分だし、便利だと思います。
 +
 +WSL2はWindowsとのファイルの交換が容易なので、ビルドしたコードを即座にWindows上のエミュレータに送り込むことができます。
 +WSL2側からは ''/mnt/<ドライブ名>/<パス>''で、Windows側からは ''\\wsl$\Ubuntu\<パス>''でそれぞれ、互いのファイル空間にアクセス可能です。
  
 ==== ローダー  ==== ==== ローダー  ====
行 603: 行 616:
 というか、ゲームでBGM鳴らす場合はみんなこんな風な処理をしているものなんですよね? というか、ゲームでBGM鳴らす場合はみんなこんな風な処理をしているものなんですよね?
  
 +=== 競合 ===
 +
 +ゲーム中、ビープ音的な音を鳴らすわけです。ブロックを消したときとかフルーツを取った時ですが。
 +元々、BGMがなかった時分には、直接そこでPSGをたたいて音を出していたのですが、タイマー割込みで、BGMを鳴らしだすと、どうやら、PSGを触っている最中に割り込まれて、おかしな動作((具体的には音が止まらない))をするようになりました。
 +
 +さて困った。
 +
 +PSGの操作は、ポート''A0H''にレジスタ番号を出力して選択したレジスタに対して、ポート''A1H''経由で値を出力するという手順で行います。
 +このレジスタの選択からデータの出力までの間に割込みが入って、向こう側でもPSGをたたいてくれると、こちらで選択したはずのレジスタじゃないものが選ばれた状態で帰ってくる可能性があります。
 +これが消音 -- ボリューム0を出力する処理 -- の最中に来たら、意図しないレジスタに0を出力してしまい、期待しない作用を引き起こす可能性がありますし、肝心のレジスタに0が出ずに音が止まらないということになります。
 +ビープ音鳴りっぱなしはエラー感、バグバグ感たっぷりでいただけません。
 +
 +なので、最初に試したのが、レジスタの選択からデータの出力までの区間を割込み禁止 -- ''di''~''ei''で括る -- です。
 +が、どうもタイマー割込みはこれを無視しているようで、症状は一向に改善しません。
 +
 +じゃあ、ビープ音を鳴らしている間はタイマーを止めるか?
 +とも思ったのですが、タイマー割込み16回分くらいはビジーループで時間調整しているので、好ましくありません。
 +多分BGMがおかしなことになるでしょう。
 +
 +''B0H''への出力のように、''A0H''に出力した値もワークエリアに残すか、とも思いましたが、PSGたたくときにはガンガンレジスタを変えるので、''out''を一個発呼するために、''ld (nnnn),a''を一つ発呼するのはいかにもイケてません。
 +大体、レジスタを選択してからワークエリアを更新するまでの間に割り込まれたら何の解決にもありません。
 +
 +割込みでPSGを操作して戻るときにチャンネルAの音量を0にするというのはよさげにも思えましたが、場合によっては音が鳴らないかもしれません。
 +
 +となったら、もう、ビープ音もタイマー割込み側でならせばいいじゃん、という結論に至りました。
 +
 +メインルーチン側では、ビープ音の音程、音量、そしてどのくらいの間鳴らすかの三つの値をワークエリアに書き込みます。
 +割込み側では、これらを読んで、指定された音程、音量を設定し、音の長さを0になるまで割込みごとに減算して、0になったところで音量を0にして終わります。
 +
 +割込みは1/512s間隔で発生するので、平均待ち時間は1/1024s程度になります。
 +ビープ音を鳴らしたいタイミングから平均1ms未満の待ち時間ですので、テストプレイした限りでは、音が遅れて鳴るようなことはありませんでした。
 +めでたし。
 +
 +万一、鳴っている最中に、別のビープ音を鳴らす処理(値の更新)があったら、まあ、音がつながって長くなったりするだけ(のはず)なのでいいことにします。
 +
 +AY-3-8910のエンベロープには単調に減少するとか、単調に大きくなるとかはあるんですが、一定期間ONで周期が来たら0になるというようなものがないので、ビープ的な音を鳴らしたい場合には、一定期間鳴らしたらオフにするという操作がひつようになるため、まあ、こんなやり方で逃げるしかないのかな、と、いう感じです。
 +
 +なお、カウンターは手抜きで、1byteしかとっていませんので、音の長さは 1/512s~1/2s になります。
 +まあ、0.5秒より長く鳴らすともうそりゃビープじゃないよな、ということで、フルーツフィールド的にはよいことにします。
 +
 +副作用として、ビープ音のためにビジーループしていたのがなくなって、タイマー割込みでタイミングを見るようにしたので、連続してフルーツを取るのが多分少しだけ早くなっています。
 ==== 16bit演算 ==== ==== 16bit演算 ====
  
行 662: 行 716:
 なので、フルーツフィールド内でも同様にしていますが、とりあえず問題は起きてないので良いことにしておきます。 なので、フルーツフィールド内でも同様にしていますが、とりあえず問題は起きてないので良いことにしておきます。
  
 +==== キー入力とジョイパッド ====
 +
 +PC-6001にはゲーム用のキー入力ルーチンがあり、Aレジスタにビットマップ値でキー入力を返してくれます。
 +フルーツフィールドでもこれを利用していますが、[[DevTerm]]についているジョイパッドに対応するために、ジョイパッドの入力を拾うルーチンも呼び出す必要が発生しました。
 +このルーチンもジョイパッドの操作をAレジスタにビットマップとして返してくれるのですが、このマッピングが、キー入力のそれと違うのです。
 +NECは何を考えて異なるビットマップを返すようにしたのでしょう?
 +
 +^-^0^1^2^3^4^5^6^7^
 +|キー|SHIFT|STOP|↑|↓|→|←|-|SPACE|
 +|ジョイパッド|↑|↓|←|→|A|B|-|-|
 +
 +上のようなビットマップなんです。
 +いやらしいのは、そもそも方向とトリガー相当のもののマッピングがずれているし、右左が逆になっていたりするところ。
 +
 +都度、それぞれの処理を書くのは面倒なので、既に、キー入力に合わせて処理を組んでいるので、ジョイパッドの入力をキー入力に合わせるように変換するコードを書いて、対応しました。
 +
 +<code>
 +;;; gamekeypad
 +gamekeypad:
 +        call    gamekey
 +        and     a
 +        ret     nz        ; キー入力があったら戻る
 +
 +        ld      a,1       ; ジョイパッド#1からの入力を見る
 +        call    joystick
 +        and     a
 +        ret             ; 何も押されてなければ戻る
 +        push    bc
 +        ld      b,0
 +        ld      c,a
 +        rlc             ; 左に1bitローテートして 10hでマスクして→を取り出す。  |-|-|-|-|→|-|-|-|
 +        ld      a,10h
 +        and     c
 +        ld      b,a
 +        rlc             ; 左に1bitローテートして 0chでマスクして↑↓を取り出す。 |-|-|↑|↓|-|-|-|-|
 +        ld      a,0ch
 +        and     c
 +        or      b
 +        ld      b,a
 +        rlc             ; 左に1bitローテートして 0a3hでマスクして←とABを残す。 |B|-|-|-|-|←|-|A|
 +        ld      a,0a3h
 +        and     c
 +        or      b                                                              |B|-|↑|↓|→|←|-|A|
 +        pop     bc
 +        ret
 +</code>
 ===== 技術的ではないボヤキのようなもの  ===== ===== 技術的ではないボヤキのようなもの  =====
  

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also, you acknowledge that you have read and understand our Privacy Policy. If you do not agree, please leave the website.

More information