「CityBravo!」時間停止コード探求の記録と御負け

CityBravo!」(シティーブラボー,アルトロン制作)といふPSゲームがあります。此のゲームはSimCityのやうな都市シミュレーション型のゲームなのですが,困ったことに「時間を止めながら建築物を配置する」ことができません。操作に手間取ってゐると,ライバル会社の職場や店舗が乱入して来て,都市計画が台無しになることも屡屡です。

そこで改造コードを使って,時間を止めながら建築物を置ける状態に持って行けたので,その改造コードを発見するまでに私が辿った軌跡を書き留めておきます。序でに,御負けもつけておきました。

軌跡

時間停止フラグの捜索

づ,ゲーム画面上部の「一時停止」ボタンで時間が止ります。このフラグ0x0EC530番地(接頭辞「0x」は16進数の意)にあり,値が0x01で停止,0x00で解除になります。この番地自体は,「ゲームで『一時停止』ボタンを押す度に,cepで『異なる』で比較検索」をすると簡単に見つかります。

しかし,800EC530 0001といふコードをcepで始動させても全く意味が有りません。といふのも,「一時停止フラグ」=「作業不可」といふ条件分岐になってゐるらしく,このコードが作動中は確かに時間は止ってゐるのですが,時間停止中は作業できませんといふ忌まはしいメッセージは相変らず消えません。別の方法を探す必要が有ります。

で,此のゲームには「調査」といふコマンド(情報アイコン⇒調査アイコン)があるのですが,「調査」する建物を選ぶ場面では,時間スピードの設定に関らず,時間が止ってゐます。詰り,「『一時停止』とは何か別のフラグで時間を止めてゐるのでは」と推察し,「『調査』する建物を選ぶ場面」と「それ以外で普通に時間が流れてゐる場面」とで,cepの「異なる」比較検索を繰り返してみました。

結果,数十件の候補が残ったのですが,先の例で解るやうに,かういふフラグは大抵0x000x01の値(boolean型)で管理してゐますから,値が0か1になってゐるものを一つづつ,片端から試した結果,先程とは別のフラグが見つかりました。即ち,0x0EC700番地の値を0x01にすることで時間が停止し,0x00で解除になります。

此のフラグで時間を止めても,建築物を建てる際に文句は言はれません。成功です。

押されたボタンの検出

此れで一往の目的は達成したのですが,使ひ易くする為に,コントローラーで時間停止フラグを操作できるやうにします。その為にはコントローラーで押されてゐるボタンを検出する必要がありますが,これはゲーム中で押すボタンを変えながら,cepにて「異なる」で比較検索を繰り返せばOKです。但しSSSPSXのウインドウから他のウインドウに切り替える瞬間,ボタンは押しっぱなしにする必要があります。(かうすることで,ゲーム中ではボタン押しっぱなしの状態になります。)

検索の結果,0x0EC064番地にコントローラーで押したボタンが現れることが判りました。茲で,ボタンと値の対応表を次に載せておきます。接頭辞「0x」は省略してあります。

# L2=+0001, R2=+0002, L1=+0004, R1=+0008, 
# △=+0010, ○=+0020, ×=+0040, □=+0080,
# SELECT=+0100, L3=+0200, R3=+0400, START=+0800,
# ↑=+1000, →=+2000, ↓=+4000, ←=+8000

同時押しは加算します。例へば,START+R20x0800 + 0x0002 = 0x0802 となります。餘談ですが,昔「ゲームラボ」で,「PSのボタン検出で現れる値は,先の表か,もう1つのパターン(減算だったかな?)とのどちらかが多い」と読んだ記憶があります。

今までの成果を踏まへて出来た改造コードが次のものです。(註: 不完全版です。後で完成版が出てきます。)

"STARTで時間停止,△で解除" # 不完全版
D00EC064 0800
300EC700 0001
D00EC064 0010
300EC700 0000

不本意な時間停止解除(×ボタン)への対策

此れで完成と言ひたいところですが,建物を建設する場所を選ぶ場面で×ボタンを押して,建物を選択する画面に戻ると,先の時間停止フラグ(0x0EC700番地)が強制的に0x00に設定されることが判りました。詰り,折角時間を止めてゐても,解除用のボタンを押してゐないのに動き出してしまひます。

この対策として,「ボタンを押したフラグを別に作って,そのフラグを時間停止判定の条件にする」といふ方法を採りました。言葉で表しても解り難いので,次の完成版を御覧ください。

完成版

"STARTで時間停止,△で解除"
D00EC064 0800
300EC701 0001
E00EC701 0001
300EC700 0001
D00EC064 0010
300EC701 0000
E00EC701 0000
300EC700 0000

このコードをcepの「改造」タブにあるテキストボックスにコピー&ペーストし,「始動」を押せばOKです。

このコードが何をやってゐるのかを,一行づつ日本語で読んで行きます。但し,最初の行はタイトルなので無視します。

D00EC064 0800
0x0EC064番地の値が0x0800の時,即ちSTARTボタンが押されてゐる時のみ,次のコードを1つだけ実行します。
300EC701 0001
0x0EC701番地の値を0x01に置換します。此れは「時間停止フラグを有効にする為のフラグ」です。このアドレス(0x0EC701)は別に何処でもよいのですが,ゲーム中で使はれてゐなささう(値を変更しても影響が無ささう)な場所にしてゐます。
E00EC701 0001
0x0EC064番地の値が0x01の時,即ち「時間停止フラグを有効にする為のフラグ」が立ってゐる時のみ,次のコードを1つだけ実行します。
300EC700 0001
0x0EC700番地の値を0x01にします。即ち,時間停止フラグを有効にします。

後半のコードも同様の動作です。此れをLisp風・C風に書くと次のやうになります。

(loop
  (when (= (aref memory #x0EC064) #x0800)
    (setf (aref memory #x0EC701) #x01))
  (when (= (aref memory #x0EC701) #x01)
    (setf (aref memory #x0EC700) #x01)))
for(;;) {
  if( memory[0x0EC064]==0x0800 )
    memory[0x0EC701]=0x01;
  if( memory[0x0EC701]==0x01 )
    memory[0x0EC700]=0x01;
  }

何故此れで上手く行くのかと言ふと,不本意に時間停止が解除された場合,「時間停止フラグ」(0x0EC700番地)が無効(0x00)になりますが,「時間停止フラグを有効にする為のフラグ」(0x0EC701番地)が有効(0x01)のままの為,直ぐに「時間停止フラグ」(0x0EC700番地)が有効(0x01)に上書きされるからです。cep等の改造ツールは,十分に短い間隔で,定期的に値を更新する(loop)からこそできる技です。

時間停止解除ボタンを押した場合は,先づ0x0EC701番地の値が0x00になり,続いて0x0EC700番地の値が0x00になります。詰り,「時間停止フラグ」を直接解除するのと同じ動作になります。

副作用

此のコードを有効にすると,STARTを押して時間停止状態にしない限り,「調査」等のコマンドで時間が止らなくなる(ことがある)ので注意が必要です。

御負

データに誤りがあったら御免なさい。