たまりば

  パソコン・インターネット パソコン・インターネット  三鷹市 三鷹市

Windows10にフォント消されたけどまあ理解できる
2017年04月16日 17:31

Windows8から10にアップグレードして使っていたマシンで、先日(2016/10/12)いくつかのフォントが消えていることに気づいた。

調べ物をしていて韓国語の字体を見たくなり、文字コード表でフォントをDotumにしようとすると、選択肢に無い。
Gulimでもいいかと思って探すとこれも無い。BatangもGungsuhも無い。
有効化していなかったかと思いfontsフォルダを見ると、無効ではなく存在しない。
この辺で焦りだす。
他の言語のフォントも怪しいと思い調べてみるとMingLiUもSimHeiも無い。なんだこれは。
ここまではWindows付属のフォントだがOffice付属のNew Gulimは…? と見るとこれはある。
すると消えたのはWindows付属のフォントのみなのだろうか。

ググるとWindows10でMS明朝が無いという投稿が見つかった。→Windows10のフォントにMS明朝がありません
「設定→システム→アプリと機能→オプション機能の管理」に「日本語補助フォント」のオプションがあるようだ。見てみると他にも各言語の「補助フォント」があり、ここからGulimやSimHeiなどをインストールできた。

ここにきてやっと何が起こったのか理解できた。
Windows10になって、各言語のフォントに「補助フォント」という概念ができたようだ。
そして基本的なフォントはデフォルトで全言語のものがインストールされるが、補助フォントは使用言語のもののみがインストールされるようになったのだろう。
その判断はまあ問題ないだろう。対応言語も多くなりフォントの容量も馬鹿にならない。

ここで問題になるのが旧OSからのアップグレードだ。
旧Windowsでは非使用言語の補助フォント相当も全て入っていたが、Windows10の流儀に合わせるためには存在してはいけない。だから消すと。
理解はできる。
消すにあたって、どのフォントを使っているかは判断のしようがないから、すべて消すことになる。
理解はできる。

理解はできるが、普通に使っていたファイルが消えるとなると他に何が消されたか分からないのが怖くてたまらない。
あるはずのファイルが見つからないという経験も何度かあった。まず間違いなく気のせいだろうが、Microsoftは自分の中でもうだいぶ信用を失っているので、本当に消されてもおかしくないと思ってしまう。

