マシン語とか
最近の若いもんはマシン語をしらん、けしからん、みたいな話が盛り上がってますね。
そんな若くもないのですが(22歳)、中学のころにはWindows95があって、携帯電話を持っていて、高校生のころには既にADSLなどの高速回線を普通に使っていた、そんな世代の俺の考え。まぁ俺はプログラマでもなんでもないんだけど。
全体的な結論
全体的な結論を先に言うと、個人的にこういう原点回帰的な話というのはそんなに好きじゃない。もっと高次で活躍する人が増えてもいい、と思っているから。一人の人間の時間は有限で、それを高次レイヤにつぎ込んでもっとおもしろいことができるなら、そっちにつぎこめばいいんじゃないかな。俺はそれは全然アリ派。たとえば、音楽でいうと、DTMしかできないやつは音楽できる顔すんな、みたいなのが嫌い。DTMしかできなくてもいい曲かく人なんていっぱいいるし、それでいいと思う。なんていうか、努力とかよりも、感性にあこがれるタイプだからかな。上のレイヤからはいっても、きっと基礎を固めてちゃんとやりたい、それが必要だ、と思えば人は勉強する。だからあえて言うこと(必要だと言い切ること)でもないんじゃないかなあ。現に、だいたいコンピュータ技術者というものは最終的に下のレイヤへ下がっていく人が多いですよね。
マシン語とかについて
きっと議論を呼んでいるのは「絶対必要」みたいに断定してしまったからで、知っていればこんないいことがあるんだよ、という感じならみんな納得するんじゃないかなあ。
上に書いたように俺の世代ってのは中学ですでにWindows95があってVBやらVCやらDelphiがあった世代で。そんなに苦労しなくても見栄えのいいGUIアプリがかける環境があったわけで。当然意識しないとマシン語とかアセンブラには触れない。俺はたしかJAVAからプログラミングに入ったけど、別にマシン語知らなくても全然大丈夫だった。
んでさらにはWebアプリの台頭。Webアプリを書いているときにマシン語をしらないから、という理由で困ったこともないし、新しい言語を覚えるときに困った覚えもない。つまりプログラマでも書くプログラムによってはそんなに必要ない、ということ。そういう時代まで、先人達の努力でやってきた、ということ。暇があるなら低レイヤを覚えておくにこしたことはないけど、他に覚えるべきことがあるなら、そっちを勉強したらいいと思う。
ただ、知っといたほうがいろいろいいことがあるのも事実。なので覚えたい人はがんばりましょう、ということで。
同じことを書いてる人もいるけど、むしろアセンブラとかにこだわりを持っている人のほうが、「ひどい」コードを書くこともあるよね。処理効率を優先しまくって可読性を落としたりとか、何をやってるのかわからないのがイヤ、と自分で必要ないものまで書いたりとか。
俺と低レイヤ技術
とそんなことを書きつつ、実は低レイヤも好きな俺。すみませんすみません。個人的に低レイヤの(特にCPUとか。ネットワークとかじゃなく。)ことを勉強したいなら、エミュレータは一度書いてみるべきだと思う。一個8bitCPUのエミュレータを書いて、そのCPUの逆アセンブラを書いて、デバッガ作って、できれば自分でアセンブラを書いて、アセンブリ言語をマシン語に落として、そのコードを実行させてみれば、CPUの基礎はかなりわかると思う。データがそろってる8bitCPUならそんなに苦労することなくかけるので、一度書いてみてはいかが。アセンブリ言語の書き方も、割り込みがどーたらも、なんMhzとかってなんなの、とかサイクルってなにとかメモリってどうなってんの、DMAってなにがうれしいんだよとかそういやビット演算ってなんの役にたつの、とか色々一気に疑問が解決する。それがわかっていればあとは順をおってCPU関連技術を勉強していけば理解もはやい気がする。自分で命令セットまで考えてそのCPUをソフトで実装すればもっと完璧。
実装言語はなんでもいいんじゃないかなあ。手前味噌だけど、Pythonでもエミュレータを書こうと思えばかけるわけで、PerlでもRubyでもJavascriptでもいいと思う。動作速度よりも理解する過程が楽しいかと。ちなみに自分の書いたPythonでのNESエミュレータだとCPU(6502)とメモリ関連で、簡易逆アセンブラ込みで1000行ほど。速度を犠牲にすればもっと短くかける。
あと、これも書かれてるけどむしろネットワークとか、DBとかのほうがよっぽど低レイヤの知識が必要だよなあ。10BASE-Tと100BASE-Tでなんでつなげるリピータハブの数が違うのかとか、これならどれだけスループットが確保できるか、それをわかるためにもCSMA/CDはなんたるかとか、実際どうやってケーブル上で衝突を検出してんのかとか色々わかってないと困るしねえ。他のネットワーク技術でも一緒。生のパケット(orフレーム)を見なけりゃいけないことも多々あるし。ソフト使ってちゃんと設定がかけます、だけだと意味ない。OSIの層を上から下までカバーしないと。そういった意味でもネットワークっておもろい。
PythonによるNESエミュレータ開発5
もうすぐ引越しです。頑張って部屋を片付けないと・・・
しばらくドタバタすると思し、これ以上作りこむモチベーションもないので、ここまで作ったものをあげておこうと思いました。
ダウンロード
pynes-0-0-1.zip
試し方
インストールはダウンロードしたzipファイルを展開するだけです。
必要なライブラリは
です。
両方ともeasy_install psyco、easy_install pygameでインストールできたはずです。
roms/以下に最低1つ以上ロムファイルを置いてください。現状、マッパーに対応してませんので、マッパー0のしか動く可能性はありません。現在動作を確認してるのは、前回あげさせていただいたTkShootくらいです。市販のはほとんど動かないんじゃないでしょうか。
一応参考までにあげておくと、動く可能性があるのはGolf,DonkeyKongなどです。
bin/pynesi.pyが起動用スクリプトです。コマンドラインから起動してください。起動したら、romファイルを番号で選択してください。
キーバーインドは
- 十字キー : カーソル
- スタート : テンキーの0
- セレクト : テンキーのEnter
- A : テンキーの3
- B : テンキーの2
になってます。キーバーインドを代えたい方はsrc/pynes/pad.pyを適当に書き換えてください。
- self.keymap1 = {
- K_UP : NES_PAD_UP,
- K_DOWN : NES_PAD_DOWN,
- K_LEFT : NES_PAD_LEFT,
- K_RIGHT : NES_PAD_RIGHT,
- K_KP0 : NES_PAD_START,
- K_KP_ENTER : NES_PAD_SELECT,
- K_KP2 : NES_PAD_B,
- K_KP3 : NES_PAD_A
- }
ここです。
とにかく、めちゃくちゃ遅いので、固まったと思ってもしばらくすると画面がちゃんと切り替わったりします。
よもや話
かなり適当です。前回(PythonによるNESエミュレータ開発4)から変わってません。マッパーっぽいのが用意してありますが、これはダミーです。他のエミュのソースを参考に必要そうな部分に適当にいれただけです。
一応、速度を重視しているものの、わかりやすく書いてるつもりなんで、Pythonが分かっていてかつ、エミュレータの基本的な構造が知りたい人には参考になるかもしれません。
PythonによるNESエミュレータ開発4

