「ポートピア連続殺人事件」のテキストを抜き出すpythonコード

聖闘士星矢に続いて、ポートピアのテキスト部分を抜き出してみました。
ポートピア連続殺人事件のバイナリイメージと、Python3系の実行環境が必要となります。

portopia.pyとかいう名前でコードを保存して、

python portopia.py portopia.nes(バイナリファイル名)

とかいう感じで実行して下さい。
portopia.nes_dic.txt(辞書ファイル)
portopia.nes.txt(辞書を適応した変換後のテキストファイル)
の2ファイルができあがります。
辞書ファイルにはよく使われる単語(登場人物の名前や証拠品、地名など)とか、言い回し(「あやしい」「いました。」「それいじょうのことは」など)、コマンド名などが収納されていて、テキスト部分の容量を節約するのに一役買っているようです。

単語辞書やテキストエリアの開始/終了アドレスなどは決め打ちで書いてるので、もしROMにバージョン違いがあったら、正常動作しないかもしれません。

portopia.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import sys
 
argvs = sys.argv
argc = len(argvs)
 
for i, s in enumerate(argvs):
    print('%d:%s' % (i, s))
 
if (argc < 2):
    print('Usage:>python %s [nesfile]' %argvs[0])
    quit()
 
str_after = \
'0123456789あいうえおか'\
'きくけこさしすせそたちつてとなに'\
'ぬねのはひふへほまみむめもやゆよ'\
'らりるれろわをんッロハカウゃゅょ'\
'っべイスタナフホマヤラー゛゜、。'\
'「‥!?・…→↓ヒ#*Aトアンリ'
offset = 0x00
 
def str2dic(dics, string, offset):
  for i, s in enumerate(string):
    dics[offset + i] = s
 
dics = {}
str2dic(dics, str_after, offset)
del dics[0x57]
dics[0xfb] = '(間)'
dics[0xfd] = '(人/アイテム名)'
dics[0xfe] = '\n'
dics[0xff] = ' '
 
kana_dic = {
  0x4c:['かきくけこさしすせそたちつてとはひふへほ'\
        'カキクケコサシスセソタチツテトハヒフヘホ',\
        'がぎぐげござじずぜぞだぢづでどばびぶべぼ'\
        'ガギグゲゴザジズゼゾダヂヅデドバビブベボ'],
  0x4d:['はひふへほハヒフヘホ', 
        'ぱぴぷぺぽパピプペポ']
}
 
with open(argvs[1], 'rb') as f:
    read_data = f.read()
 
#単語辞書の作成
dic_word = {}
dic_begin = 0x60
dic_end = 0xea
dic_address_from = 0x3e9e
dic_address_to = 0x44bd
tmp = ''
i = dic_begin
for c in read_data[dic_address_from:dic_address_to]:
  if c in kana_dic.keys() and len(tmp) > 0:
    #濁音・半濁音変換
    if tmp[-1] in kana_dic[c][0]:
      j = kana_dic[c][0].find(tmp[-1])
      tmp = tmp[0:-1] + kana_dic[c][1][j]
  elif c in dics:
    tmp += dics[c]
  else:
    dic_word[i] = tmp
    i += 1
    tmp = ''
 
#単語辞書ファイル出力
with open(argvs[1] + '_dic.txt', 'w') as f:
  for k, v in dic_word.items():
    f.write("%04X[%s]\n" %(k, v))
 
#単語辞書を変換表に反映
for i in range(dic_begin, dic_end+1):
  dics[i] = dic_word[i]
 
text_begin = 0xd92
text_end = dic_address_from
#素のテキストと辞書の該当単語を変換
with open(argvs[1] + '.txt', 'w') as f:
  tmp = ''
  hexs = ''
  is_bracket = False
  for i,c in enumerate(read_data[text_begin:text_end]):
    if (len(tmp) == 0):
      address = i + text_begin
 
    if c in kana_dic.keys() and len(tmp) > 0:
      #濁音・半濁音変換
      if tmp[-1] in kana_dic[c][0]:
        j = kana_dic[c][0].find(tmp[-1])
        tmp = tmp[0:-1] + kana_dic[c][1][j]
    elif c in dics:
      hexs += '%02X' % c
      t = dics[c]
#      if c in range(dic_begin, dic_end) and c not in range(0xd1,0xea):
#        t = '{%x:%s}' % (c, dics[c])
      tmp += t
      if '「' in dics[c]:
        is_bracket = True
    elif len(tmp) > 1:
      if is_bracket:
        tmp += '」'
      f.write("0x%x\n%s\n%s\n" % (address, hexs, tmp))
      tmp = hexs = ''
      is_bracket = False
    else:
      tmp = hexs = ''

「聖闘士星矢 黄金伝説」のテキストを抜き出すpythonコード

ファミコン版「聖闘士星矢 黄金伝説」のテキスト部分を引っこ抜くpythonのコードを書きました。
実行には「聖闘士星矢 黄金伝説」を引っこ抜いたバイナリファイルと、python3の実行環境が必要です。
Ubuntu Linux14上のpython3.4.3でしかテストしていませんが、ファイル操作をしているだけなので、他の環境でも多分動くでしょう。