他にも、.NET2.0がWindows10へのアップデートに伴って消えるという問題もあるらしい。ああ嫌だ。
[note] Win10アップグレード後のVisual Studio 2005起動時エラーの修正について  

  • ゼルダの伝説ブレスオブザワイルドプレイ日記(ネタバレ有)
    2017年03月12日 18:13

    1週間ちょっとプレイしてみて(というか週末だけなので累計2日3日くらい)これは感想を書き留めておきたいという気分になったので書き始める。
    主に自分が後で読み返して懐かしむために書いているが、本作は多様なルートで攻略できることが特徴のようなので、他人が変なルートをとっているを見るのも面白いかもしれない。ということで公開する。ただあまり人に読ませる文体でない部分もある。
    ネタバレについて。積極的にネタバレをしたいわけではないが、感想を書く時点ですなわちネタバレである。本作を十分にクリアした、あるいは未来永劫プレイしないと確信が持てる人以外が読むことは強く非推奨する。

    2017/04/02 エンディング到達。総プレイ時間は本体の記録によれば60:14であった。
    とりあえず日記はここまででいいかな。もしかしたらまた何か書き足したくなるかもしれないけど。→書き足したくなった。
    2017/07/24 最終更新

    ところで、本文にも書いたが、本作は(トワイライトプリンセスの時のようなことはなく)Switch版の方が全面的に優れている。
    あまり無いと思うがWiiU版とSwitch版のどちらにしようか迷っている人がここを見た時のために情報をまとめておこう。
    ・Switch版の方がTV出力時の解像度が高い。Switch本体とWiiU GamePadの比較でもSwitchの方が解像度が高い。
    ・Switch版の方が安定してフレームレートを保てる。
    ・Switch版の方が音質が良い。
    ・WiiU版は、GamePadを一切使わない。 ←これを事前に知っていたら自分はSwitch版を買っただろう
    ・Switch版は言語切替えが可能。 ←同上
    (2017/05/22追記: WiiU版も音声は切替え可能になった。文字も欲しい。)

    折角なのでWiiU版でしか見られない画面をここに載せておこう。
    タッチするとGamePadであそべます画面  続きを読む

  • JPEG圧縮を繰り返しても際限なく劣化するわけではない
    2017年02月10日 01:47

    ビデオテープのダビングやコピー機でのコピーは世代を重ねるごとに劣化が蓄積する。
    同様にJPEG画像も、保存→開く→保存…と繰り返すと、
    JPEG劣化_オリジナル
    オリジナル
    JPEG劣化_ずらし_1世代目
    保存1回目
    JPEG劣化_ずらし_9世代目
    保存9回目
    JPEG劣化_ずらし_17世代目
    保存17回目
    JPEG劣化_ずらし_49世代目
    保存49回目
    JPEG劣化_ずらし_97世代目
    保存97回目
    JPEG劣化_ずらし_201世代目
    保存201回目
    JPEG劣化_ずらし_497世代目
    保存497回目
    JPEG劣化_ずらし_1001世代目
    保存1001回目
    JPEG劣化_ずらし_2001世代目
    保存2001回目
    JPEG劣化_ずらし_5001世代目
    保存5001回目
    JPEG劣化_ずらし_10001世代目
    保存10001回目
    といった具合に劣化が蓄積して画質が際限なく落ちていき、最後には一面のノイズになってしまう…

    …と誤った認識を持っている人が多い。

    実際に試してみよう。使用するソフトは定番のImageMagick。
    magick convert -sampling-factor 1x1 -quality 95 orig.png gen1.jpg
    magick convert -sampling-factor 1x1 -quality 95 gen1.jpg gen2.jpg
    magick convert -sampling-factor 1x1 -quality 95 gen2.jpg gen3.jpg
    このようなバッチファイルをExcelとテキストエディタで作成し、実行する。
    結果は次のとおり。
    JPEG劣化_オリジナル
    オリジナル
    JPEG劣化_1世代目
    保存1回目
    JPEG劣化_17世代目
    保存17回目

    以上だ。
    3000回くらい回していたのだが、確認してみると18回目で既に前回と同一の画像が出力されていた。だいぶ時間を無駄にした。
    このように、繰り返し保存による劣化は早々に止まることが分かる。
    なお今回は1種類に収束したが、以前試した時は3種類のローテーションになったこともあった。
    また、見て分かる(分からない)とおり、1回目と17回目で差はほとんど無い。
    念のため差分をとってみよう。
    JPEG劣化_差分_1-17
    全く見えないので64倍に強調したものも置いておく。
    JPEG劣化_差分_1-17(×64)

    そもそも非可逆圧縮の原理は、元データを少々変えて「圧縮しやすいデータ」を作り、それを可逆圧縮するものと解釈できる。
    よって一度非可逆圧縮したデータを展開したデータは、既に「圧縮しやすいデータ」になっているため、同じ設定で圧縮すれば完全に可逆圧縮になってもおかしくない。
    むしろ17回まで劣化が続くことの方が不思議といえる。
    ではなぜかだが、JPEGの圧縮の根幹である離散コサイン変換(DCT)は本来は可逆なのだが、実際には有限の精度で計算するために丸め誤差が発生する。おそらくこれがJPEG再圧縮が不可逆な原因だと思う。
    またどうもJPEGの仕様はあまり厳密でないようで、エンコードでは演算の精度をソフトの自由で選べたり、デコードもソフトによって結果が違ったりする。これも一因かもしれない。
    (2/11追記)RGB→YUVの変換も丸め誤差が発生するので一因かもしれない。

    さて次にパラメータを少し変えてみる。
    JPEG劣化_オリジナル
    オリジナル
    JPEG劣化_サンプリング2×2_1世代目
    1回目
    JPEG劣化_サンプリング2×2_10世代目
    10回目
    JPEG劣化_サンプリング2×2_20世代目
    20回目
    JPEG劣化_サンプリング2×2_50世代目
    50回目
    JPEG劣化_サンプリング2×2_103世代目
    103回目

    今度は劣化が103回目まで続く。劣化の度合いも目に見えて分かる。色が褪せていて、特に赤が大幅にくすんでしまっている。
    差分をとってみる。
    JPEG劣化_サンプリング2×2_差分_1-103
    少し見にくいので4倍に強調しておこう。
    JPEG劣化_サンプリング2×2_差分_1-103(×4)
    闇夜に光る眼のようで可愛い。

    何を変えたかというと、カラーサブサンプリングだ。
    カラーサブサンプリングは、クロマサブサンプリングや色成分間引きと呼ばれたり、単にサンプリングやサンプリング比という名の設定項目で設定したりする。名前が定まっておらず面倒な概念だ。
    先の17回で劣化が止まったものは、カラーサブサンプリングがOff、別の言い方をするとサンプリングが1x1や4:4:4と呼ばれるものだ。この設定では輝度成分と色成分を元の解像度のまま処理する。この時、画像は8×8のブロックごとに処理され、隣のブロックとの間で影響を及ぼすことはない。
    一方103回の方は、カラーサブサンプリングがOn、サンプリングが2x2や4:2:0と呼ばれる設定であり、輝度成分は元解像度で、色成分は縦横1/2に縮小してから処理をする。
    この縮小で単純に2×2ピクセルを平均するのであれば16×16のブロック内に影響が留まるだろうが、どうもそうではなく線形補間か何かをされているようで、ドットの色が16×16pxの境界を越えてにじむ現象が見られる。これにより隣のブロックの色が圧縮に影響し、次回は隣の隣のブロックにまで波及し、と際限なく影響を与え合う。厳密なことは分からないがこれが劣化が長く続く理由ではないかと思う。

    なので劣化が蓄積するというのは、カラーサブサンプリングOnの設定においてはある程度正しい。
    ただしそれにしても際限なく劣化するということはないし、JPEGが全てそのように劣化するわけでもないことは上で示したとおりだ。

    さてもうひとつ、冒頭の例のように完全なノイズにまで際限なく劣化させるにはどうすればよいだろう。劣化しそうな方法をいろいろ試してみた。
    まず圧縮率を毎回変えたら量子化の閾値が変わることで劣化が続くのではないかと考えたのだが、駄目であった。1万回繰り返してもほぼ劣化が見えなかった。(同じ画像が続くことは無かったので何パターンかのローテーションになっていたようだ)
    次に90度回転を試したがこれも同様であった。今回使ったJPEGの量子化行列は縦と横で対称でないのでそれによるゆらぎを期待したのだが…。
    そこで毎回画像の位置をずらしてみることにした。7回右下へ1pxずらしたあと、1回左上に7pxずらして戻すの繰り返し。これは見事に成功、これでできたのが冒頭の画像だ。
    なぜこれが上手くいくかは、正確なことは分からないが、特定のドットに注目するとそのドットは8×8のブロック内で位置が毎回変わるようになっており、これで誤差が波及し続けるのが一因だろう。
    サンプリング2x2の時は止まってしまったのでそれ以外に何かあるのだろうが、よく分からない。何か誤差が発振するような機構があるのだろうか…。
    なお90度回転も、画像サイズが8×8の倍数でない場合はずらすのと同じことになる。

    以上、まとめると
    ・単純に同じ設定で圧縮を繰り返すだけでは際限なく劣化することはない。
    ・ただしサンプリングを落とした場合は少々劣化が続く。
    ・設定を変えても際限なく劣化はしてくれない。
    ・位置の移動を伴うと際限なく劣化した。

    JPEGの劣化は奥が深い。  

  • I2C液晶が動かない理由が分かった
    2017年01月31日 01:54

    以前、秋月で超小型のI2Cキャラクタ液晶(I2C接続小型キャラクタLCDモジュール 8x2行)を買い、PIC10F200で色々と表示していた。
    ある時思いついたネタを実装しようとしたところ10F200ではROMが足りなかったので、石をPIC12F510に変えることにした。
    移植作業はわりと楽であった。ADコンバータ関連を無効化すればあとはだいたい似たようなものである。
    しかし動かない。
    しかも不思議な事に信号線にLEDやテスターをつなぐと動く。つまり原因は単純なプログラムのミスではなくアナログ的な微妙な差異によるもののようだ。
    色々考えたが分からないのでその時はあきらめた。一昨年の5月ころだ。

    (昨年の4月に)その原因が判明したので顛末をここに書き留める。何かの参考になれば幸いだ。

    まず最初に言っておくと、このプログラムで出していた信号は正常なI2Cではない。
    第一に、本来I2CはLowとプルアップで駆動するものをHighとLowで駆動している。プログラムの簡略化と高速化の為だ。
    第二に、クロック立ち下がりからデータ変化の時間、tHD:DATはデータシートによれば最小0・最大0.9μs(後述)のところ、最小ギリギリの0にしている。10F200で可能な間隔が1μsの為だ。またデータシートによればこれでも300nsの余裕があるように読める(後述)。

    もっとまともな信号にすれば動くかもしれなかったが、それは解決にならない。
    問題は動かない事ではなく、動かない理由が分からない事である。
    規格外や規格ギリギリではあるものの、これでも動くはずだと考えてやっているのだし、実際10F200ではほぼ確実に動くのである。
    この状態で適当に変更して動くようになったとしても本当にその変更が正しかったのか分からない。何か重大な思い違いがあったら危険だ。
    またなにより、何が問題なのか分からないままというのは気持ち悪い。

    移植して動かなかった時から(覚えている限り)時系列に沿って状況を書く。

    MPLABのシミュレータで見た波形は全く同じ。
    怪しいのは実際に信号が出ているかだ。TRISの設定を間違ったり、間違って別のピンにつないでいたりすることはしょっちゅうだ。
    なので信号が出ているかどうかを確認するため、信号線に青LEDをつないだ。(LEDをつなぐと点滅具合で色々分かる。青なのは電源が電池2本の時抵抗を入れなくても大丈夫で便利だからだ)
    すると…不思議なことにほぼ確実に動作するようになった。
    最初はデータとクロック両方に付けていたが、データ線だけでも動作する。
    赤LED(+抵抗)だと駄目。電圧の問題かと思い赤LED+ダイオード1、2本で試すも駄目。また、データ線にテスターを当てるとほぼ確実に動作する。

    この時点で問題はアナログ的なものと分かった。

    アナログ的な仕様に何か違いがあるのではないかとデータシートを見る。ほとんど同じだったが、1つだけ、デバイスリセットタイマ(DRT)の時間が異なっていた。早速その分の待ちを入れてみる。
    …が、変わらず。

    もはやこれはオシロスコープを買うしかない。
    2万円の機種と迷ったが3万円のものを購入。オシロスコープで12F510で動く時(青LED付き)と動かない時を確認すると信号に違いが!
    …と思ったがよく見るとそれはACKが返っていないだけであった。
    分かったことは、最初の1バイト(アドレス)から既にACKが返っていないということだけ。
    あとはノイズだが、電源投入からI2C送信までの間に目立ったノイズは無く、電源投入時のノイズはわりと酷いがどちらも同様に酷い。

    そして10F200と12F510を比較してみると、I2C信号を送信するところは一切違いが見当たらないが、リセット直後の挙動が違っていた。
    調べてみると、デバイスリセットタイマ相当の待ちを入れた時、待ちの後にHigh-ZからHighにするつもりのところを間違って待ちの前にHighにしてしまっていた。
    …しかしこれを直しても変わらず。
    もしかしてデバイスリセットタイマ中とプログラムが走っている時では何か違いがあるのだろうか。そうなると12F510で動かすのは不可能ということに。

    この辺でできることも無くなり諦めてしばらく経った。

    ある日、なんとなくI2Cについて考えていて思った。なぜtHD:DATに上限があるのだろう。
    液晶コントローラのデータシートに上限があるように書かれていたので不審に思いながらも従っていたのだが、やはりおかしい。
    I2C液晶データシート
    I2Cのデータシートを見ると、違う書かれ方をしている。(なお後で知ったが古いデータシートでは上限0.9μsになっていた)
    I2Cデータシート
    上限はなし、その上で注釈として、
    The maximum tHD:DAT could be 3.45 μs and 0.9 μs for Standard-mode and Fast-mode, but must be less than the maximum of tVD:DAT or tVD:ACK by a transition time.
    最大のtHD:DATはスタンダードモードで3.45μs、ファースト(fast)モードで0.9μ秒になりうるが、tVD:DATまたはtVD:ACKの最大値よりトランジション時間だけ短くなくてはならない。
    This maximum must only be met if the device does not stretch the LOW period (tLOW) of the SCL signal.
    この最大値はデバイスがSCL信号のLOW期間(tLOW)をストレッチしないときのみ満たす必要がある。
    If the clock stretches the SCL, the data must be valid by the set-up time before it releases the clock.
    もしクロックがSCLをストレッチするなら(訳注: 意味が分からない。SCLはクロックだ)、データはそれ(訳注: どれ? クロック?)がクロックを解放する前にセットアップ時間だけ有効でなければならない。
    CBUSとの兼ね合いかとも思って調べようともしていたが、どうも死んだ規格らしく情報がない。その辺で当時は諦めていた気がする。
    しかしさらに考えてやっと分かった。この0.9μsという上限の値は、スレーブに対する制限なのだ。
    「マスターがクロックを生成しスレーブがデータを送信するとき、マスターがクロックをLowにしている間にスレーブはデータを変化させなければならない」という当たり前の制限について言っているだけだ。

    クロックがLowの間にデータを変化させるには、データのホールド時間(tHD:DAT)・データの立ち上がり時間(tr)または立ち下がり時間(tf)・データのセットアップ時間(tSU:DAT)の和がクロックのLow期間(tLOW)より短くなければならない。
    I2Cタイミング関係
    ファーストモードではクロックのLow期間の最小値が1.3μs、立ち上がり時間の最大値が300ns、データセットアップ時間の最小値が100nsなので、
    1.3-0.3-0.1=0.9
    となり注記の値に一致する。

    スタンダードモードでも同様に
    4.7-1-0.25=3.45
    となる。

    今回データ送信はマスター側からのみ行うため、スレーブの制限は無関係だ。よって最大0.9μsは無視してもっと長い時間とれば余裕を持った通信ができる。

    解決方法は見えた。あとは原因の方だ。10F200と12F510、LEDやテスタリードを付けた12F510で何が違うのか。

    もう一度オシロで波形を見てみよう。
    ここまでI2Cの通信内容が分かる程度の縮尺で見ていたのだが、限界までサンプリング速度を上げて拡大して見てみる。すると波形が明らかに違っていた!
    I2C_10F200/12F510比較
    10F200はシンクが強いのか立ち下がりが速い。
    これによって、SCK・SDAを同時に操作してもSCKの立ち下がりの後にSDAの立ち上がりが来てくれていたようなのだ。それが12F510では逆になっている。
    この違いで動作が分かれていたのだろう。
    なおこの3万円のオシロのサンプリング速度は250Msps(2ch時)、帯域は60MHz。迷っていた2万円の方の機種は100Msps・25MHzである。
    1/(60MHz)=17ns、1/(25MHz)=40nsであり、25MHzの帯域で今回の波形の違いを捉えられたかはかなり怪しい。
    高い方を選んで良かった。

    さて最後に、冒頭で言った300nsの余裕の件だ。

    tHD:DATの下限について、以下のように注釈がある。バージョンによって言い回しが少々変わっているが内容は同じようだ。
    ・A device must internally provide a hold time of at least 300 ns for the SDA signal (referred to the VIHmin of the SCL signal) to bridge the undefined region of the falling edge of SCL.
    ・A device must internally provide a hold time of at least 300 ns for the SDA signal (with respect to the VIH(min) of the SCL signal) to bridge the undefined region of the falling edge of SCL.
    この文章も微妙に意味が取れないのだが、精一杯の訳が以下だ。
    「SCLの立ち下がりの不定区間を橋渡しするため、デバイスはSDA信号に対して内部的に最低300nsのホールド時間を(SCL信号のVIH(min)を基準に)用意しなければならない。」
    internally・reffered・with respect to・bridgeあたりの意味がよく分からない。
    なお誤訳の可能性を考えてオランダ語の原文があるかと探したのだがどうやら英語が原文のようである。

    これを自分はこう理解した。

    受信側はSDA線の立ち下がりから300ns間内部的にHighと扱う。
    よってSCKよりSDAが(300ns-立ち下がり時間)だけ早くてもよい。
    立ち下がり時間の最大が300nsなので、都合余裕は0。

    これは12F510で動作しない現状と食い違うが、上記の文章の解釈は他に思いつかない。
    (「送信側がSDA線を300ns遅らせて駆動しなければならない」という説も見かけたが、それではinternallyでないのと、それはtHD:DATの下限が300nsと書けばよいことなので、別に注釈として書かれている説明がつかない。)
    自分の解釈が間違っているのか、このデバイスが仕様に従っていないのか分からない。
    まあどちらにせよ、諸悪の根源はI2Cの仕様書が分かりづらいせいだ。マスターの条件とスレーブの条件が混ざって書かれているし、0.9μsだの300nsだのと注釈で変な条件を追加するし、その注釈は文章の意味が取れない。

    とそんなわけで不可解な点は残ったものの、まとめると、

    ・最大値が0.9μsだと思っていたが制限は無かった。
    ・最小値が0だが300nsの余裕があると思っていたが、文の解釈はよく分からず、現に余裕は無かった。
    ・石を変えて動かなくなったのは立ち下がりの速さの差のせい。

    tHD:DATを長くしたところ、安定して動くようになった。
    12F510でI2C液晶が動いた
    (なお表示は温度計を作ろうとしていた時のダミー表示)  

  • ゲームボーイの吸い出し機を作った (後編)
    2017年01月16日 22:44

    前編の続き。プログラム側について。

    まずは単純に読むことを試みる。
    手持ちの中でバンク切り替えなし(32kB)のソフトとしてDr.マリオを選択。

    バンク切り替えが無ければアドレスを出してデータを読むだけ。
    …とはいえCLKとかCSとかRDとかどう制御すればいいのか。
    GBのカートリッジの仕様くらいいくらでも見つかると思っていたのだが、ROMの読み出し方法は常識なのか、細かい解説が意外と見つからない。
    結局、分かってみると単純で、
    /RDがLにアサートされている間、アドレスピンで指定されたアドレスのデータが、データピンに出る
    というだけのことだった。
    つまり読み出すには、/RDをLにアサートしたままアドレスを順次変え、データピンを読むだけでよい。
    これが分かるまでに/RDをH/L切り替えてしていた。
    あと/CSはSRAMを読む時アサートするものだった。

    プログラミング自体もなんだかんだで苦労した。
    やはり合っているか分からない操作を正しく組めているか分からない機械にプログラムするのは疑心暗鬼に陥ってだいぶ精神を消耗する。
    まずシリアル通信するところからしてうまくいかない。
    シリアルポートが全く反応しなくて焦った挙句Windows10へアップグレードした時にケーブル類全部抜いてたのを戻してなかっただけだったりもした。
    何か出るようになったと思えば文字化けしている。これはどうもTeraTermのバグかWindows10との相性のようで、最新版を使ったら正常であった。
    新しいPICを使う際には毎回のようにGPIO以外の機能を切っていなくて問題が起こるのだが、今回もまんまとその罠にはまった。
    ADコンバータとコンパレータを切ったまでは良かったのだが、それで読もうとしても何も読めない(FFが読める)。
    ポートのレジスタを直接インクリメントしてたのがまずかったかと思い、別の変数をインクリメントしてそれを出力するようにしたところ何かは読めるようになったが、全体にわたりほぼ確実に8バイトづつ同じ値が取れる。
    つまりアドレスの下3bitが何かおかしい。そのピンを調べると、LCDドライバの電圧生成機能がデフォルトでONであった。
    ということはポートのレジスタを直接インクリメントすること自体は問題なく、最下位bitの書き込みが無視されていたせいでインクリメントできていなかったんだな。

    というわけでついにDr.マリオが読めた。
    Dr.マリオ

    次はバンク切り替え…の前に色々なソフトをバンク0だけ読んでみることにした。
    するとポケモンYellowやポケモンカードなど読めるものもあるが、ポケモンSilverが読めない。
    読めないというのは、ほぼ全てFFが返ってくる。ごく稀にFF以外のものが返ってくることもあるのがまた不可解である。
    FFでない箇所のパターンは規則的で、なにかありそうである。2進数で「xxxx xxx1 0000 000x」と「xx00 0110 0000 0001」、つまり0100, 0101, 0300, 0301,…と0601, 4601がFFでない。
    不要なはずのクロックだがMBCを積んでいることもあり何か変わるのではないかと入れてみる。当然変わらず。
    …散々悩んだ挙句、電圧不足であった。
    いつもPICを動かす時はEneloop2本(2.6V程度)を使っていて、使いやすい5V電源を持っていないこともあり、とりあえずそれでやっていたのだが、GBの電圧は5Vなので動かなくてなんの不思議も無いのであった。
    Dr.マリオを始めいくつかのソフトで(バンク0は)読めていたので発覚が遅れた。

    改めてバンク切り換えだ。
    バンクの少ない(最少の4バンク)ものとしてQIXを選択。
    バンク切り換えの手順はMBCによって少々違うが、基本的に特定のアドレスにデータを書き込むだけである。
    書き込むべきデータを入れていなかったり、PICのIOを入力のまま出力したつもりになっていたり、書き込むアドレスを間違ったりして手間取ったが、まあまあすんなりと読めた。
    QIX

    さて続いて本命のポケモンSilverだ。
    128バンクあるが、バンク切り換えのやり方は同じなので、単純に数が多いだけ。難しいことは何もない。
    しかしなぜか途中でデータが飛ぶ。読み取ったデータを見るとファイルサイズが想定より小さい。
    今までこのような大量のデータをシリアルで受信したことは無かった。シリアル通信の信頼性はこの程度なのだろうか。
    だがそれは想定の内。1バンクごとに目印を入れてあるのでどこで抜けたかは分かる。何度か読んで正常な部分を切り貼りすればよいだろう。
    …と思っていたのだが、不思議な事に常にエラーが出ている場所がある。
    バッファ切れを疑ってバッファ量を変えたりウェイトを入れたりしてもなんとなく変化はあるものの直らず。
    データの問題かと思いXOR 0x55したデータを送ってみると抜けの量はほぼ変わらず、抜けの位置が変わった。特定のデータが来ると問題が起こるのだろうか。
    速度を落としてみるとだいぶ改善した。抜けが6バンクまで減ったので試しに起動してみると、一応起動はした。
    ポケモンSilver_データ抜け1ポケモンSilver_データ抜け2
    このような分かりやすいバグった表示になるものなんだなあ。
    なお部屋に出口がないので進めなかった。その後もう1バンク正常に取れたのでそれと合わせると部屋から出られたがBGMが異常になったりする。
    しかしここで何度とってもほぼ同じ場所でエラーを起こす。
    やはり速度を落とすだけでは解決しない。特定のデータが問題という線で考えてみよう。
    改行の処理に時間が掛かっている可能性を考えてCRの後にウェイトを入れてみる。むしろ悪化。
    あとは…エスケープシーケンス。何らかのエスケープシーケンスが来るとそれの処理に時間がかかってデータを取りこぼすのではないか。
    ここでTeraTermを調べて、受信した文字をすべて表示するデバッグモードがあることを知る。
    デバッグモードで受信するようにしたところ、一切取りこぼさなくなった!
    ポケモンSilver
    後で調べたところ、制御シーケンスに「1B 63: 端末リセット」というものがあるらしい。
    つまりこのバイト列が来るとTeraTermがリセット動作を起こし、その間に来たデータを取りこぼしていたようだ。
    調べてみると「1B 63」は最後まで読めなかった5バンク中の3ヶ所にあった。残り2ヶ所やそれ以前のエラー箇所は分からないままだがたぶん他のエスケープシーケンスだろう。
    デバッグモード以外にエスケープシーケンスを無視する方法がないか調べたのだが、見つからなかった。
    人が読む文字列を出す時は改行は使いたいのだが、致し方ない。

    次に困ったのがX(エックス)だ。バンク切り替えができない。
    調べてみるとこれに使われているMBC2はバンク切り替え時に書き込むアドレスに制限があり、今まで使っていた0x2000では駄目だった。
    と0x2100に変えてみたが、やはりバンクは切り替わらない。
    そこで読み取れたバンク0のコードを見てみることにした。この中にバンク切り替えのコードがあるはずである。
    するとやはり0x2100に書き込んでいる。
    合っているのにおかしいなと思い更に調べると、バンク1に変更する時は0x2100だったのだが、バンク2では0x2101、バンク3では0x2102…と、バンクNに変更する時0x2100+(N-1)に書き込むようになっていた。
    1少ないのは書き込み後のインクリメントの関係だろう。ということでバンクNに変更する時は0x2100+Nに書き込むようにコードを書き換えてみると、見事読み取りに成功した。
    なんだろう。バスコンフリクトだろうか。ファミコンのMMCでバスコンフリクトを起こすものがあるという情報はあるが、GBで起こるというのは見たことがなかった。
    X(エックス)

    さて次はニンテンドウパワーのGBメモリの読み取りを試みている。
    これは複数のMBCの動作を再現する特殊なコントローラを積んでおり、普通のバンク切り換えとは異なるコマンドを入れる必要があるらしい。
    色々試しているのだがまだ一切反応がない。一番つらい時期だ。
    読み取りができたら、どうも書き込みも出来るらしいのでやりたい。自作ソフトを実機で動かすのは夢である。

    ただその前に、どうも読み取りが安定しないのでどうにかしたい。
    今まで読めていたソフトでも読めなくなったりしている。
    断線しかかっているとかだろうか…。