PC-6001: July 2009アーカイブ

私は普段ほとんどゲームをしない(別に嫌いなわけではない)のですが、ふと見つけてダウンロードしたゲームにちょっとはまっています。 東方プロジェクトという方々が作られているゲームで、東方何某というシューティングゲーム(の体験版)です。

このゲーム、当然私は一番やさしいモードでしかまともにプレイできません。 でも面白いと思ったのは、「敵の弾が画面一杯に出るけど、避けられる」ように作ってある点です。 当たり判定を狭く設定してあるのと、ボス戦など強い敵の場合には自機の近くでは弾のスピードが落ちるようにしてあるので、落ち着いて行動するとかわせるのですね。 とは言っても常に、というわけではないですし、未だに体験版をクリアすることもできてませんけど。

で、ちょっとだけ作ってみたいなどと思ってしまいました。 もちろん、ストーリーやキャラデザインやらゲームバランス調整やら、能力と根気のない私にはとても無理です。 私が思ったのは、ゲームのアルゴリズムのほうの話です。

その昔、PC-6001などでゲームを作りまくっていた頃があるのですが、不思議とシューティングゲームをほとんど作った記憶がありません。 アクションパズルやシミュレーション、ロールプレイングゲームみたいのは結構作ってましたが。

今考えてみると、どうも「弾を飛ばす」のが苦手みたいなのです。 三角関数も知らなかった当時、任意の角度に複数の弾を飛ばす、というのがものすごく難しく見えました。 また、敵の動きのアルゴリズムをどうやったらパターン化できるか(e.g. 編隊飛行)、ということも知りませんでした。 いろいろ挑戦したけど挫折。 以来トラウマになったみたいです。

んで何となくWebを彷徨っていたら、国立情報学研究所(NII)のサイトにシューティングゲームの敵機攻撃弾発射アルゴリズムに関する考察 などという論文を見つけ、ちょいと驚きました。 確かに、Entertainment Computingは私がCMUにいたときにひとつの分野として確立していましたから、何も不思議はないのですが。

でも今見ると、たまにはこういうのを作るのも楽しそう、と思えてきます。 もちろんターゲットマシンはPC-6001。 まぁ、自機や敵機の動きを作ったり、弾を飛ばすことなどで満足してしまい、ゲームとして完成させることは無理でしょうけどね...。


続きです。 西田さんからBELUGAのアダプターの回路図を参考にせよとの指摘があったので、それに習って調べています。

まず、BELUGAのアダプターは次のように信号を作っています。

CS = (RAS2 and EXCAS) or (MREQ & デコード済みアドレス)
OE = DRD2 or CS3

なお、全部負論理である点に注意してください。

私のカードの論理は次のように修正しました。

CS = EXCAS or (MREQ & デコード済みアドレス)
OE = DRD2 or RD

これで動かしてみたことろ、テキストモードのページ1とページ4がちらついた状態で表示されました。 ただし、スクリーンモードを4などにすると画面が乱れます。

どうも、ページ1にはページ1とページ3が、ページ4にはページ2とページ4が混じって表示されているみたいです。 その証拠に、画面左下のページ番号がちらついて両方表示されており、たとえばページ3のスクリーンモードを変更するとページ1の表示に影響しています。

BELUGAのカートリッジでCS3を使っているのはROMエリア読み出し用だと思うのですが、DRD2のみでRDを使ってない理由はよく分かりません。 DRD2はVRAM DMA用のRD信号ですが、通常のメモリアクセスでもアサートされるのでしょうか?

CSを作るのにRASとのandを取っているのもよく分かりません。 SRAMですから、CASだけ見れば十分じゃないかと思っているのですが、タイミング的にRASも見ないとネゲートのタイミングが遅すぎたりするのかな?

CS2/CS3などを扱うROMエリアがメモリデコードだけでアクセス可能になるかどうかも気になりますが、その前にRAMエリアももう少し調査・実験が必要です。

(20 July 2009追記)

CSの入力をEXCASの代わりにRAS2に変更してみると、まったく画面が乱れたままなので、やはりEXCASのほうが「近い」のですが、andを取らなければならないのかもしれません。

と思い、EXCASとRAS2の両方を使ってみました。 つまり、

CS = (RAS2 and EXCAS) or (MREQ & デコード済みアドレス)
OE = DRD2 or RD

であり、ほとんどBELUGAと同じです。 しかし、何も症状が変わりません。 画面は乱れたままです。 RAS2の入力をはずすと元に戻ります。 すなわち、ちらついた状態になります。 何で...???