以下のコードを”ss.py”とかそんなファイル名で保存して、

python ss.py ss.nes(聖闘士星矢のバイナリファイル名)

と実行すると、”ss.nes.txt”というテキストファイルが出来上がります。

テキストの内容は、
(ROM中の番地)
(該当するバイナリ)
(変換したテキスト)
の3つで1つの組み合わせになっています。


最初の方は意味不明ですが(これはどうやって取り除いたものか……)、

このあたりは解読可能ですね。

6~21行目の変換後文字のマップと、39行目のelif(改行コード)、42行目のelif(多分表情などを変えている制御文字)あたりをいじくれば、他のゲームにも応用が効きます。
もっとも、たいていの場合はもっと制御文字を使ってROM容量を削っているので、この聖闘士星矢のようにベタのテキストデータをそのまま埋めるような贅沢な使い方は珍しいかもしれませんが。

ss.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import sys
 
argvs = sys.argv
argc = len(argvs)
 
str_after = \
'0123456789あいうえおか'\
'きくけこさしすせそたちつてとなに'\
'ぬねのはひふへほまみむめもやゆよ'\
' ■■■らりるれろわをんぁぃぅぇ'\
'ぉっゃゅょアイウエオカキクケコサ'\
'シスセソタチツテトナニヌネノハヒ'\
'フヘホマミムメモヤユヨラリルレロ'\
'ワヲンァィゥェォッャュョ゛゜、ー'\
'?!・‥ABCDEFGHIJKL'\
'MNOPQRSTUVWXYZ/「'\
'」()%×           '\
'がぎぐげござじずぜぞだぢづでどば'\
'びぶべぼぱぴぷぺぽ       '\
'ガギグゲゴザジズゼゾダヂヅデドバ'\
'ビブベボパピプペポ'
 
if (argc < 2):
    print('Usage:>python %s [nesfile]' %argvs[0])
    quit()
 
with open(argvs[1], 'rb') as f:
    read_data = f.read()
 
with open(argvs[1] + '.txt', 'w') as f:
    str = ''
    hexs = ''
    for i,c in enumerate(read_data):
        if c > 0 and c < len(str_after):
            if (len(str) == 0):
                address = i
            hexs += '%02X' % c
            str += str_after[c]
        elif c == 0xfe:
            hexs += '%02X' % c
            str += '\n'
        elif c >= 0xe0 and c <= 0xef:
            hexs += '%02X' % c
            str += hex(c)
        elif len(str) > 5:
            f.write("0x%x" % address + "\n")
            f.write(hexs + "\n")
            hexs = ''
            f.write(str + "\n")
            str = ''
        else:
            hexs = ''
            str = ''

【ゆゆゆ関連 21】鷲尾須美の章第3章の覚え書き

そろそろ上映終わるところが出てきたので覚え書き。1章と2章は書き忘れてたし、記憶も曖昧になってきたので、秋のテレビ版放送後かなー。
BDは買えていないので、記憶に頼って書いています。ところどころうろ覚え。
以下、「鷲尾須美の章」はもちろん、ゆゆゆ、のわゆシリーズのネタバレ含むので要注意。
続きを読む

江戸川乱歩のここが好き その1「触覚」

ここ数年、江戸川乱歩を読むのにハマっている。
少年探偵団などの子供向けの作品を除いて、ほとんど読んでしまったので、どういうところが好きなのかをまとめておきたいと思う。

今回は「触覚」を取り上げたい。
もちろんネタバレ放題なので、未読の方は注意されたい。というか、未読の型は以下の文章の意味が分からないと思います。

2017/08/02現在で、青空文庫で50作品程度が読めるようです。
どの書籍のどの作品が収録されているか、などは乱歩の世界様が詳しい。
私は、様々なバージョン違いを細かく網羅している光文社文庫の全集が気に入っている。
続きを読む

ArduinoからYMZ294のエンベロープを操作のシンプルなやつ

2年前の記事に質問頂いたので、回答も兼ねて久しぶりにArduinoのスケッチを書きました。

前にYMZ294のエンベロープをいじった時は、MMLの解釈部分や外部入力からエンベロープを操作する部分など、やや複雑になっていたので、今回は出来る限りシンプルにしてみました。
こんなよーな音が出ます。
続きを読む

人類の黄昏の時代?「けものフレンズ」の世界

ここで言う「黄昏の時代」は、ポストアポカリプスよりもうちょっと広い意味で、人類が今現在より衰退している、的な意味です。
タイトルそのまんまな「人類は衰退しました」や、「ヨコハマ買い出し紀行」、「結城友奈は勇者である」シリーズなど、あと実写映画の「マトリックス」も入るかな。あーいう感じの作品を念頭に置いといてもらえるとありがたいです。
続きを読む

音をいろいろいじくってる人のサイト