正月だというのにひたすらCPUの命令を実装・・・。ここはひたすら地道な作業が続く。やっぱりこういう単純作業は苦手だ・・・

実装の際には InfoNES6502 Emulation Package のソースコード、そして NES on FPGAのCPUのページ に大変お世話になりました。特にNES on FPGAのページは非常に分かりやすくまとめられていて助かりました。

実装方針は前にも書いたとおり「できるだけPythonっぽく」。着々とエミュレーターっぽくないソースが出来上がってきています(笑 エミュレータのソースコードというとそれはもう、C言語でマクロ全開、register指定、inline(もしくはstatic)で出力されるコードを極限まで速く、なんて感じですが全く逆です。分かりやすさ優先。とりあえず書いてみて、ダメそうなら諦めるか頑張ってチューニングするか考えよう。

今日までで、CPUの全命令は実装しました(したつもり)。ただ、Indexed Absolute AddressingのX,Y、そしてIndirect Indexed Addressingでページクロスしたとき1クロック余計に発生する、という件は今のところスルー。

メモリ周りもIO以外はだいたい作ったので、今日の時点で単純なコードなら実行可能に。早速アセンブラを書いてNESASMで.NESファイルを作成。それを読み込んで動かしてみました。とりあえず動くことは動く・・・が全命令が正しく実装されているかはまだ分からないです(笑

というわけで次はデバッグ環境を整えて、命令のテストをしないとなあ。       余談。いやー卒論という重圧がないのは非常にプログラミングがはかどる。別にギリギリなわけでもないのに「卒論完全に出来上がってないのにこんなことしてていいのかなーって感じちゃう」的なものがないし。


2007年になりましたね。月に1回更新するか怪しいこのブログを購読してくださってる方々、ありがとうございます(笑

無事卒論も提出し、気楽な学生気分を満喫しています。ちなみに、卒論は完璧にコンピュータは関係ないもので、まぁラットと戯れていました。生物、こと脳にかかわる話も面白いですよ。まったくもって大した研究ではないのですが、教授が今年ヨーロッパの学会で発表してくださるらしいです。とりあえず書けて何より。

さて、プログラミング関連ですが、卒論もようやく終わり4月までは暇な学生生活、まとまった時間がとれるようになったので、ちょろちょろ書き始めています。

書いているのは・・・なんと今更NESエミュレータ。

一から自分で解析してエミュレータを書くのは達人ワザですが、十分なハードウェアの情報がある場合、実はそんなに難しくなかったりします。

というわけで書いているんですが、ここで普通にC言語やアセンブラで書こうというような楽?はしてません!NESエミュレータをPythonで書いてみる、これがチャレンジング。ぶっちゃけPythonで速度がシビアに求められるものを書いたことがないので、チャレンジです。

書く上で、とりあえず

  • ctypesは使わない(Cの流儀をそのままもっていってもおもしろくない)
  • 当然Cで拡張モジュールは書かない

というポリシーで書き進めています。

しかしやっぱりキツイ。絶対Cの方が楽な気がするのは気のせいだろうか・・・。現在はだいたいCPU(6502)のコアが書き終わったので、メモリ周りを書き進めてます。とりあえず.NESファイルから読み込んでメモリに読み込み、PCをセットするあたりまで書きました。

まず、NESのヘッダ読み込むのもめんどくさい。Cならfreadで構造体にマップしておわり、なのにPythonだとそうは行かない。そしてなんといってもポインタがない。これ。メモリのミラーリングとかめんどくさいだろうな・・・(笑

そうこう書いてるうちに、Pythonでのバイナリの扱いが上手くなってきました(きたような気がします)。       今のところ以下のような関数が活躍しています。エディアンは今のところ決めうちです。

 1from struct import * 
 2from array import array
 3
 4def unpack_byte(b):
 5  return unpack("<B", b)[0]
 6
 7def zero_filled(n):
 8  n /= 2
 9  return pack('h'*n, *([0]*n))
10
11def byte_array(v):
12  return array('c', v)
13
14class byte_ref(object):
15  def __init__(self, p):
16    self._value = p
17  def get_value(self):
18    return self._value
19  def set_value(self, v):
20    self.value[0:] = byte_array(v)
21  value = property(get_value, set_value)

まず、PythonでRAMをエミュレートしようと思うと、可変なunsigned charな配列が当然必要です。

Pythonで data = open("name", "rb").read() とした場合、きちんとバイナリデータがdataに入って、 unpack_byte(data[0:1]) などとするとちゃんとデータを取り出せます。

しかし、この場合、Pythonの内部では*不変な型である*文字列型として扱われているので data[w_addr & 0x7ff] = 0x12 みたいなことは出来ません。つまりROMにはなりますが、RAMになれません。じゃあどうやってunsigned charの配列を表現するか、ということで array モジュールの登場なわけです。 data = byte_array(open("name", "rb").read()) という感じで使っています。生成方法がことなるだけで data[0] みたいなインデックスによるアクセスも出来るし、部分書き換えも可能です。

byte_refは・・・別になくてもいいかもしれませんが、byte配列に対する参照を表現するオブジェクトです。といっても注意して使わないと意味がないクラスで気持ちの問題かもしれません。

ここをctypesでポインタを使えば考えなくてもよかったんですが、あえてPythonなんだ、ということで(笑

 

   

近況はこんな感じです。

ついに就職が近づいてきました。仕事はプログラマではないので、プログラムを書く時間はあんまり取れないかもしれません。でもまぁ、日曜プログラマとして細々やっていけたらなあ、と思っています。


coLinux で Emacs の kill-ring の内容をWindowsのクリップボードと同期する とか coLinux 上の Emacs の kill-ring の内容をWindowsのクリップボードと同期する by Perl から。

上記のサイトのをもってきて.vimrcをちょろっと書けばいいんだけど、テキストを受信するサーバーは常時立ち上げていそうで、スクリプトだとなんとなくアレなので、exeがいいなあ。簡単にできそうなので、とりあえず探すよりは作ってみるメソッド。

ファイル一式

clsync.zip

内容は

  • clipboard_server.exe:Windows側で実行するサーバー
  • clipboard_server.ini:サーバーのポートの設定
  • clsync.py:vmware側におくクライアントスクリプト

使い方など

Windows側ではclipboard_server.iniで適当にポートを設定して(当然外部から見えないやつを)、clipboard_server.exeを起動しておいてください。タスクトレイにアイコンが表示されてますので、そこから終了できます。

vmware上のLinuxですが、まずnkfがインストールされている必要があります。すみません、クライアント側手抜きするために使っています。そしてclsync.pyをパスの通ったところにおきます。clsync.pyにはホストのWindows側で動いてるサーバーのポートとIPを設定する箇所があるので、適宜書き換えます。またポートとIPはオプションでも渡せます(詳しくはclsync.py -hで)。

あとは

1function! SyncClipboard()
2  let cliptext = substitute(getreg(), "'", "'\"'\"'", 'g')
3  let cmd = "echo '" . cliptext . "' | clsync.py"
4  call system(cmd)
5endfunction
6nmap ,c :call SyncClipboard()<CR>

こんな感じなのを.vimrcに追加すればOK。最後にyankしたものが,cでホストのWindowsのクリップボードに送られます。

追記: っとよく考えたらvmw copyとまったく一緒。.vimrcのclsync.pyの部分をvmw copyに置き換えれば同じように動作する。ただ、vmwの説明には

コピーするテキストに改行コード以外の非 ASCII 文字を含めることはできません。 ゲストおよびホスト OS によっては、キャリッジリターンの付与・除去が行われ ます。 コピー可能なテキストの最大長は約 65,000 バイトです。

ってある。 今回作ったモノの場合はnkfをかませているのでもちろんいつでも日本語オーケー。 それ以上は深くみてないけど、UTF-8だと日本語でもvmw copyしても問題なさそうだ。EUC-JPの「ほげほげ」とかいう内容のtest.txtをvmw copy test.txtとかするとダメだった。

ま、というわけで、 cat test.txt | nkf -w | vmw copyで万事解決なんだけど。

というわけでこのツールは使われないまま終わる(笑 coLinuxはよく知らないけど、coLinuxにこういうホストOSへのクリップボードコピーコマンドがないなら、coLinuxでは役に立つかも。