スロットを一バイトづつずらしながらターゲットの数値を探す。

コマンドラインの精進のためのネタとしてやってみることにする。

もちろん目的はHPをマックスにすること。

  1. ひとつのセーブデータしかない状態にする。
  2. HPが271のデータをメモリカードデータから探す。

ひさしぶりのunpack

$ cat epsxe000.mcr| ruby -e 'a=STDIN.read;0.upto(a.size){|i|puts "#{i},#{a[i..i+1].unpack("s*")}"}' | egrep ",271$"
15714,271
15756,271
15758,271

現在のHPが271でHPMAXも271だから、ほぼ15756-9であることはまちがいないだろう。

  1. 15758-9バイト目を999にしてみる。
$ cat epsxe000.mcr| ruby -e cat epsxe000.mcr| ruby -e 'ad,v=15756,999;a=STDIN.read;a[ad..ad+1]=[v].pack("S*");STDOUT.write a'> a ; mv a epsxe000.mcr

確認もしておく

$ cat epsxe000.mcr| ruby -e 'a=STDIN.read;0.upto(a.size){|i|puts "#{i},#{a[i..i+1].unpack("s*")}"}' | egrep ",999$"
15758,999

見事。
ロードしてみると、「ロードできません」が…しまった。チェックサムでもついてるのか。

その後いろんな調査により、チェックサムの存在を確認
面倒になったのでirbで作業することにしてクリアした。

> a=File.open("epsxe000.mcr.20070720_155319").read;p a[0]
> a[0x3da3]=0x3b+0x80
> a[0x3da0,1]=[0x80+0x3b].pack("S*")
> a[0x2181]=(a[0x2182..0x3fff]+a[0x2180,1]).unpack("C*").inject(0){|r,i|r+i}%256
> f=File.open("epsxe000.mcr","w");f.write(a);f.close

それぞれ、行を読んで、1バイト書き換えて、2バイト書き換えて、チェックサムを計算し代入、ファイルを書き換える。
ひさしぶりにinjectで気持ちよかったのは内緒。

追記 2008/09/28 22:21:37:

チェックサムは128バイト毎の多連加算方式の場合

a=File.open("./epsxe001.mcr.bak").read

ad=0x250f;a[ad],a[ad+1],a[ad+2]=0x7f,0x96,0x98
ad=0x2535;a[ad],a[ad+1]=0xe7,0x03
ad+=2;a[ad],a[ad+1]=0xe7,0x03
ad+=2;a[ad],a[ad+1]=0xe7,0x03
ad+=2;a[ad],a[ad+1]=0xe7,0x03
ad+=2;a[ad],a[ad+1]=0xe7,0x03
a[0x257f]=a[0x2500..0x257e].unpack("C*").inject(0){|r,i|r+i}%256

f=File.open("epsxe001.mcr","w");f.write(a);f.close