さらなる低レイヤへ
- 独習 電気/電子工学
- 著: Stan Gibilisco
- 訳: 日向俊二
- 監修: 矢沢久雄
- ISBN:9784798113289
- 出版社:株式会社翔泳社
買った。
デジタル回路くらいまでならある程度知識はあったけど、ここらへんまでくるとさすがに知らないことばかり。
結構幅広く書いてあるので、疑問に思ったことを調べる辞書的にもつかえそう。
謹賀新年&近況
2007年になりましたね。月に1回更新するか怪しいこのブログを購読してくださってる方々、ありがとうございます(笑
無事卒論も提出し、気楽な学生気分を満喫しています。ちなみに、卒論は完璧にコンピュータは関係ないもので、まぁラットと戯れていました。生物、こと脳にかかわる話も面白いですよ。まったくもって大した研究ではないのですが、教授が今年ヨーロッパの学会で発表してくださるらしいです。とりあえず書けて何より。
さて、プログラミング関連ですが、卒論もようやく終わり4月までは暇な学生生活、まとまった時間がとれるようになったので、ちょろちょろ書き始めています。
書いているのは・・・なんと今更NESエミュレータ。
一から自分で解析してエミュレータを書くのは達人ワザですが、十分なハードウェアの情報がある場合、実はそんなに難しくなかったりします。
というわけで書いているんですが、ここで普通にC言語やアセンブラで書こうというような楽?はしてません!NESエミュレータをPythonで書いてみる、これがチャレンジング。ぶっちゃけPythonで速度がシビアに求められるものを書いたことがないので、チャレンジです。
書く上で、とりあえず
- ctypesは使わない(Cの流儀をそのままもっていってもおもしろくない)
- 当然Cで拡張モジュールは書かない
というポリシーで書き進めています。
しかしやっぱりキツイ。絶対Cの方が楽な気がするのは気のせいだろうか・・・。現在はだいたいCPU(6502)のコアが書き終わったので、メモリ周りを書き進めてます。とりあえず.NESファイルから読み込んでメモリに読み込み、PCをセットするあたりまで書きました。
まず、NESのヘッダ読み込むのもめんどくさい。Cならfreadで構造体にマップしておわり、なのにPythonだとそうは行かない。そしてなんといってもポインタがない。これ。メモリのミラーリングとかめんどくさいだろうな・・・(笑
そうこう書いてるうちに、Pythonでのバイナリの扱いが上手くなってきました(きたような気がします)。
今のところ以下のような関数が活躍しています。エディアンは今のところ決めうちです。
- from struct import *
- from array import array
- def unpack_byte(b):
- return unpack("<B", b)[0]
- def zero_filled(n):
- n /= 2
- return pack('h'*n, *([0]*n))
- def byte_array(v):
- return array('c', v)
- class byte_ref(object):
- def __init__(self, p):
- self._value = p
- def get_value(self):
- return self._value
- def set_value(self, v):
- self.value[0:] = byte_array(v)
- 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なんだ、ということで(笑
近況はこんな感じです。
ついに就職が近づいてきました。仕事はプログラマではないので、プログラムを書く時間はあんまり取れないかもしれません。でもまぁ、日曜プログラマとして細々やっていけたらなあ、と思っています。
Python:バイナリでコンソールを表示しないようにするには?
Pythonのコードをwindows用exeにするには当然、py2exeを使います。
で、そのとき、 python setup.py py2exe --windows とすれば、コンソールを表示しないようにできます。
Note:これはもう古いやり方で、現在のバージョンのpy2exeでは動きません・・・。現在はターゲットファイルの拡張子を.pywにする、もしくはwindows = [{'script' : 'script.py', "icon_resources": [(1,"script.ico")]}]というオプションをsetupに渡す、という方法になっています。
今日、昔py2exeで作ったファイルが出てきたんですが、困ったことにpythonのソースファイルはない。いや、別に改良とかもうしないしいいんだけど。
ふと起動してみるとGUI with console。かっちょわりい。
コンソールが表示される、というのは単純にPEファイルのオプションなわけで。

この部分を変更してやればとりあえずは直る。ちなみに、
00 00:未知のサブシステム
01 00:デバイス ライバおよびWindowsNTネイティブプロセス用
02 00:GUIで実行されるファイル
03 00:コンソールで実行されるファイル
07 00:Posixコンソールで実行されるファイル
09 00:WindowsCEで実行されるファイル
なので02h 00hにしてやればオッケー。
Pythonでバイナリファイルの読み書きとかしたことないので練習もかねて。
- # vim: fileencoding=utf-8
- import sys
- from struct import *
- target_file = len(sys.argv)> 1 and sys.argv[1] or sys.exit("Target file is not specified.")
- target_file = unicode(target_file, "mbcs")
- out_file = open(target_file + "_gui", "wb")
- io = open(target_file, "rb")
- while 1 :
- if io.read(1) == "P" and io.read(1) == "E" : break
- subsystem_pos = io.tell() +90
- io.seek(0)
- out_file.write(io.read(subsystem_pos))
- io.seek(4, 1)
- out_file.write(pack('hh', 2, 0))
- out_file.write(io.read())
- io.close()
- out_file.close()
こんな感じ。引数にexeファイルを渡せばオッケー。でも、適当なので全部のケースで動くかはあやしいw
pythonではバイナリを扱うときはstructモジュールを使う、ということが分かりました(笑