もう降参。 ダレカタスケテ...;-(

ちなみに表示の様子。

P1000816.JPG

ちらついてるのが分かるでしょうか?


少しづつ原因を特定しようと頑張っています。 今のところ、明らかになっているのは次のような動きです。

  • 起動時、本体は32kBとして認識している。これは、BIOSで以下のようなロジックを実行することで判定している。
    ld      hl, 0xbfff
    ld      b,(hl)
    ld      (hl),a
    cp      (hl)
    
    ちなみに0xbfffは拡張RAMの最終アドレス。
  • スクリーン1(0x8000-0x83ff)およびスクリーン4(0xa000-0xb9ff)の表示は同じように乱れている。
  • スクリーン1のアトリビュートエリア(0x8000-0x81ff)やテキストエリア(0x8200-0x83ff)をpeekすると内容は正しい。
  • スクリーン2(内蔵RAM)を表示した状態でプログラムを入力したり実行したりできる。すなわち、0x8400からのメモリを正しくアクセスしている。
  • スクリーン1または4でキー入力をするとかなりの確率でリブートしてしまう。
  • screen 4,4を実行するとかなりの確率でリブートしてしまう。

ここから言えることは、以下のようなことです。

  • SRAMはほぼ正常に動作している。
  • VDGからのDMAで正しいデータを読めていない。現在はDRD(拡張コネクタ3番ピン)が0になるときにSRAMからのCSおよびOEをアサートしてますが、それでは足りない?
  • VRAMに書き込みをするとリブートしてしまう。

DMA関連の不具合は、ハードウェアに起因した現象なので、ちょっと困り果てています。

もともと、PC-6001の拡張RAMはDynamic RAMを想定しているので、ひょっとすると、DRDのみでSRAMをリードにしてしまうのが原因なのかも。 DRDのタイミングのみでSRAMをアクティベートしていることで、何か他の信号との関係でデータバスがコンフリクトしていることが考えられます。 もしそうだとすると、RAS and/or CASのアサートも見なければいけないのかもしれません。

そうなると、さらにCPLDに入力しなければならない信号が増えてしまいますね...。

Discrete logicに外出しにするにしても、DRDとRDはand(7408)で、RAS/CASはor(7432)なので、ひとつのチップで処理できません。 まぁ、74139を使ってデコードするという手はありますが、手元にあったかな?


続きです。 ページ1(0x8000-0x83ff)およびページ4(0xa000-0xb9ff)の画面は乱れるものの、なんとなく動いていたSDアダプタですが。 たまに入力を受け付けなくなって暴走するなど、やはり不安定です。

どこか結線の問題だと思っているのですが、正直調べるのはかなりの苦行です。 回路図と睨めっこしながらハーフピッチのコネクタにショートや断線がないかどうか一本ずつ調べる必要があります。

なまじジャンパが結構這っているので、それも含めて丁寧に追いかけなければいけません。 ジャンパはUEWなので、断線ならまだしも結線の際に熱でどこかショートしてたとしたら、発見するのは相当厄介です。

これまでいろいろ作って一番経験したデータバスの誤配線はなさそうです。

また意外にも、パッドとラインの間の隙間が非常に狭いところなどには今のところショートなどは見つかっていません。

CPLDやAVRのプログラミングを行うのも特に問題は起きていないので、電源周りも大丈夫そうです。

う~ん、やはり地道にやっていくしかないのか...。


続きです。

回路に一箇所誤接続がありました。 データバスの部分でしたので、動かなかったのも納得です。

とりあえず似非ROMは後回しで、外したままですが、早速直して動かしてみると...画面が真っ白。

よく調べてみると、キーを受け付けますし、プログラムを入力したり実行したりできます。 プログラムを入れて0x8400近辺のアドレスをpeekすると、ちゃんと入っているのです。 ところが、スクリーン1と4が真っ白で、2と3はちゃんと出力されます。

それで気づいたのですが、6847からのDMAって、MREQまたはRDを使っていない?!

またしてもオマエカー!! VDG!!

これは気づきませんでした。 ええと、6847からのリード要求はコネクタ3番かな? 唯一残っているCPLDに入力して、CSのロジックを変えてみました。


...動かない。

よく考えてみたら、SRAMのRDがアクティベートしていないようなのですから、いくらCSをいじったところで読み出しができるわけがありません。 ということは、現在拡張コネクタからダイレクトに入力してしまっているSRAMのOE信号自体に細工をする必要があるということです。

たったAND1個ですよ。 でも、CPLDのI/Oがたった1本(SRAM OE用出力)だけ足りない...。 そのために08をつけるのは馬鹿馬鹿しいし、パターンもありません。


「こ...こうなったら、醜くてイヤだが、大猿に変身してアドレス線を1本削ってぶっつぶしてやる......!!」


で、A4を削ってやってみました。 白い画面ではなくなりましたが、ページ1と4が乱れまくっています。 ちなみに、以下のようなロジックです。

  OE <= RD and DRD;

  process (MREQ, Address15, Address14, INIT, WR, DRD)
  begin
    if DRD = '0' then
      CS <= '0';
    elsif MREQ = '0' and Address15 = '0' and Address14 = '1' then
      if INIT = '1' or WR = '0' then
        CS <= '0';
      else
        CS <= '1';
      end if;
    elsif MREQ = '0' and Address15 = '1' and Address14 = '0' then
      CS <= '0';
    else
      CS <= '1';
    end if;
  end process;

DRDは拡張コネクタ3番、OEはSRAMへ行っています。 もう、DRDがアクティベートされたら無条件でSRAM READにしている感じです。

でも、ちゃんと動きません。 う~~ん、あと何が足りないんだ??


続き。SDアダプタですが、まだ動いていません。

tiny2313をつけた状態で電源をつけると暴走しているので、データバスがコンフリクトしているのではないかと思います。 tiny2313はROM代わりですので、とりあえず外してしまえば単なる拡張RAMカードとして機能するはずなのですが、外すと何も起こらず普通に起動し、内蔵の16kBしか認識されていません。

というわけで、CPLDがうまく動いていないのではないかと思います。

たいしたロジックを入れているわけではないし、ISEではフィッティング含めエラーも出ません。 Timing constraintsは何もかけていないのでwarningが出ますが、たいした問題ではないでしょう。

ロジアナがあるとはいえ、回路上で実動作を確かめるのはとても大変です。 そのため、Behaviour modelをベースにシミュレーションをしているのですが、今のところ特に問題らしいところも発見されていません。

とりあえず今のソースを貼り付けておきます。

SDDecoder.vhd

拡張バスからの信号は、アドレス線、データ線とRDおよびWRは直接SRAMに接続し、CSのみ次のようにCPLDでデコードしています。

  process (MREQ, Address15, Address14, INIT, WR)
  begin
    if MREQ = '0' and Address15 = '0' and Address14 = '1' then
      if INIT = '1' or WR = '0' then
        CS <= '0';
      else
        CS <= '1';
      end if;
    elsif MREQ = '0' and Address15 = '1' and Address14 = '0' then
      CS <= '0';
    else
      CS <= '1';
    end if;
  end process;
  • 初期化時(AVRから^INITが入る)の0x4000-0x7fffへの読み込みはインアクティブ
  • 初期化時の0x4000-0x7fffへの書き込みはアクティブ
  • 0x8000-0xbfffへのアクセスは常にアクティブ

ひょっとしてCPLDにクロック供給とかいるのかなぁ。 クロックとして使われるピンも普通のI/Oにしちゃってますが。

あ、それともSRAMにCS以外の信号線を垂れ流し続けるのって無謀? データシート上ではCSさえインアクティブにしておけばデータバスはHigh-Zになって楽なのでこんな感じにしたんですが。


先週基板ができたので、今日はジャンパを通しました。 およそ30本。 面倒ですが、全部手配線に比べたら圧倒的に楽です。 ちなみにUEWを使って半田面に配線したので、部品面は未だにスッカスカです。 ISP用に背の高いコネクタをつけたくらい。

P1000708.jpg

プログラミングはCPLD、tiny2313、mega88の3種類に必要です。 デバイスへの書き込みはこれだけのために用意してある古いノートパソコンを使います。 タダでもらったVAIOで、シリアル&パラレルポートを持っています。

なおこれ、液晶のヒンジが折れています。 ありあわせのネジで直しても直しても折れてしまうので、スピーカーに寄りかかった状態で使っています。

P1000706.jpg

CPLDは特に問題もなく終了。

tiny2313が、どうしてもDevice connection failedでうまくいかない...。 RS-232Cを疑ったり書き込みデバイスを変えたり、いろいろしてもなかなか見えず、仕方ないので試しに別のチップでやってみたら...できた。

見事にババ引いちゃったみたいです。 その間、電源取りに使っていたFT245Rのボードを壊してしまったみたいです(泣)。

mega88のほうは、まだプログラムのほうが古いままで、新しいアダプタに対応していません。

明日の引越し荷物到着の準備をしなきゃいけないし、今日はもう疲れたので、こちらは明日以降にしましょう...。

それでも、面倒なハードウェア部分はおおよそ終わったので一段落かな。


ここんところ、SourceForgeへのCVS接続がうまく動かない障害にずっと悩まされていて放置プレイだったのですが、久しぶりにContikiのメンテナンスをはじめてみました。 一応私は、Z80全般およびPC-6001部分のソースが担当になっています。

ていうか、えらいコードが変わっていて、ついていけない...。 まぁ、メーリングリストもちゃんと読んでいるわけではないんですが。

しかし、そんなことより問題は、SDCCがバージョンアップ(2.9.0)したことにより、今までなら通っていたと思われるコードが通らなくなってしまったことでしょう。 なんか、開発時間の半分以上はSDCCのおかしな挙動の解析とその回避に費やしているような。

最初に動くようになるまでは楽しいのですが、こういうメンテナンス作業って苦痛なんですよね...。


P6絡みののりさんが、ROM乗せかえ(実際にはエミュレータ上のBIOSイメージ入れ替え)によるフリーのPC-6001実行環境を開発しています。

私も以前、実機のROMを外して別のROMやRAMに変えられるのではないかと妄想していましたが、それをエミュレータ上でやってしまおうということですね。

現在のエミュレータでも、ROMイメージファイルの入れ替えはできますが、RAMにできたらいいなぁ。 そうしたら、SDカードから似非ROM(別に本物のROMでもよいが)で起動して、CP/MやらUN*Xもどきやらを作れそう。 もちろんContikiも動かしやすくなります。

おそらく実機に実装されているROMを外してしまえば、拡張カードに積んだROMやSRAMが動くと思うので、あながち夢物語でもないような気がしています。 PC-6001mkII以降の場合は最初から64kB RAMが実装されているので、そちらでやったほうが早いかな? でも中身しらないんだよな~。

などと思っていたら無性にOSのソースが読みたくなって、ELKSやらMINIXやらのブートアップソースを眺めちゃったりしてます。 久々にx86のアセンブリソースを見ました。 これでも昔はPC-9801(初代)内蔵のワンラインアセンブラでゲーム作ったりしてたんですョ。

Z80ベースのOSなら「まずCP/Mを読め!」と言われそうですが、Intelニーモニックのオールアセンブリなので、読むのが面倒なこと、もともと商用ライセンスのものであること、設計が古いということで、ちょっとスキップです。:-p

x86(というかIBM PCおよび互換機)ではBIOSがソフトウェア割込み(INT 13hなど)によって基本機能を提供していますが、Z80系だとRSTを使うのがいいのでしょうね。 CP/Mのように常に0番地をRAMにしろというのも微妙ですが、64kB空間を確保してRSTベクタを活用すれば、他機種への移植性も高まるでしょう。 さすがに割り込みモード0を使った機種はないと思いたい...。

BIOSといえば、LinuxなどではROM BIOSに依存するのは最初のブートアップのときだけです。 最初の一部分はどうしてもBIOSに依存しなければならないのですが、そのせいで逆にブートアップシーケンスがとてつもなく面倒なことになっています。 Linuxカーネルのbootsect.Sやsetup.Sを見ると苦労の跡がしのばれます。

SDカードアダプタへのI/Oがコールドスタートのできるだけ直後に開始できれば、機種依存のROM BIOSを可能な限り小さくできます。 そうすれば、読み込むカーネルが機種依存になるとしても、ただのFAT上のファイルなので移植やメンテナンスが多少は楽になるかもしれません。

今のSDカードアダプタを動かしたら、試してみたいものです。


SDカードアダプタ、まだやってます。 先日失敗した感光基板作成、日本で基板を買って戻ってきたので、再挑戦です。

今回は出力11Wの蛍光灯を使いました。基板との距離は10cmちょっとくらいです。 10分ごとに蛍光灯の位置をずらしつつ、感光時間は1時間弱行いました。

感光の様子。

P1000696.JPG

現像の結果。 一部ベタ部分で基板にインクがついてしまったところは感光剤がはがれてしまいましたが、おおよそ良好な結果になっています。

P1000697.JPG

感光剤がはがれた部分はレジストペンで修正をかけて、15分エッチング。 エッチング液はおよそ40~45度。

今回はきれいにできました。

穴あけは、基本が0.6mm、ICソケット(1箇所)および太目の線を通す部分は0.8mm、レギュレータは1.0mmです。

んで、部品実装を開始しました。

部品面のエッジコネクタをどうするのか、いまさらになって問題になりました。 EジスPenを使うつもりだったのですが、摩擦に弱いんですよね。

仕方ないので、例により(?)ファミコンカセットのジャンクから毟り取ったコネクタを接続。 必要部分だけとはいえ、40本近くの配線量になりました。 結構面倒だしやりにくい。 しかも何度も再利用しているのもあって、出来が汚い...。

で、今はこんな感じです。

P1000703.JPG P1000704.JPG

ボードが大きくてスカスカに見えるかもしれませんが、片面基板のため、配線は右側の銀色の部分を除いてかなりびっしりです。 配線間隔は50mil(1.27mm)です。

そのため、100mm x 150mmの基板を使いました。 75mm x 100mm両面でもいけるかと思ってアートワークしてみていますが、せっかく両面なのだからジャンパを飛ばさずにと思うとかなり難しいです。

主要な部品はつけ終わりましたが、今回の片面基板バージョンではジャンパも結構飛ばさなければいけないので、のんびりやります。