パッド入力部分を書いたので、動くゲームも出てきました。といってもまだほとんどのゲームが動かないんですけど。画面はブルジョアソフトウェア研究所さんのTkShoot 1.00が動作している様子です。
さて、ここまできたので基本的にはこの企画も終了かなー、という感じがします。目的はPythonのパフォーマンスについて知ることだったので。
作成の過程でかなりPythonのパフォーマンス関連について勉強ができてよかったと思います。
速度
サウンドは作っていないので、それを除くと1frameだいたい0.4秒弱くらいで動きます(もちろんpsycoを導入して)。変にベタ書きしたりはしていません。わりとメソッドはちゃんと分割しています。ただ、LDA $ssss(absolute addressingのLDA)だけ、実行回数が多いので完全にベタ書きしました。
んで感じたのは
- プリプロセッサでマクロを使えばそこそこ実用的な速度になりえるのではないか
- bytecodehacksでインライン化すれば結構いけるんじゃないか。ただし、bytecodehacksがオブジェクトのメソッドには対応していないので、classを使わずに書くことになる。
- 部分的にCで拡張モジュールを書けば、わりといけそう
ってことでしょうか。
まぁただ、JAVAとかC系全く分かりません><っていう人以外は、素直にC系かJAVAで書いたほうがいいと思います。
高速化のためにオブジェクトのプロパティをローカルにだしたり
- read = self.memory.read
- write = self.memory.write
- # .
- # .
- for i in xrange(foo):
- code = read(addr)
- # .
- # .
- # .
するので、無駄に行数も増えますし、ぶっちゃけ読みにくいです。それでも普段使い慣れてるLLで書けるってのは大きな利点だとは思います。
10年くらいして、マシンがもっと速くなることに期待しましょう、ということで(笑
その他雑感
現時点でも単純なゲームくらいなら、そこそこ動くのでコンピューターの仕組みの基礎を学ぶには、もしかしたらLLでエミュレータってのはいいかも。当然ですけど、デバッグの段階ではアセンブリ言語を書くことになりますし、そのアセンブリ言語の内容も完全に自分で処理するわけですから、単に本で読むよりは格段CPUやメモリについて詳しくなれると思います。ただ、CPUの仕組みを勉強しながら書くのはきついものがあるかもしれませんが・・・
他の利点としては「俺エミュレータ書いたんだぜ」と自慢できる(笑)、自分の書いたエミュレータでゲームが動くと結構感動できる、というくらいでしょうか。
というわけで、とりあえず動くようになりました。今のところソースをアップする気はないです。(してもほとんどのゲームは動かないし意味無い)
確実にいないと思いますが、もし、「俺もLLでエミュレータ書いてみるんだぜ!だからお前のしょーもないソースも参考にしてやるから見せるんだぜ!ついでにエミュってどうやって作るのか教えるんだぜ!」というような方や「おめーソースがないのに信用できるか!」という方がおられましたら、この記事のコメント欄やはてブなんかのコメントに、「うp」とか書いてください。適当にソースまとめてうpして、それをネタに簡単なエミュの書き方でも記事にします(笑
まぁとにかく書いてて楽しかったです。チャレンジ精神旺盛な方、そして時間があまっている方は是非LLでエミュにチャレンジしてみてください。
#追記
アップしました。コチラの記事へドウゾ。