忍者ブログ

データ置き場

ニコ生RTA放送を見ていて湧いた疑問を調査してアップするかも。ほぼドラクエのみを扱うブログ風のマニアックなサイト

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

エクセル関数を使ったフィールドマップ作成の作業メモ

この記事の解析情報はほとんど参考サイトの情報を利用している。データ処理には表計算ソフトLibreOfficeを利用した。

DQ3のROMには地形の情報が1*1マスのマップパーツ毎に設定されている。地形情報は上の世界とアレフガルドでROM上の別々な場所に格納されている。マップパターンはマップパーツ(1*1マス)を16個集めたもの(4*4マス)。フィールドの全体マップ(256*256マス)のマップパターンの配置はRAM上に展開されている。



(1)フィールドマップ(256*256マス)とマップパターン(4*4マス)の配置(上の世界とアレフガルドで異なる)

取得したいフィールドに移動してRAM上のデータを取得、成形するとフィールド全体に配置されたマップパターン番号のデータ(64*64)を知ることができる。
データの先頭はマップ左上から順番に右上まで64個、次は2段目左端から右端まで3段目左端から右端まで、という風にマップ右下まで続いている。1データは2バイトで7F0000から7F1FFFまで4096個(=0x1000=64*64個)ある。
- 利用したEXCEL関数
HEX2DEC[2バイトデータを10進数へ変換するのに利用。RAMデータはリトルエンディアン],
OFFSET[8*512を64*64に成形する際row()やCOLUMN()などと一緒に利用]
ROW(), COLUMN()[引数がなければ式のあるセルの行番号や列番号を帰す]
INT(),MOD()[商や余りの取得]
- 実例
16*512の7F0000-7F1FFFからコピーしたデータ(セル範囲A1:P512)を10進数16*256のデータ(セル範囲R1:AG256)に変換
=HEX2DEC(OFFSET($A$1,(ROW()-1)*2,(COLUMN()-18)*2))+HEX2DEC(OFFSET($B$1,(ROW()-1)*2,(COLUMN()-18)*2))*256
セル範囲R1:AG256にできた16*256のデータを64*64の形式にセル範囲AI2:CT65にて変換
=OFFSET($R$1,(ROW()-2)*4+INT((COLUMN()-35)/16),MOD((COLUMN()-35),16))

(2)マップパターン(4*4)とマップパーツ(1*1マス)の配置

全体マップと同様にマップパターンにもマップパーツ番号が設定されている。2621個ある全てのマップパターンのうち、左上にあたるマップパーツ[ 0]の番号がROMアドレス0x2DA49Cからひたすら記載されている。その直後の0x2DAED9以降にもパーツ[ 1]からパーツ[15]までのデータが続く。(参考:アドレスの詳細など)
マップパターン上でのマップパーツの配置は次のよう並びになっている
[0] [1] [2] [3]
[4] [5] [6] [7]
[8] [9] [10] [11]
[12] [13] [14] [15]
ROMからマップパターン番号と16箇所のマップパーツ番号を記述した一覧表を取得する。セルのA列にマップパターン番号0-2620、B列にパーツ[ 0]のマップパーツ番号であるアドレス0x2DA49C以降のデータ、C列に0x2DAED9以降のデータと言った具合である。10進数に変換しておくと扱いやすい。

(3)マップパーツ(1*1)の地形情報(上の世界とアレフガルドで異なる)

 
表1
0 不明
1 通常
2
3 侵入不可
表2
0 草原
1  
2 砂漠
3 森林
4 毒沼
5 山地
6
7 岩山
8  
9 施設
10 氷原
11  
12  
13  
14  
15  
16  

地形情報は1バイトのデータで上の世界はROM上0x2836D8-0x2837C4、アレフガルドはROM上0x2837C5-0x283874に設定されている。
これらを取得して10進数に変換する。さらにINTやMOD関数を使ってbit 2-3(=MOD(INT(data/4),4))とbit 4-7(=INT(data/2^4))を取得する。
bit2-3は侵入不可などを記述した2*4の表1を作る。同様にbit4-7についても値と地形を書いた2*16の表2を作る。(「施設・橋」「毒沼」など)






