今回は昔懐かしの「復活の呪文」と
BASE64の関係についてです
解説動画はこちら
復活の呪文について
さて、復活の呪文を知らない人のために
復活の呪文についてですが
ひらがなの羅列を入力し
正しい呪文であったら
呪文の長さ
実データ長
有名な復活の呪文
この
電子メールなどに利用されているような仕組みです
最近だと画像なんかも有りますね
BASE64の変換の仕組みが
復活の呪文の変換方法と似ているので
BASE64の仕組みを見てみましょう
BASE64の仕組み
まずはBASE64文字対応表を用意します
使える文字種は
英大文字(26種):A - Z
英子文字(26種):a - z
数字(10種):0 - 9
記号(2種): + /
これはPythonだとstringライブラリで
用意できます
あとはこれを6ビットの2進数文字列にします
こんな感じで64文字分のデータを用意します
0100111101110100011101010111000001111001
連結するとこんな感じの文字列になります
こんな感じで文字列を変換できました
なお、変換後の文字列の長さは4の倍数分の長さにして
足りないところは=で埋めるようです
T3R1cHk=
これがBASE64に変換した際の文字列です
長々と仕組みを見てきましたが
PythonにはBase64ライブラリがあるので
この変換自体は1行で出来ちゃいます
道中の、64文字の変換表を用いて
データを変換させる仕組みの部分が
復活の呪文に近い所ですね
と言うわけで
復活の呪文ぽい実装を見てみましょう
復活の呪文っぽい実装
64文字のひらがなを用意して
それに対応するように変換します
20文字分のひらがなを入れてみましょう
呪文からデータへ
データから呪文を生成します
ゲームではおそらく
このようなデータを使って
ゲームのステータスを再現していたのでは
なかろうかと思います
まとめ
現在ではBASE64への変換などは
ライブラリで一発で出来ちゃいますが
と言うわけで文字の変換表などを
実装していただろうと推測します
各桁の数値をデータに対応させて
たんだろうなーと思うと
1文字間違えて地獄を見た日々を思い出しますね
ドラクエ1の容量が512kbit(64KB)らしいので
画像とプログラム含めでこのサイズに納めるのは凄まじいテクニックが
必要だったんだろうと思います
今では画像だけで1MBとか
余裕で越してしまうので
当時の技術力の高さが
窺い知れますよねー
というわけで
今回は昔懐かしの
「復活の呪文」とBASE64
についてでした
それでは
BASE64の関係についてです
解説動画はこちら
復活の呪文について
さて、復活の呪文を知らない人のために
復活の呪文についてですが
ドラクエ1-2に実装されていた
データの進行状況を保存する方法のことで
データの進行状況を保存する方法のことで
ひらがなの羅列を入力し
正しい呪文であったら
対応するステータスが再現される
というものです
というものです
発売当時のファミリーコンピューターには
ゲームの保存機構が付いていなかったので
知っていたら40代以上確定という代物
その後のドラクエ 3や
ファイナルファンタジーなどは
セーブ機能があるので
この復活の呪文を知る世代は
少なくなっているかもしれません
ファイナルファンタジーなどは
セーブ機能があるので
この復活の呪文を知る世代は
少なくなっているかもしれません
ドラクエ1の復活の呪文の仕様
ドラクエ 1と2では復活の呪文の
使用が違いますが
ドラクエ 1は次の様です
使える文字種(64文字種)
使用が違いますが
ドラクエ 1は次の様です
使える文字種(64文字種)
あいうえお かきくけこ
さしすせそ たちつてと
なにぬねの はひふへほ
まみむめも らりるれろ
やゆよわ
がぎぐげご ざじずぜぞ
だぢづでど ばびぶべぼ
呪文の長さ
20文字固定
実データ長
6(bit)×20=120(bit)=15バイト相当
有名な復活の呪文
くわたきよはらしのずかなかはたはらいしい
この
ひらがな+濁音文字で64文字というのが
BASE64の仕様と似ている訳です
ここでBASE64の仕組みを見てみましょう
BASE64
BASE64
データを64種類の印字可能な
英数字のみを用いてそれ以外の文字を
扱うことの出来ない通信環境にて
英数字のみを用いてそれ以外の文字を
扱うことの出来ない通信環境にて
マルチバイト文字や
バイナリデータを扱うためのエンコード方式
バイナリデータを扱うためのエンコード方式
電子メールなどに利用されているような仕組みです
最近だと画像なんかも有りますね
BASE64の変換の仕組みが
復活の呪文の変換方法と似ているので
BASE64の仕組みを見てみましょう
BASE64の仕組み
まずはBASE64文字対応表を用意します
アルファベットを6ビットで対応させた
辞書データのようなものです使える文字種は
英大文字(26種):A - Z
英子文字(26種):a - z
数字(10種):0 - 9
記号(2種): + /
これはPythonだとstringライブラリで
用意できます
あとはこれを6ビットの2進数文字列にします
import string
upper = string.ascii_uppercase
lower = string.ascii_lowercase
digits = string.digits
base64_str = upper + lower + digits + '+/'
dict64 = {}
for i ,s in enumerate(base64_str):
b = bin(i)
str64 = '{0:06}'.format(int(str(b)[2:]))
dict64[str64] = s
print(s ,'\t', str64)A 000000
B 000001
・・・
9 111101
+ 111110
/ 111111
こんな感じで64文字分のデータを用意します
次にBASE64に変換する文字列を用意します
今回は「Otupy」
BASE64に変換するには
このアルファベットを文字列から16進数に直し
16進数から2進数文字列に変換して連結します
text = 'Otupy'
out = []
for t in text:
hex_str = t.encode('utf-8').hex()
int_num = int('0x' + hex_str , 0)
bin_num = bin(int_num)
out_str = '{0:08}'.format(int(str(bin_num)[2:]))
out.append(out_str)
print(out)
encode_str = ''.join(out)
print(encode_str)['01001111', '01110100', '01110101', '01110000', '01111001']
0100111101110100011101010111000001111001
連結するとこんな感じの文字列になります
この連結した文字列を
6桁(ビット)で区切って
6桁(ビット)で区切って
さっき作った対応表に当ててみると
values = []
for i in range(0,len(encode_str),6):
key = encode_str[i:i+6]
key = key if len(key)==6 else key + '0' * (6-len(key))
value = dict64[key] if key in dict64 else '='
values.append(value)
print(key , value)010011 T
110111 3
010001 R
110101 1
011100 c
000111 H
100100 k
こんな感じで文字列を変換できました
なお、変換後の文字列の長さは4の倍数分の長さにして
足りないところは=で埋めるようです
v_str = ''.join(values) encode64_str = v_str if len(v_str)%4==0 else v_str + '=' * ((8-len(v_str))%4) print(encode64_str)
T3R1cHk=
これがBASE64に変換した際の文字列です
長々と仕組みを見てきましたが
PythonにはBase64ライブラリがあるので
この変換自体は1行で出来ちゃいます
import base64 # T3R1cHk= text = 'Otupy' st = base64.b64encode(text.encode()) print(st)b'T3R1cHk='
道中の、64文字の変換表を用いて
データを変換させる仕組みの部分が
復活の呪文に近い所ですね
と言うわけで
復活の呪文ぽい実装を見てみましょう
復活の呪文っぽい実装
64文字のひらがなを用意して
それに対応するように変換します
import re
charas = '''
あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほ
まみむめもらりるれろやゆよわ
がぎぐげござじずぜぞばびぶべぼぱぴぷぺぽ
'''.replace('\n','')
# 復活の呪文にする
def jyumon_encode(bin_num):
b = bin_num + '00000'
b = b[0:-(len(b)%6)]
encoded = ''.join(map(lambda c: charas[int(c, 2)], re.split('(.{6})', b)[1::2]))
return encoded
# 復活の呪文からデータにする
def jyumon_decode(encode_text):
decode = ''.join(map(lambda c: format(charas.find(c), '06b'), encode_text))
return decode
20文字分のひらがなを入れてみましょう
encode_text = 'くわたきよはらしのずかなかはたはらいしい' decode_text = jyumon_decode(encode_text) print(decode_text) re_encode_text = jyumon_encode(decode_text) print(re_encode_text)000111101011001111000110101010011001100011001011011000110011000101010100000101011001001111011001100011000001001011000001 くわたきよはらしのずかなかはたはらいしい
呪文からデータへ
データから呪文を生成します
ゲームではおそらく
このようなデータを使って
ゲームのステータスを再現していたのでは
なかろうかと思います
まとめ
現在ではBASE64への変換などは
ライブラリで一発で出来ちゃいますが
1986年(昭和61年)当時は
BASE64ライブラリとか無いんじゃないかと
BASE64ライブラリとか無いんじゃないかと
と言うわけで文字の変換表などを
実装していただろうと推測します
各桁の数値をデータに対応させて
たんだろうなーと思うと
1文字間違えて地獄を見た日々を思い出しますね
ドラクエ1の容量が512kbit(64KB)らしいので
画像とプログラム含めでこのサイズに
必要だったんだろうと思います
今では画像だけで1MBとか
余裕で越してしまうので
当時の技術力の高さが
窺い知れますよねー
というわけで
今回は昔懐かしの
「復活の呪文」とBASE64
についてでした
それでは

コメントする