vlookup()で表1に対応した情報を書き出す。
表1が侵入不可で表2が海に当たる場合は浅瀬になるようなので表2の情報の場合はIFを使って次のような計算式にする。
=IF(AND(table1="侵入不可",VLOOKUP(bit4to7,table2range,2,1)="海"),"浅瀬",VLOOKUP(bit4to7,table2range,2,1))

(4)マップの背景をスタイルで設定する。

表2の説明の一文字目をスタイルの名前にして背景を設定していく。(例:森林→「森」)
計算が多いので新しく2つファイルを作って、上の世界とアレフガルドの結果だけを貼り付けておく。(64*64の表、16*2621の表)
次に(3)で設定した表2の情報を利用する。
- 例
セルB2から記述を開始。
=T(STYLE(LEFT(VLOOKUP(OFFSET('patternID_UpperWorld field'!$B$2,INT((ROW()-2)/4),INT((COLUMN()-2)/4)),'map pattern_GeoInfo'!$S$3:$AI$2623,2+0,1))))
セルE5
T(STYLE(LEFT(VLOOKUP(OFFSET('patternID_UpperWorld field'!$B$2,INT((ROW()-2)/4),INT((COLUMN()-2)/4)),'map pattern_GeoInfo'!$S$3:$AI$2623,2+15,1)))
B2:E5の16個で1セットでVLOOKUP()の第3引数は別々の値となっている。
本当はさらに成形しておいたほうがいいかもしれない(動作の重さ的に)。
T [引数が文字列でなければ空の文字列を帰す。]
LEFT()[一文字目を取得]
STYLE("スタイル名")[スタイル関数で背景色を指定する]

(5)出力データ

ROMデータを元に作成したエクセルマップ(上の世界とアレフガルド)のDLリンクを貼っておく。
https://dl.dropbox.com/u/24283494/DQ3/DQ3map/dq3_map%28from_romram_data%29.xls
ただし、橋は地形情報としては施設扱いだったので赤になっている。エンカウントの歩数消費は平地と同じで256である。また、マップ切り替えのある一部の施設は赤くなっていない(エルフの里、ギアガの大穴の落ちた先にある船着場など)。3がドラクエ6のROMとそっくりな部分があり、wikiをざっと見た限りDQ6も同じ方法でフィールドマップを作成できそうである。
追記:RTAなどに利用するならこれを使うより、夢幻斎さんのブロマガで公開しているシートの方が便利。

参考サイト>

 

PR
Comment form
お名前
メールアドレス
URL
タイトル
コメント
  Vodafone絵文字 i-mode絵文字 Ezweb絵文字
パスワード
カレンダー
05 2017/06 07
S M T W T F S
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
プロフィール
HN:
bamboo
性別:
非公開
自己紹介:
2010年の3月ごろニコニコ生放送のゲーム放送でRTAを知ってよく見るようになった。
どちらかというとゲームはプレイするものじゃなくてプレイを"みる"ものだと思っている。
逆アセンブル解析というのをかじったものの放置していたが、某放送の影響で解析を再開。
2を初クリアしたのは2011.3.10。ブログの内容はSFC版ドラクエ1・2の解析がメイン。最近はjavascriptとかluaをある程度扱えるようになったので、botでルート検証とかできたらと思いつつも進んでいない。
要点をまとめたり文章書くのが苦手なので記事が長ったらしかったり、日本語のようで日本語でなかったりする。プログラム用語が使えるようになりたいかも。
ツイッター: https://twitter.com/bamb00h
ブログに公開せずツイートのみの情報もあり(twilog
バーコード
ブログ内検索
カウンター
忍者アナライズ
  Copyright 2017 データ置き場 All rights reserved.
Template Design by LockHeart|powered by NINJA TOOLS 忍者ブログ [PR]