【ARM】DQ9で学ぶARMアセンブル【逆汗】

このエントリーをはてなブックマークに追加
1名無しさん@お腹いっぱい。
・この際だから、DQ9を教材にして、ARMの勉強をしようという奇特な人たちの集うスレですw

・ソースは各自用意のこと。逆アセツールはARM用のならなんでもいいですが、
  ttp://hp.vector.co.jp/authors/VA018359/ndsdis/ndsdis2_v110.zip
 がNDS専用になってて便利です

・ソースの一部(スニペット)貼るのはいいですが、1レスに入るくらいにして、それについてきちんと
 論評なり解説なりしてください。要は「引用」にしてください

・「まるっとソースをzipでうp」とかはヤヴァいです。昔、PC-8001だかのROMを逆アセしたソースを
 出版して訴えられたバカがいますw
 繰り返しますが、ソースは各自用意のこと
2名無しさん@お腹いっぱい。:2009/08/26(水) 09:12:36 ID:fD3C5dnU
とりあえず期待
3名無しさん@お腹いっぱい。:2009/08/26(水) 09:16:26 ID:W/+sz/ts
まずはこのあたりからでしょうかね?

<引用>
:02003C30 E59F2020 ldr r2,[r15, #+0x20] ;r15+0x20=*(02003c58)=#34533008(0x020eee90)
:02003C34 E59F0020 ldr r0,[r15, #+0x20] ;r15+0x20=*(02003c5c)=#1103515245(0x41c64e6d)
:02003C38 E5923000 ldr r3,[r2, #+0x0] ;r2+0x0=*(020eee90)=#1696729393(0x65220931)
:02003C3C E59F101C ldr r1,[r15, #+0x1c] ;r15+0x1c=*(02003c60)=#32767(0x00007fff)
:02003C40 E0000093 mul r0,r3,r0
:02003C44 E2800039 add r0,r0,#0x39
:02003C48 E2800A03 add r0,r0,#0x3000
:02003C4C E5820000 str r0,[r2, #+0x0] ;r2+0x0=*(020eee90)=#1696729393(0x65220931)
:02003C50 E0010820 and r0,r1,r0,lsr #0x10
:02003C54 E12FFF1E bx r14 (Jump to addr_02003B0C?)
<ここまで引用>

各解析スレで超有名になった乱数アルゴリズムです。
高級言語で書くと

020eee90 : ←SEED

int dq9_rand(void)
{
  SEED = SEED * 1103515245 + 12345; // 0x39+0x3000=12345(10進)
  return SEED >> 0x10 & 0x7ffff; //r1=#32767(0x00007fff) at :02003C3C 行
}

x86しかわからない方でも十分想像がつくと思います。まずはこの数行を熟読w
4名無しさん@お腹いっぱい。:2009/08/26(水) 09:25:17 ID:fD3C5dnU
wがウザい
5名無しさん@お腹いっぱい。:2009/08/26(水) 09:49:08 ID:W/+sz/ts
おすすめサイトはやっぱここかな?

ttp://www.mztn.org/slasm/arm00.html

x86系ですでにアセンブラになじんでる人なら、ここのうち

 レジスタ系→ttp://www.mztn.org/slasm/arm02.html
 演算分岐→ttp://www.mztn.org/slasm/arm03.html

をザッと斜め読みするだけで、逆アセソースはだいたい把握できると思う
6名無しさん@お腹いっぱい。:2009/08/26(水) 13:00:01 ID:BoOx2FWK
ARMってDSのCPUなの?
DSのメモリマップってないの?
7名無しさん@お腹いっぱい。:2009/08/26(水) 21:04:06 ID:XF/vVIpV
これはまた興味深いスレを。 どんどん進化しますね

おすすめの書籍なんぞを

  CQ出版社、ARMプセッサ、Steve Furber著

これ20世紀の本です(2000年3月出版、邦訳は2001年初版)

もう10年以上たってますので、古本屋で低廉で買えます。しかも内容は濃いので、ディスアセ解読
くらいならこれで十分です

ふろくに"ARM Developer Suite"の評価版(45日無料)がついてます
だけど、Windows98の時代のソフトだから動くかな?
8名無しさん@お腹いっぱい。:2009/08/26(水) 21:21:37 ID:XF/vVIpV
保守ageついでに、ARMトリビアなんぞを

・ARM=Advanced Risc Machine と(今では)思われてるが、本当は、「Acorn社のRisc マシン」の略(上記本p39)

・上のほうのリンクにもあるとおり、ARMのレジスタはR0〜R15の16個(このほかステータスレジスタ)。
 うち、R15はプログラムカウンタ(インストラクションポインタ)。それ以外は設計上等価だが、R13はスタックポインタ、R14
 はリターンアドレス用(リターンアドレスは、自動的にはスタックポインタにはセーブされない)

・こういう仕様だから、リカーシブルな関数とかは、直感的には書けない。また、子サブルーチンから孫ルーチンにそのまま
 飛ぶとR14レジスタが上書きされて帰ってこれない _| ̄|○

・サブルーチン「呼ぶ」のは、call 命令ではなくて、「ブランチアンドリンク」。IBM・DECっぽい。ニーモニックはBL

・戻るときは、ブランチなんとせず

      mov r15 , r14

 とやるのがARM風味。ただし、DQ9はソース見てわかるとおり、bx r14 という26ビットアドレスバス時代をしのばせる記法

・上記のネックがあるんで、リカーシブル関数とか孫ルーチンに飛ぶには、

   STMFSD r13! , (r0-r5 , r14)

 とかして、ドサっとスタックに積むのがイディオム。 r13! のビックリマークは、必要数×4だけr13を加算するの意

・戻すときは

   LDMFD r13! . (r0-r5 , r15) ;; ←r14でなくてr15

これで、自動的に@スタックの内容をレジスタに戻して、A親ルーチンに帰ります
 実にARMだ
9名無しさん@お腹いっぱい。:2009/08/26(水) 23:52:04 ID:dG3cqiXu
ndsdisだとthumb命令の逆汗が出来ないんじゃ無かったっけ?
10名無しさん@お腹いっぱい。:2009/08/27(木) 08:14:32 ID:MOLS2Dqy
11名無しさん@お腹いっぱい。:2009/08/27(木) 08:49:17 ID:u9k+Kg9o
>>6
> ARMってDSのCPUなの?

そだお(・∀・)

メインは、ARM946E-S 67MHz
だけど、アドバンスとの互換性を保つため、もう1個ARM7TDMI 33MHzってのを積んでる贅沢
仕様

ゲームボーイはZ80だったんだお(・∀・)




だけど助かるわーこういうスレ
まじめに勉強するほどじゃないけど、ARMもそれなりに読めるようになりたかったし

マジメな演習プログラムとかやる気にならないけど、ドラクエなら趣味と実益をかねて( ^ω^) 
12名無しさん@お腹いっぱい。:2009/08/27(木) 12:30:36 ID:WwWBRtpN
DQNは興味ないが、ARM解析なら乗った。ということで、遅ればせながらひととおりやってみた。。。

・まずソフトはちゃんと買うこと。これ常識。遊び用と解析用に2本買えば満点。
・その上で、ROMの用意。
 吸い出せれば良し。あるいは「3966 Dragon Quest IX - Hoshizora no Mamoribito (JP)」あたりで
 ググれば幸せになれるかも。これ以上は聞くなw
・エミュを用意する。この世界に慣れてない人は「エミュっ!?」と思われるかもしれんが、クロス(逆)アセンブラ
 付きのデバッガだ。
 場所はここ→http://desmume.org/download/
・DSエミュ用オンラインメモリエディタ haste を用意する。
 場所はここ→http://hp.vector.co.jp/authors/VA018359/nds/hasteds_v130.zip
 まっ、86系統でいう、「うさみみハリケーン」だ。
・エミュを立ち上げる。File→ROM open でDQ9のROM指定。なんの問題もなく立ち上がるはず。
・適当なタイミング(初期値のメモリ展開終わった程度)でhaste起動。
・わかりにくいが、右上の[メモリダンプ(DUMP)]はボタンになってる。バイナリダンプする。
・1で紹介されてる逆汗ツールで、可読ニーモニックに戻して解読。

この世界、ROMファイルから直接逆汗しても理解不能だと思う(通常)。
136:2009/08/27(木) 13:17:19 ID:3ZQhGFCZ
ありがたや。デバッガもあるのか。
ここまで資料ならべてもらえれば、なんとでもなりそうだな。
14名無しさん@お腹いっぱい。:2009/08/27(木) 13:50:06 ID:sTdXA0Xj
>>13
ところがどっこいw ARM系の(フリーの)ディスアセンブラは機能がプアでクロスレファも取れないんだなwww
つうことで、ndsdis2のはき出す逆ソースを食って参照関係をファイルに書き出すスクリプトを作った

open IN,'<ソースファイル名>';

while(<IN>){
  chomp;
  ($label,$code,$mnemo,$jadr,$rest)=split;
  next if ($mnemo ne 'bl');

  #print"DEBUG : $mnemo $jadr $rest\n";
  $HASH{$jadr}.=$label;
}

open OUT,'>dq9_xref.txt';
foreach $key (sort keys %HASH){
  print OUT "$key is called by $HASH{$key}\n";
}

とりあえずは、bl (x86でいうところの call命令)部分だけだが、ほかがみたければ、while ループの
なかの3行目いじっってくれやw
15名無しさん@お腹いっぱい。:2009/08/27(木) 13:52:06 ID:sTdXA0Xj
乱数ルーチンあたりからおっかけるとしたら、ここだな


00003C30 is called by :0001E83C:0001E934:0002DE2C:00031E7C:00031EB0:00031F08
  :0003CCEC:000409CC:00041220:00041330:00041630:000416E4:000487B8:000574F4
  :0005756C:0005758C:000575AC:00057B60:00057B9C:00057C1C:00057C58:00057CD8
  :00057D14:00059DC4:00059F44:0005A110:0005A418:0005A468:0005A5DC:0005A654
  :0005A6DC:0005A778:0005A87C:0005A930:0005AA24:0005AA54:00074B4C:00079A80
  :00079B00:00079ED4:0008F34C:0008F7A0:0008F7E0:0008F810:0008FBD4:00090FAC
  :00091030:00092F48:0009D22C:0009D2C4:0009D338:0009D35C:0009D3D0:0009D3F4
  :0009D468:000A5C08:000A5E80:000A6488:000A650C:000A69C4:000A796C:000A7B68
  :000A7C7C:000B071C


ふぅ。結構あるなぁwww
16名無しさん@お腹いっぱい。:2009/08/27(木) 14:59:32 ID:64Iak7lP
うーん。わからん
F3BCあたり(環境によっては、0200F3BC になるのかな?)

引用@> :0000F3BC E1A04000 mov r4,r0
引用A> :0000F3C0 E3A00000 mov r0,#0
引用B> :0000F3C4 E2400001 sub r0,r0,#1
引用C> :0000F3C8 E0040000 and r0,r4,r0

パッっと見、r0をなんかでマスクして、またまたr0に戻しているのだが、よく読むと

@ r4 = r0;
r0の内容を待避している。うむ。これは良い

A r0 = 0;
これも自明(r4とr0の使い方、逆にしろよ、とは思うが。笑)

B r0 = r0-1;
 あれれ?これじゃ、r0が、0xFFFF FFFF になってしまう?

C r0 = r4 & r0;
32ビット系マシンで、0xFFFFFFFFとANDって事実上NOPじゃん(笑)

上位コンパイラがお馬鹿なコードを吐いただけ?
ARMのやることはよくわからん
17名無しさん@お腹いっぱい。:2009/08/28(金) 16:10:13 ID:6pwLRL40
どうみても高級言語で書いてそのまま最適化とかしてない感じだよなー
アセンブラがわかる人が手を入れた形跡なしw

あるいは「動いてるコードをいじるなー」ポリシーのプロジェクトリーダかも?
18名無しさん@お腹いっぱい。:2009/08/28(金) 16:27:49 ID:6pwLRL40
■宝の地図作成ルーチンについて(説明)

A5DF0〜
・基本乱数関数3C30を使用
> :000A5E80 EBFD776A bl 00003C30 ; r0=dq9_rand();

・呼び出し側(親ルーチン)は、:000A59B8

> :000A59AC E1DA11BA ldrh r1,[r10, #+0x1a] ; 16bit(SEED)
> :000A59B0 E5DA2017 ldrb r2,[r10, #+0x17] ;8bit(rank)
> :000A59B4 E289004C add r0,r9,#0x4C ;r0=r9+0x4c ベースアドレス
> :000A59B8 EB00010C bl 000A5DF0

・子A5DF0は、呼び出されると、レジスタ類をスタックに待避させ、

> :000A5DF0 E92D4070 stmdb r13!,{r4,r5,r6,r14}
> :000A5DF4 E1A06001 mov r6,r1//SEED
> :000A5DF8 E1A05002 mov r5,r2//rank

r5とr6にランク・SEEDを入れ、SEED値をセットする。

:000A5E14 EBFD7792 bl 00003C64//setSEED(r0);

宝地図の名前を算出([r4, #+5〜#+5]に格納)した後、

:000A5E80 EBFD776A bl 00003C30

乱数を生成。次にr1に11をセットして、その余りを計算(乱数を縮退させるときに
地図関係のように剰余を使う場合と、宝箱アイテムのように32767に対するパーセント
を用いる場合とが混在している。開発チームによってバラバラなのだろうか?)

> :000A5E84 E3A0100B mov r1,#0xB ;r1=11(0xb)
> :000A5E88 EBFD9BDE bl 0000CE08

この乱数を使って所要の計算をした後、マイナスならばレベル1に、99を超えてしまったら
99にする・・・のだが、

> :000A5E9C E3500000 cmp r0,#0x0
> :000A5EA0 D3A00001 movle r0,#0x1
> :000A5EA4 D5C40019 strleb r0,[r4, #+0x19]
> :000A5EA8 DA000003 ble 000A5EBC
> :000A5EAC E3500063 cmp r0,#0x63
> :000A5EB0 C3A00063 movgt r0,#0x63
> :000A5EB4 C5C40019 strgtb r0,[r4, #+0x19]
> :000A5EB8 D5C40019 strleb r0,[r4, #+0x19]

どうみても、コンパイラがはきだしたコードそのまんまw 全くARMの良さがいかされてない
(こういうときに ble 000A5EBC などという無駄な分岐しないのがARM流)
19名無しさん@お腹いっぱい。:2009/08/28(金) 16:32:44 ID:6pwLRL40
■setSEED関数
 r0の値を、[020EEE90番地]に収納するだけ。基本乱数関数 3C30 のすぐ下

> :00003C64 E59F1004 ldr r1,[r15, #+0x4]  ; r15+4=*(00003c70)=0x020eee90
> :00003C68 E5810000 str r0,[r1, #+0x0]  ; ;r1+0=020eee90
> :00003C6C E12FFF1E bx r14 ; return
>
> :00003C70 020EEE90 ; data word(定数)
20名無しさん@お腹いっぱい。:2009/08/28(金) 17:14:03 ID:CHoBpjoD
データ入れ替えてスライムをクリボーにして遊んでみた。
21名無しさん@お腹いっぱい。:2009/08/28(金) 19:15:27 ID:WL1Vasyh
ダンジョンの入り口を決める方法が全然分からない(´・ω・`)
22名無しさん@お腹いっぱい。:2009/08/28(金) 21:05:54 ID:5S3UdeAh
>>17
おまいの引用した、0000CE08関数見てみ?
どうみてもコンパラじゃねぇから (こんなアフォなコードはき出すコンパイラはないわ)

なんせ

:0000CE7C E0B13083 adcs r3,r1,r3,lsl #0x1
:0000CE80 30433001 subcc r3,r3,r1
:0000CE84 E0B00000 adcs r0,r0,r0

が96回貼ってあるから(爆)
たしかに

:0000CE70 E0822082 add r2,r2,r2,lsl #0x1
:0000CE74 E08FF102 add r15,r15,r2,lsl #0x2

で、R2×12バイト飛ばせるのはARMらしいが、それにしても
馬鹿だろ?このプラグラマ

テクニックの使い方、間違えてる
23名無しさん@お腹いっぱい。:2009/08/28(金) 22:39:07 ID:M/slVEuk
おまいら、そんなガセ流してたら、風評の流布で訴えられるんぞ・・・・















・・・と思ってソースみたらw


ちょwww おまwwww
まじで、96行コピペかよww

しかもその次のファンクション(0200D014〜)96行コピペwwww

まじで、■eの将来が心配になってきたwww
24名無しさん@お腹いっぱい。:2009/08/28(金) 22:52:24 ID:M/slVEuk
しっかし、剰余なしプロセッサとて
(a÷b)演算くらい

i = !(a >> 8) ? 8 : !(a >> 16) ? 16 : !(a >> 24) ? 24 : 32;
do {
   if ( (a >> --i) >= b ) a -= ( b << i ) , shou += (1 << i) ;
} while (i);

こんくらい常識だべ?
96行貼っても全然これより早くなってないというwwwww

これで「メモリ空間が小さすぎて」とかホザいたら、任天堂激怒だぜw
25名無しさん@お腹いっぱい。:2009/08/28(金) 22:56:22 ID:9fsP8qV9
>>18
どうやってそのルーチンのアドレスを見つけたのか後学の為に教えて欲しい。
26名無しさん@お腹いっぱい。:2009/08/28(金) 23:11:55 ID:UwgCOcqR
>>22
そのあたりのコードが厨なのは、一目でわかるが、

>:0000CE7C E0B13083 adcs r3,r1,r3,lsl #0x1
>:0000CE80 30433001 subcc r3,r3,r1
>:0000CE84 E0B00000 adcs r0,r0,r0

を96回(3ステップ*32回)繰り返すとなぜ割り算ができるのか、教えてくれ、エロい人。
アセンブラについての知識はひととおりある(つもりだ)。
27名無しさん@お腹いっぱい。:2009/08/28(金) 23:21:26 ID:lvb+fVhd
>>22
SPARC用コンパイラとかは最適化オプション弄ると
ループを展開したコード出すけどね。
ARM用は違うん?よく知らんのだけど。
28名無しさん@お腹いっぱい。:2009/08/28(金) 23:32:23 ID:UwgCOcqR
>>21
入口って?

 意味1)世界地図上の場所
  つまり、第一地図であれば、(BYTE)0F96A3 の値

 意味2)各フロアにおける上り階段/下り階段の位置

どっちの意よ?
29名無しさん@お腹いっぱい。:2009/08/29(土) 00:14:02 ID:cHPZAF9W
>>28
1っす。
もしかしてRANKかSEEDから場所は一意に決まります・・・?
だとしたら今までどこ見てたんだって感じなんで吊ってきますがorz'
30名無しさん@お腹いっぱい。:2009/08/29(土) 05:51:31 ID:gmHBTR15
>>29
宝の地図スレで場所の解析がでてるよ
31名無しさん@お腹いっぱい。:2009/08/29(土) 09:50:15 ID:snLNCA8B
NDS用のブレークポイントが設置できるデバッガってありますか?
今までx86でゲームの解析をやっていたのですが、いつもブレークポイント置いてごにょごにょ、って言う風にやっていたのでブレークポイントが設置できないとなるとどうすればいいのか皆目見当が付かないのです。
no$gbaのdebuggerバージョンが設置できるようなのですが現在購入できないみたいで。
NDebugsも設置できるようなのですが配布してないのです。
ttp://home.usay.jp/pc/etc/nds/ndebugs.jpg
仕組みが分かれば自分で作れるのですが。
ご教示いただければ幸いです。
32名無しさん@お腹いっぱい。:2009/08/29(土) 10:51:31 ID:EonqsAGr
>>30
あれホントなの・・・?
33名無しさん@お腹いっぱい。:2009/08/29(土) 14:24:11 ID:d52umB0e
>>26
DQNはさっぱりわからんが、組み込みプログラマならそれ常識。

・まずARMとかRISKプロセッサでは、通常、除算回路はない。
・したがって、自分で除算ルーチンを用意する必要がある。たとえば、「引き算を繰り返す」でも
 良い(決して恥ずかしいことではない。ケースによってはその方が良いこともある。可読性)
・通常は、10進の筆算と同じように桁どりをして、頭の方から引き算をして残りを桁取りして
 いくことになる。ただし、10進の場合、「かけ算九九」でいくつまで引けるか暗算するが、
 2進のときは「引けるか(1)、引けないか(0)」二者択一。
・用意するのは、割られる数(R0)、割る数(R1)、商を入れるとこ(R3。初期化時点では
 ゼロにしておく)、余りを入れるとこR4。ただし、この事例ではトリッキーに(高速化を図る
 べく)、R0を再利用していく。
・だいたいのイメージはこんな感じ。@R0をシフト(R0=R0+R0;)して、一番右をキャリービット
 へ。AそれをR3に左から流し込む(R3=R3<<1+C;)。BR3のベルトコンベアwみて、
 R11より大きくなったら、R11を引く。上記のとおり2回以上引けることはない。このことは直感的
 に「前回(シフトする前だからだいたい半分)引けなかったのだから、2回以上引けるはずがない」
 と理解。C以上を32ビット分=32回(各3ステップだから全部で96ステップ)繰り返せばよい
・なお、先頭数ビットがゼロビットのときはやる必要がなく、冒頭からスキップできる。RISKではそれを
 調べるべく、CLZ(カウント・リーディング・ゼロ)という命令がある(おそらく、CLZ使わずにジャンプ
 テーブルを使った点が馬鹿にされてる所以か?)。

・コードをみよう。
 「96回」の前に必ず、
>:0000CE84 E0B00000 ads r0,r0,r0
があるはず。ここで先頭1ビットをキャリーに入れて1ビットシフト。

@1行目
>:0000CE7C E0B13083 adcs r3,r1,r3,lsl #0x1
足し算に見えるが、R1は符号反転してるはず。R3からとりあえずR1を引く
A2行目
>:0000CE80 30433001 subcc r3,r3,r1
「アセンブラについての知識はひととおりある」そうなので、補数表示はわかるよな?符号反転したR1
とR3を「足しこんで」(セマンティクには、R3からR1を引くのだがw)、キャリーがたつのは、R1補数
がオーバーフローして「正の数」になったときのみ。したがって、元R1<=R3のときのみCが立つ
だから、CC(キャリ無し)のとき、つまり、元R1>R3のときA発動で足しもどす。つまり@の引き算
を無かったことにする。
B3行目
>:0000CE84 E0B00000 adcs r0,r0,r0
ここではふたつのことをやってる。
・まず、R0をシフトして、先頭ビットをキャリーに保管する。つまり、次のループの準備。
・@で立ったキャリー(つまり商)をR0に流し込む。

これで、割られる数であるR0から1ビットずつ絞りとりながら、商を先頭ビットから流し込んでいる。

しかし、割られるレジスタと商のレジスタが同じである必要はないのだから、つまらんとこで可読性を
犠牲にして、1ステップ節約、1レジスタ節約する必然性は乏しい。総じてあまりよくないプログラム
と思われる。
34名無しさん@お腹いっぱい。:2009/08/29(土) 15:04:35 ID:elFB2IVx
>>33
> ・だいたいのイメージはこんな感じ。@R0をシフト(R0=R0+R0;)して、一番右をキャリービット
>  へ。AそれをR3に左から流し込む

左右が真逆。左効きの人?w
それとも「ビットレベル・リトルエンディアン・レジスタ」のマシンとかあるのか?
35名無しさん@お腹いっぱい。:2009/08/29(土) 15:28:30 ID:AC5E0+0P
地図の場所

>乱数シード設定後、2番目の乱数で地図のSEED、3番目の乱数で場所決定
>ランクが高いと
>場所 = rand() % 150 + 1

だそうだ。
36名無しさん@お腹いっぱい。:2009/08/29(土) 16:03:09 ID:Czn63REn
>>20
kwsk
37名無しさん@お腹いっぱい。:2009/08/29(土) 17:28:08 ID:6ArE8IEt
ま、こっちは真実・実証系でまたーり逝こうぜ
落ち着けage
38名無しさん@お腹いっぱい。:2009/08/29(土) 20:12:59 ID:MPLbSfCc
39名無しさん@お腹いっぱい。:2009/08/29(土) 21:17:20 ID:gmHBTR15
>>35
そのルーチン見つけた
そこで使われてる初期乱数シードは0x04000100から16bit持ってきているんだけど
ここってどんな値かわかる人いる?
40名無しさん@お腹いっぱい。:2009/08/29(土) 22:49:25 ID:ZsCQcOb4
そこはタイマー0のカウンタの場所だね
41名無しさん@お腹いっぱい。:2009/08/29(土) 23:02:27 ID:ShY4pj8F
>>35
ん? ランクが高いと場所が一意に決まる・・・だと?
42名無しさん@お腹いっぱい。:2009/08/29(土) 23:10:23 ID:gmHBTR15
>>40
ほう、それではそのタイマーを把握できれば好きな地図を
だせるってことだね
単位は秒なのかな?

>>41
1つの乱数シードに対して場所が一意に決まる
擬似乱数だから当たり前だけど
43名無しさん@お腹いっぱい。:2009/08/29(土) 23:17:10 ID:le7BSvnW
ランクが高いってのはB5以上ってことなのかな
まだ見つかんないけど
44名無しさん@お腹いっぱい。:2009/08/29(土) 23:36:33 ID:bw6d/XGs
>>42
その式が正しいとするとSEEDから求められる
場所の候補は1ヵ所になるよね。おかしくね?
45名無しさん@お腹いっぱい。:2009/08/29(土) 23:38:37 ID:gmHBTR15
地図の取得時の関連ルーチン

:021AA270
この関数内で乱数シードの設定をして、マップ生成のルーチンを呼んでる

:020CA8C8
0x04000100の値をwordで取得

:020A7C20
普通の地図生成
地図のSEEDは0xFFFFの範囲で乱数を取り出そうとしてるんで、
乱数そのまま

:020A7CA0
魔王の地図生成

:020A7A5C
RANK生成関数、地図スレで出ている式がここにある
もう一つの式、レベル*1.5+転生*5はイベント用?

:020A7BB4
場所生成関数、RANKによって3つの範囲の乱数を取り出している
0x51以上のRANKで1-150だね

最初の乱数シードの設定が16bitしかなく地図のSEED数に対してパターンが
少なすぎるのが、場所が少数に特定されてしまう原因だね
46名無しさん@お腹いっぱい。:2009/08/29(土) 23:40:57 ID:gmHBTR15
>>44
最初の乱数シードで地図のSEEDと場所が一意に決まる
同じ地図SEEDになる別の初期乱数シードがあれば場所は別になる
乱数シードと地図のSEEDをごっちゃにしないように
47名無しさん@お腹いっぱい。:2009/08/29(土) 23:50:00 ID:AC5E0+0P
>>46
初心者が質問してすまない

最初の乱数シードと地図用のSEEDが別物なら
地図のランクと地図用のSEEDから地図の割り出しするのって無理じゃないの?
48名無しさん@お腹いっぱい。:2009/08/30(日) 00:05:33 ID:AiISSJOy
>>47
最初の乱数シードが0から0xffffまでしかないので、
総当りで地図SEEDと場所の組み合わせを出せる

ようするに全ての可能性を羅列しても65536通りしかないってこと
地図SEEDは32768通りあるので、全ての可能性のなかから
ある地図SEEDを探しても2個ぐらいしか見つからない
49名無しさん@お腹いっぱい。:2009/08/30(日) 00:32:21 ID:7OhnrR8A
>>48
レスありがとう
つまり、ある地図シードから逆算される乱数シードは
65536通りの乱数シードのうちの1〜2個になるから
その乱数シード%150+1から特定できる場所が1・2カ所になるんだね

ということは、乱数シードから地図シードをどう生成しているのかが
理解できれば場所がわかるわけだ

ここまでは理解できて,おそらく>>18>>45をみればわかる人にはわかるんだろうね
自分はもうちょっと勉強しないとわからなさそうだ
50名無しさん@お腹いっぱい。:2009/08/30(日) 00:40:15 ID:zSO7wRwR
>>48
理解が間違ってたらゴメン
場所を解析する手順としては
1.ランクと地図シードから初期シードを総当たりで求める
2.初期シードから場所を求める
という感じ?
51名無しさん@お腹いっぱい。:2009/08/30(日) 00:50:53 ID:AiISSJOy
>>49,50
手順としては、

1) 65536通りの乱数シードから実際のルーチンと同じ手順で65536枚の地図をつくってしまう
2) その中からほしい地図を探す

これが一番単純で分かりやすいかな
52名無しさん@お腹いっぱい。:2009/08/30(日) 02:39:56 ID:HYFwNEFU
>>45
低レベルな質問で非常に申し訳ないのですが、それらのルーチンのアドレスはどのように発見されたのか教えていただけませんか?
53名無しさん@お腹いっぱい。:2009/08/30(日) 03:09:13 ID:AiISSJOy
>>52
ここで出ている剰余を出すルーチンとランダムを使った、
範囲ランダムを出すルーチン020A5BFCを見つけていたので、
このルーチンを1-150で呼んでるところ(rand()%150+1の部分)を探して
そこからは順に呼び出しているとこを探していってって感じかな
知ってるルーチンが多いほど解析がやりやすくなる

たとえば>>45で出した021aa270を呼んでいるところをさかのぼれば
戦闘終了時のアイテムドロップ処理が見つかるかも知れん
54名無しさん@お腹いっぱい。:2009/08/30(日) 03:21:24 ID:HYFwNEFU
>>53
なるほど。こんな低レベルな質問に答えて頂きありがとうございます!
55名無しさん@そうだ選挙に行こう:2009/08/30(日) 09:57:23 ID:Fm80ovuo
セーブデータの書き込みってswiで何番を叩いてるの?
56名無しさん@そうだ選挙に行こう:2009/08/30(日) 10:32:27 ID:dWoq4Cke
mapSEED と (rank, location)とは関係ないね

(:021AA270関数からみて)mapSEEDは、外生変数で r3 で渡される。
rank と location は中断秒数をSEEDにして、2回乱数をふる。

関係あるといえば関係あるだろうけど、rank → location に関数関係はないね。およそ「場所はランダム」
という理解でいいと思う。

以上の事実をソースで
57名無しさん@そうだ選挙に行こう:2009/08/30(日) 10:39:26 ID:dWoq4Cke
失礼。途中通信しかもアゲてしまった。最低w

>:021AA270 E92D4070 stmdb r13!,{r4,r5,r6,r14}
>:021AA274 E24DD008 sub r13,r13,#0x8
>:021AA278 E1A04000 mov r4,r0
>:021AA27C E1A06002 mov r6,r2
>:021AA280 E5C4130D strb r1,[r4, #+0x30d]
>:021AA284 E284000A add r0,r4,#0xA
>:021AA288 E3A01000 mov r1,#0x0
>:021AA28C E3A0201C mov r2,#0x1C
>:021AA290 E1A05003 mov r5,r3 ← ■r3 はmapSEEDでここでr5に待避
>:021AA294 EBFC8771 bl 020CC060
>:021AA298 E2840028 add r0,r4,#0x28
>:021AA29C EBFBEF17 bl 020A5F00
>:021AA2A0 EBFC8188 bl 020CA8C8 ←★ r0=getTimer();
>:021AA2A4 EBF9666E bl 02003C64 ← ★ setSEED(r0); >>19参照
>:021AA2A8 E5D4030D ldrb r0,[r4, #+0x30d]
>:021AA2AC E3500001 cmp r0,#0x1
>:021AA2B0 1A000009 bne 021AA2DC
>:021AA2B4 E1A01006 mov r1,r6
>:021AA2B8 E1A02005 mov r2,r5 ←■さっき、r5に待避したmapSEED値をr2に積む
>:021AA2BC E284000A add r0,r4,#0xA
>:021AA2C0 EBFBF656 bl 020A7C20 ← ■マップ生成関数(mapSEEDは、r2で与える=計算はしない。
  rank と location はこの関数内で乱数から生成)

rank と locationは、★時点で乱数SEEDいれかえて計算するから、中断技類似のテクで意図的に
かえられる可能性はある。戦闘終了時点だから難しいとは思うが。。。
58名無しさん@そうだ選挙に行こう:2009/08/30(日) 10:41:48 ID:7OhnrR8A
ということは地図同じで場所同じなんていうのは
よっぽどの偶然か発見者改変という理解でOK?
59名無しさん@そうだ選挙に行こう:2009/08/30(日) 10:42:58 ID:dWoq4Cke
■ getTimer(void) 関数

引数: 無し
戻り値: 中断後の秒数を返す。ハーフワード(16bit)。

プロシージャ部
>:020CA8C8 E59F0004 ldr r0,[r15, #+4] //r15+0x4=*(020ca8d4)=0x04000100
>:020CA8CC E1D000B0 ldrh r0,[r0, #+0] //r0=HarfByte[0x04000100]
>:020CA8D0 E12FFF1E bx r14  //return;

データ部
>:020CA8D4 04000100
60名無しさん@そうだ選挙に行こう:2009/08/30(日) 10:49:44 ID:dWoq4Cke
■地図情報・データ構造

このあたり、PAR厨の方が詳しいと思うがw

baseから(各地図baseは+0x1c × 最大 0x63枚)

+0x00 発見フラグ(09未発見、0A発見済み、0Cクリア済み)

+0x01〜0x0A 発見者氏名全角5文字
+0x0B〜0x14 更新者氏名全角5文字

+0x15 場所←■
+0x16 ドロップ確率表示
+0x17 rank←■

+0x18 unknown
+0x19 unknown

+0x1a mapSEED(2バイト)
+0x1b mapSEED(2バイト)


なお、0x18〜0x19 の unknown は、「あまり意味がない」とういだけで、魔王ボス名とか
最短討伐回数あたりで本気出して調べればすぐわかる(が興味なしw)
61名無しさん@そうだ選挙に行こう:2009/08/30(日) 10:50:24 ID:AiISSJOy
>>57
r3に0以外の数値が渡された場合はそうなるね
戦闘終了時に呼び出されるときはr3が0なので、020a7c20内で乱数を取得してるよ
r3に値が入るときはrank、場所の数値も一緒に渡される
地図もらったときや最初の地図の処理かな?
62名無しさん@そうだ選挙に行こう:2009/08/30(日) 11:12:06 ID:dWoq4Cke
失礼。レス57で、r2(外生 rank値もパラレルに r6 に待避して↓この関数に「外から」与えているね)
ますます、場所とランクは関係ないっぽい(ただし、ランクが乱数上限を形成することは後述)。

■ MapSeedRankLocationSet( ) 関数
このうち、rank値は、r1で、mapSEED値は、r2 で外生的に与えられる
r0 は地図情報構造のbaseアドレス

>:020A7C20 E92D4070 stmdb r13!,{r4,r5,r6,r14}
>:020A7C24 E1A05001 mov r5,r1
>:020A7C28 E1A04002 mov r4,r2 //mapSEED(外生)を r4 に待避
>:020A7C2C E1A06000 mov r6,r0
>:020A7C30 E3A01000 mov r1,#0x0
>:020A7C34 E3A0201C mov r2,#0x1C
>:020A7C38 EB009108 bl 020CC060
>:020A7C3C E1A00006 mov r0,r6
>:020A7C40 E3A01001 mov r1,#0x1
>:020A7C44 EB000038 bl 020A7D2C
>:020A7C48 E1A00006 mov r0,r6
>:020A7C4C E3A01001 mov r1,#0x1
>:020A7C50 EB000052 bl 020A7DA0

【rank処理】
>:020A7C54 E3550002 cmp r5,#0x2
>:020A7C58 3A000002 bcc 020A7C68 //外生rank<2 なら再計算
>:020A7C5C E35500F8 cmp r5,#0xF8 //外生rank>0xf8 なら再計算
>:020A7C60 95C65017 strlsb r5,[r6, #+0x17]  //範囲内ならばそのまま[0x+17]へ
>:020A7C64 9A000001 bls 020A7C70

>:020A7C68 EBFFFF7B bl 020A7A5C //エラー処理rank再計算
>:020A7C6C E5C60017 strb r0,[r6, #+0x17]

【mapSEED処理】
>:020A7C70 E3540000 cmp r4,#0x0
>:020A7C74 11C641BA strneh r4,[r6, #+0x1a]←■さきほど待避したmapSEED(ハーフバイト)を[+0x1a〜+0x1b]へ if (r4!=0);
>:020A7C78 1A000003 bne 020A7C8C //分岐 if (r4!=0);

>:020A7C7C EBFD6FEB bl 02003C30←mapSEED==0 のときのエラー処理(再計算)
>:020A7C80 E59F1014 ldr r1,[r15, #+0x14]
>:020A7C84 EBFD945F bl 0200CE08
>:020A7C88 E1C611BA strh r1,[r6, #+0x1a]

【location処理】
>:020A7C8C E5D60017 ldrb r0,[r6, #+0x17] // r0=rank;
>:020A7C90 EBFFFFC7 bl 020A7BB4    //■location 計算→r0
>:020A7C94 E5C60015 strb r0,[r6, #+0x15] //r0(場所情報)を[+0x15]へ
>:020A7C98 E8BD8070 ldmia r13!,{r4,r5,r6,r15}

データ部
>:020A7C9C 0000FFFF
63名無しさん@そうだ選挙に行こう:2009/08/30(日) 11:20:14 ID:AiISSJOy
おっと間違い、場所の数値は引数にはなかったね

>>62
:021AEAA4
ここから呼ばれるときに、r1=1(通常地図),r2=r3=0で地図の生成ルーチンが動くよ
64名無しさん@そうだ選挙に行こう:2009/08/30(日) 11:25:05 ID:dWoq4Cke
■ location( r1: Rank) 関数
戻り値: r0=場所値(1〜0x96=160:十進)

>:020A7BB4 E92D4008 stmdb r13!,{r3,r14}
>:020A7BB8 E3500051 cmp r0,#0x51
>:020A7BBC 3A000007 bcc 020A7BE0
>:020A7BC0 E35000F8 cmp r0,#0xF8
>:020A7BC4 8A000005 bhi 020A7BE0 //あり得ないと思うがw

【Rank >= 0x51】
>:020A7BC8 E3A00001 mov r0,#0x1 ;r0=1(0x1)
>:020A7BCC E3A01096 mov r1,#0x96 ;r1=150(0x96)
>:020A7BD0 EBFFF809 bl 020A5BFC // 1〜150の範囲で乱数を振る
>:020A7BD4 E1A00800 mov r0,r0,lsl #0x10
>:020A7BD8 E1A00820 mov r0,r0,lsr #0x10   // 上位16bitクリア
>:020A7BDC E8BD8008 ldmia r13!,{r3,r15}  //RETURN

【Rank >= 0x33】
>:020A7BE0 E3500033 cmp r0,#0x33
>:020A7BE4 3A000007 bcc 020A7C08
>:020A7BE8 E3500050 cmp r0,#0x50
>:020A7BEC 8A000005 bhi 020A7C08
>:020A7BF0 E3A00001 mov r0,#0x1 ;r0=1(0x1)
>:020A7BF4 E3A01083 mov r1,#0x83 ;r1=131(0x83)
>:020A7BF8 EBFFF7FF bl 020A5BFC   //1〜131の範囲で乱数を振る
>:020A7BFC E1A00800 mov r0,r0,lsl #0x10
>:020A7C00 E1A00820 mov r0,r0,lsr #0x10   // 上位16bitクリア
>:020A7C04 E8BD8008 ldmia r13!,{r3,r15}  //RETURN

【Rank それ以下】
>:020A7C08 E3A00001 mov r0,#0x1 ;r0=1(0x1)
>:020A7C0C E3A0102F mov r1,#0x2F ;r1=47(0x2f)
>:020A7C10 EBFFF7F9 bl 020A5BFC   //1〜47の範囲で乱数を振る
>:020A7C14 E1A00800 mov r0,r0,lsl #0x10
>:020A7C18 E1A00820 mov r0,r0,lsr #0x10   // 上位16bitクリア
>:020A7C1C E8BD8008 ldmia r13!,{r3,r15}  //RETURN
65名無しさん@そうだ選挙に行こう:2009/08/30(日) 11:26:31 ID:dWoq4Cke
>>63
失礼。必ずしもエラーではなくて、r2=r3=0 でサイコロを振らせる場合がある訳ですね。理解
66名無しさん@そうだ選挙に行こう:2009/08/30(日) 11:34:51 ID:dWoq4Cke
■範囲乱数関数
r0(下限値)〜r1(上限値)までの値を返す関数。基本関数は何度も出てるレス3の int dq9_rand(void) を使用

>:020A5BFC E92D4038 stmdb r13!,{r3,r4,r5,r14}
>:020A5C00 E1A05000 mov r5,r0 //r5=下限値
>:020A5C04 E1A04001 mov r4,r1 //r4=上限値
>:020A5C08 EBFD7808 bl 02003C30//■ここでdq9_rand()を振って、乱数(0〜32767)を生成
>:020A5C0C E0441005 sub r1,r4,r5 //r1=上限値-下限値; つまり「差分」
>:020A5C10 E2811001 add r1,r1,#0x1 //r1++;
>:020A5C14 EBFD9CFE bl 0200D014//■このスレで評判の悪い単純割り算w
>:020A5C18 E0850001 add r0,r5,r1  // つまり、r0=下限値+(生乱数 % (差分+1) )
>:020A5C1C E8BD8038 ldmia r13!,{r3,r4,r5,r15}

さほど複雑ではないと思うが念のため。


(具体例)
たとえば、r0=1、r1=150のとき、

@乱数を振って、0〜32767の乱数を得る
A上限-下限+1 でそれを割って余りを出す。したがって、余りは、0〜149
Bそれを下限値1に足す→答えは1〜150
67名無しさん@そうだ選挙に行こう:2009/08/30(日) 12:04:41 ID:ryufjHM8
つまり地図の場所出すときには
改めてもう一度かき混ぜてるってこと?
68名無しさん@そうだ選挙に行こう:2009/08/30(日) 12:50:25 ID:0tnXTAQa
地図生成依頼(r2=0, r3=0)で call <57のルーチン>

・秒数で乱数シード再セット(しがって以下は、この時点での秒数のみに依存)
したあと、

・ランク処理(ここで1回乱数計算→次の乱数シード確定)
・マップシード処理(ここで1回乱数計算→次の乱数シード確定)
・ロケーション処理(ここで1回乱数計算)
の順番で計算

だから、中断秒数→ランク、マップ、ローケションの組み合わせが65536通り計算できる。

このうち、マップシド処理(乱数関数の値をそのまま用いる)とロケーション処理(既に計算したランクを
場合分けして上限値決める)は容易にわかるが、ランク処理が伏魔殿。ここが解明できれば、あとは
その65536通りの作表をして、(ランク、マップシード、ロケーション)が「あり得る組み合わせか?」は
検証可能になる。
69名無しさん@そうだ選挙に行こう:2009/08/30(日) 12:55:01 ID:0tnXTAQa
ランクの関数がなんか変だ

レス62番の

>:020A7C68 EBFFFF7B bl 020A7A5C //エラー処理rank再計算

からたどっていって
冒頭から10ステップ

:020A7A5C E92D4070 stmdb r13!,{r4,r5,r6,r14}
:020A7A60 EBFD9DFD bl 0200F25C
:020A7A64 E1A05000 mov r5,r0 ;r5=99(0x63)
:020A7A68 EBFDA125 bl 0200FF04
:020A7A6C E1A01000 mov r1,r0 ;r1=99(0x63)
:020A7A70 E1A00005 mov r0,r5 ;r0=99(0x63)
:020A7A74 EBFDA0BF bl 0200FD78
:020A7A78 E1A04000 mov r4,r0 ;r4=99(0x63)
:020A7A7C EBFDACCA bl 02012DAC
:020A7A80 E1A00005 mov r0,r5 ;r0=99(0x63)

この最後の2行

最後から2行目で呼ばれてるルーチンは

:02012DAC E59F0000 ldr r0,[r15, #+0x0] ;r15+0x0=*(02012db4)=#34582812(0x020fb11c)
:02012DB0 E12FFF1E bx r14 (Jump to addr_00000000?)
:02012DB4 020FB11C

r0 に定数0x020FB11C を搭載して帰還するだけの他愛もない関数
しかし最後の行でこのr0をr5で書き潰している。バグか?
70名無しさん@そうだ選挙に行こう:2009/08/30(日) 14:11:54 ID:LLwhh0bK
まとめると

@中断秒数→mapSEED(一意に決まる)

A中断秒数、自分のレベル、転生の回数など→rank
 したがって、中断秒数だけからrankは計算できない

B中断秒数、rank→location
 したがって、厳密に考えると、Aと同じだけパラメータが必要
 しかしながら、rankは3パターンだから、【秒数→考えられる場所3パターン】 は計算可能

逆に(プログラム的に)考えると、
・まず、中断秒数をセット
・3回乱数を計算。うち2回目は使わない(他の要素があるのでランク確定は無理)

・1番目の乱数値がmapSEED値
・3番目の乱数値で、考えられる3パターンの場所値を示す

つまり

   (mapSEED、場所1、場所2、場所3)

というデータが0xffff 通り得られる。
うむ。perlでも計算できそうだなw
71名無しさん@そうだ選挙に行こう:2009/08/30(日) 14:16:17 ID:Fm80ovuo
中断秒数って何だ?
72名無しさん@そうだ選挙に行こう:2009/08/30(日) 14:29:00 ID:LLwhh0bK
とりあえずこれでいいのかな?

use bigint;

$SEED=0;

for $sec (0..0xffff){
  $SEED=$sec;
  $mapSEED=&dq9_rand;&dq9_rand;$rand=&dq9_rand;

  $loc1=&loc($rand,47);
  $loc2=&loc($rand,131);
  $loc3=&loc($rand,150);

  printf "$sec秒:SEED=%04X 場所(%X,%X,%X)\n",$mapSEED,$loc1,$loc2,$loc3;
}


sub dq9_rand{
  $SEED = ($SEED * 1103515245 + 12345) & 0xffffffff;
  $ret =($SEED >> 0x10 & 32767);
  return $ret;
}

sub loc{
  $r=shift;
  $upper=shift;
  $diff_1=$upper; # 差分+1 = $upper-下限1+1
  return ( 1 + ($r % $diff_1 ) );
}
73名無しさん@そうだ選挙に行こう:2009/08/30(日) 16:34:12 ID:Xtsq0ynM
いや、高ランク以外は
場所 = 乱数(1〜150)
ではないので、候補が9通りになるのでは?

7473:2009/08/30(日) 16:47:39 ID:Xtsq0ynM
ごめん、まったくの勘違い
無視して m(__)m
75名無しさん@そうだ選挙に行こう:2009/08/30(日) 18:39:59 ID:oniIX3Pr
>>72
1番目がランク、2番目がmapSEEDに使われてるんで
読み飛ばす乱数が間違ってるよ
76名無しさん@そうだ選挙に行こう:2009/08/30(日) 20:02:06 ID:hV2DpkbK
コードを作るじゃなくてarmの勉強をするスレなんかw
77名無しさん@お腹いっぱい。:2009/08/30(日) 20:26:20 ID:kFou9yJ4
これまでSPARCとMIPSしか触ったことないオッサンにも
非常に興味深いスレですw
78名無しさん@お腹いっぱい。:2009/08/30(日) 20:41:26 ID:D7/IlL6f
仕事じゃない勉強は楽しくて仕方ないなあ
79名無しさん@お腹いっぱい。:2009/08/30(日) 23:20:45 ID:7OhnrR8A
>>75
そうするとどこが入れ替わらないといけないわけ?
80名無しさん@お腹いっぱい。:2009/08/30(日) 23:55:32 ID:hOrYZumw
内容が高等すぎてレスを付けられないレベル
81名無しさん@お腹いっぱい。:2009/08/31(月) 00:00:44 ID:oniIX3Pr
>>79
  $mapSEED=&dq9_rand;&dq9_rand;$rand=&dq9_rand;
ここが
  &dq9_rand;$mapSEED=&dq9_rand;$rand=&dq9_rand;

>>62にあるように処理順はランク→SEED→場所
82名無しさん@お腹いっぱい。:2009/08/31(月) 02:20:14 ID:knigeFca
>>35の文章をperlに翻訳してみた

> 乱数シード設定後、
  $SEED=$sec;
> 2番目の乱数で地図のSEED、3番目の乱数で場所決定
  &dq9_rand;$mapSEED=&dq9_rand;$rand=&dq9_rand;

>ランクが高いと
>場所 = rand() % 150 + 1
  $loc3=&loc($rand,150);

うん、このスレにとっては完全な計算式だなw
83地図スレ377:2009/08/31(月) 04:02:05 ID:wu28GP+a
すみません、場所をお借りします
>>72のプログラムと同様のプログラムで、自分が使ったソースです

#include <stdio.h>
unsigned int rand_seed;
int rand(void)
{
rand_seed = rand_seed * 1103515245 + 12345;
return (rand_seed >> 0x10) & 0x7fff;
}
int main(int argc, char *argv[])
{
unsigned int seed,i;
if(argc < 2) return 0;
seed = strtol(argv[1],NULL,16);
for(i=0;i<0x10000;i++)
{
rand_seed = i;
rand();
if(rand() != seed) continue;
printf(" %02x",rand()%150+1);
}
printf("\n");
return 0;
}

引数に地図SEEDを入れると場所の候補を出します
84名無しさん@お腹いっぱい。:2009/08/31(月) 07:22:00 ID:UbyTk0SM
85名無しさん@お腹いっぱい。:2009/08/31(月) 07:31:54 ID:UqNyEUEX
この秒数って何の秒数?
86名無しさん@お腹いっぱい。:2009/08/31(月) 08:49:56 ID:wwQwYhbw
>>85
中断秒数だといっていたが、ここに>>83が地図のSEEDに依存するという爆弾を投下
87名無しさん@お腹いっぱい。:2009/08/31(月) 12:40:29 ID:LWH073qc
>>83
どうやればいいのかわからん
88名無しさん@お腹いっぱい。:2009/08/31(月) 13:04:48 ID:nPQY+saG
遅々として解明がすすまない Rank( ) 関数・・・
とりあえずはレベル・転生部分まで

:020A7A5C E92D4070 stmdb r13!,{r4,r5,r6,r14}
:020A7A60 EBFD9DFD bl 0200F25C←r0 に定数0x020f33d8を詰むだけの関数
:020A7A64 E1A05000 mov r5,r0 ←r5=0x020f33d8 待避
:020A7A68 EBFDA125 bl 0200FF04← r0=[r0, #+0x3ac] 20F3784を参照??
:020A7A6C E1A01000 mov r1,r0
:020A7A70 E1A00005 mov r0,r5 ←r0=0x020f33d8 復活
:020A7A74 EBFDA0BF bl 0200FD78
:020A7A78 E1A04000 mov r4,r0
:020A7A7C EBFDACCA bl 02012DAC←謎
:020A7A80 E1A00005 mov r0,r5 ←なぜかせっかくのリターン値を上書き。論理バグ?
:020A7A84 EBFDA687 bl 020114A8
:020A7A88 E1A05000 mov r5,r0

:020A7A8C E3A00000 mov r0,#0x0←初期化r0【最大レベルレジスタ】=0;
:020A7A90 E1A06000 mov r6,r0←初期化r6=【最大転生回数レジスタ】=0;
:020A7A94 E1A0E000 mov r14,r0 ←カウンタ。12回まわし
:020A7A98 EA00000B b 020A7ACC→△へジャンプ(こういう無駄なコードが多いw)

○:020A7A9C E5943144
:020A7AA0 E20EC0FF and r12,r14,#0xFF 無駄コードw
:020A7AA4 E083108C add r1,r3,r12,lsl #0x1
:020A7AA8 E2811C01 add r1,r1,#0x100 r1=r3+0x100+カウンタ×2
:020A7AAC E1D126BC ldrh r2,[r1, #+0x6c] ←レベル
:020A7AB0 E083100C add r1,r3,r12
:020A7AB4 E5D11186 ldrb r1,[r1, #+0x186] ←各職業転生回数
:020A7AB8 E1520000 cmp r2,r0 もし【最大レベルレジスタ】より高いレベルなら
:020A7ABC 81A00002 movhi r0,r2 最大レベル更新
:020A7AC0 E1510006 cmp r1,r6 もし、【最大転生回数レジスタ】よりデカい値なら
:020A7AC4 81A06001 movhi r6,r1 最大転生回数更新
:020A7AC8 E28EE001 add r14,r14,#0x1 カウンタ++

△:020A7ACC E35E000D cmp r14,#0xD 全12職業をループ
:020A7AD0 BAFFFFF1 blt 020A7A9C→○までループ↑

:020A7AD4 E5D51009 ldrb r1,[r5, #+0x9]
:020A7AD8 E3500063 cmp r0,#0x63 ←最大レベルが99より大きければ(ありえんわw)
:020A7ADC 83A00063 movhi r0,#0x63 ←99にする
:020A7AE0 E356000A cmp r6,#0xA ←最大転生回数レジスタが10回以上なら(これはあるなw)
:020A7AE4 83A0600A movhi r6,#0xA ←10で頭打ち

↑でわかるとおり、ひとつの職業を99にしたまま、ある職業を10回転生させるのがお得かとw
89名無しさん@お腹いっぱい。:2009/08/31(月) 13:12:17 ID:nPQY+saG
このあとがサッパリわからんw
俗にいわれている、「最大レベル+転生回数×4」というやつだと思うのだが

:020A7AD4 E5D51009 ldrb r1,[r5, #+0x9] <再掲>
<略>
:020A7AE8 E3510002 cmp r1,#0x2
 :020A7AEC 00861106 addeq r1,r6,r6,lsl #0x2←r1=最大転生回数×4
 :020A7AF0 05D52007 ldreqb r2,[r5, #+0x7] ←???
 :020A7AF4 00800001 addeq r0,r0,r1
 :020A7AF8 00820000 addeq r0,r2,r0←r1=最大レベル+最大転生回数×4+[r5, #+7]
 :020A7AFC 0A00000D beq 020A7B38

そもそも、[r5, #+0x9]がジャスト2のときだけ発動されるステップだし、しかも、この直後

:020A7B40 E3A01000 mov r1,#0x0
:020A7B44 E1A00006 mov r0,r6
:020A7B48 E5C51009 strb r1,[r5, #+0x9]

とかやって、[r5, #+0x9]はゼロクリアされちゃってるし。なんなんだいったい
90名無しさん@お腹いっぱい。:2009/08/31(月) 13:23:29 ID:nPQY+saG
↑あたり含めて割り算の分母(剰余計算用)を決定しているようなのだがサッパリわからん
:020A7B64番地までで、r0の計算がおわった後はわかるんだけど・・・

:020A7B64 E1A04080 mov r4,r0,lsl #0x1←r4=r0×2
:020A7B68 EBFD7030 bl 02003C30←超有名乱数関数→r0に乱数(0〜32767)
:020A7B6C E2841001 add r1,r4,#0x1←r1=r4+1
:020A7B70 EBFD94A4 bl 0200CE08←r1=r0(乱数)%r1
:020A7B74 E1A00001 mov r0,r1←r0に剰余をうつしかえ(商は使わない)
:020A7B78 EBFD926D bl 0200C534
:020A7B7C E1A01005 mov r1,r5
:020A7B80 EBFD9378 bl 0200C968
:020A7B84 EBFD924D bl 0200C4C0
:020A7B88 E0860000 add r0,r6,r0
:020A7B8C E1A00800 mov r0,r0,lsl #0x10 ←上位16ビットクリア
:020A7B90 E1A06820 mov r6,r0,lsr #0x10 ←上位16ビットクリアしてr6に代入
ここまででr6がランク(以下のとおりr0のままで良いと思うのだが。謎w)

範囲正規化
:020A7B94 E3560002 cmp r6,#0x2
:020A7B98 33A06002 movcc r6,#0x2←2未満なら2
:020A7B9C E35600F8 cmp r6,#0xF8
:020A7BA0 83A060F8 movhi r6,#0xF8←F8より大きければF8
:020A7BA4 E1A00006 mov r0,r6←ランクをr0に搭載
:020A7BA8 E8BD8070 ldmia r13!,{r4,r5,r6,r15} リターン

データ
:020A7BAC 40A00000
:020A7BB0 3DCCCCCD
91名無しさん@お腹いっぱい。:2009/08/31(月) 20:36:53 ID:FeoKcv7P
保守

逆汗職人にとっても RANK(void) 関数は、難攻不落なのか
92名無しさん@お腹いっぱい。:2009/08/31(月) 20:58:40 ID:i4Q2Jy3b
>>89>>90の間は浮動小数点での計算だね
IEEE形式の単精度浮動小数点
93名無しさん@お腹いっぱい。:2009/08/31(月) 21:13:41 ID:VtictQGB
>>92
なるほど。これですかい?

    1 8     23                ビット幅
   +-+--------+-----------------------+
   |S | Exp    | Fraction            |
    +-+--------+-----------------------+
   31 30 23 22 0 ビット番号 (0が右)

    バイアス +127
   指数部はバイアスまたはエクセスと呼ばれる表現形式であり、実際の値にある固定値emax = 127を加算している。この
   ような表現にしているのは浮動小数点数同士の比較を単純にするためである。指数部は大きな値も小さな値も表せるよう
   に負の値にもなるが、これを2の補数で表すと、全体の符号 S とは別に Exp も符号を持つことになり、単純な大小比較が
   できなくなってしまうのである。そのため、指数部はバイアスされて常に正の値となるような形式で格納される。

勉強になります
94名無しさん@お腹いっぱい。:2009/08/31(月) 21:52:45 ID:VNjJ4OKI
次は魔王地図の場所ですかね
95名無しさん@お腹いっぱい。:2009/08/31(月) 22:05:05 ID:VNjJ4OKI
うは、誤爆・・・orz
96名無しさん@お腹いっぱい。:2009/08/31(月) 22:13:07 ID:22ts2HhH
地図の場所C++で頼む
97名無しさん@お腹いっぱい。:2009/08/31(月) 22:34:30 ID:rl16nBjK
横から失礼します
> :020A7AEC 00861106 addeq r1,r6,r6,lsl #0x2←r1=最大転生回数×4
r1 ← r6+r6*4 = 最大転生回数×5
 じゃないの?
それとも解釈が間違ってます?
98名無しさん@お腹いっぱい。:2009/09/01(火) 03:15:37 ID:J4qdZ0nv
>>97
たしかにそうですね
地図ランク生成の式、間違えてますね
(主人公の最大レベル+主人公の最大転生回数*5+もぐった地図レベル)+10%〜-10%
ですね
99名無しさん@お腹いっぱい。:2009/09/01(火) 03:54:34 ID:J4qdZ0nv
間違った式がすでに広まってしまって恥ずかしいです
他にも間違えているところがあるかも知れません
+10%〜-10%のあたりの私の解釈を書いておきます

それまでの計算結果をbaseとします
base=最大レベル+最大転生回数*5+地図レベル

:020A7B4C EBFD928A bl 0200C57C ; 整数→浮動小数点への変換
:020A7B50 E1A01000 mov r1,r0 ; r1にそれまでの計算結果の浮動小数点表現
:020A7B54 E59F0054 ldr r0,[r15, #+0x54] ; r0=0.1(0x3dcccccd)
:020A7B58 EBFD92CE bl 0200C698 ; 浮動小数点での乗算 base*0.1
:020A7B5C E1A05000 mov r5,r0 ; 結果をr5に退避
:020A7B60 EBFD9256 bl 0200C4C0 ; 浮動小数点→整数への変換
:020A7B64 E1A04080 mov r4,r0,lsl #0x1 ; 2倍する r4 = |base*0.1|*2
:020A7B68 EBFD7030 bl 02003C30 ;rand()
:020A7B6C E2841001 add r1,r4,#0x1 ; r1 = |base*0.1|*2+1
:020A7B70 EBFD94A4 bl 0200CE08 ; r1 = rand % (|base*0.1|*2+1)
:020A7B74 E1A00001 mov r0,r1
:020A7B78 EBFD926D bl 0200C534 ; 整数→浮動小数点への変換
:020A7B7C E1A01005 mov r1,r5 ; 020A7B5Cで退避していた結果(浮動小数点表現)をr1に復帰
:020A7B80 EBFD9378 bl 0200C968 ; 浮動小数点での引き算 rand % (|base*0.1|*2+1) - base*0.1
:020A7B84 EBFD924D bl 0200C4C0 ; 浮動小数点→整数への変換
:020A7B88 E0860000 add r0,r6,r0 ; base + |rand % (|base*0.1|*2+1) - base*0.1|

この解釈で+10%から-10%になると思います
浮動小数点の計算ルーチンの中身はざっとしか見てないので、間違ってるかも知れません
整数との変換が複数あるのは、符号付、符号なしなどの違いだと思います
100名無しさん@お腹いっぱい。:2009/09/01(火) 06:40:35 ID:xcNoxHh4
ARM7とARM9ってどう違うの?
教えてえろいひと!
101名無しさん@お腹いっぱい。:2009/09/01(火) 13:47:00 ID:801uMyiX
>>99

なるほど! float でしたかっ!

> :020A7B54 E59F0054 ldr r0,[r15, #+0x54] ; r0=0.1(0x3dcccccd)

ここ↑がポイントですね。

   0x3dcccccd = 0 0111 1011 100 1100 1100 1100 1100 1101

だからっとw

仮数:13421773(×2^-23) 指数:-4

だから、ショボい電卓で計算してもw

   0x3dcccccd = 0.100000001490116

ですね。着眼点がすごいなぁ・・・
102名無しさん@お腹いっぱい。:2009/09/01(火) 13:48:25 ID:801uMyiX
同じ伝で、

 0x3fc00000=float(1.5)
 0x40a00000=float(5.0)

だから、これで未解明の部分がわかるかな?
103名無しさん@お腹いっぱい。:2009/09/01(火) 13:59:31 ID:801uMyiX
:020A7AFC番地で、「beq 020A7B38」しなかった場合の実行コード

この段階のレジスタ状況: r0=最大レベル、r6=最大転生回数

:020A7B00 EBFD929D bl 0200C57C ←r0(最大レベル:整数)をfloat
:020A7B04 E1A01000 mov r1,r0  ←して、r1に待避
:020A7B08 E3A005FF mov r0,#0x3FC00000 ← float(1.5);
:020A7B0C EBFD92E1 bl 0200C698 ←かけ算(レベル×1.5)
:020A7B10 E1A04000 mov r4,r0 ←の結果をr4に待避

:020A7B14 E1A00006 mov r0,r6 ←今度はr6を
:020A7B18 EBFD9297 bl 0200C57C ←floatして
:020A7B1C E1A01000 mov r1,r0 ←r1へ

:020A7B20 E59F0084 ldr r0,[r15, #+0x84] ←r0=定数0x40a0000=float(5.0)
:020A7B24 EBFD92DB bl 0200C698 ←最大再生回数×5.0
:020A7B28 E1A01000 mov r1,r0 ←をr1に

:020A7B2C E1A00004 mov r0,r4 ←さきほどの最大レベル×1.5をr0へ
:020A7B30 EBFD8F52 bl 0200B880 ←float足し算(r0=r0+r1;)
:020A7B34 EBFD926E bl 0200C4F4 ←r0=int(r0);

「最大レベル+最大転生回数*5+地図レベル」組とここで合流(jumpポイント)
→:020A7B38 E1A00800 mov r0,r0,lsl #0x10 ←計算結果r0の上位16ビットをクリアして
:020A7B3C E1A06820 mov r6,r0,lsr #0x10 ←なぜかr6に待避
:020A7B40 E3A01000 mov r1,#0x0 ←r1をゼロクリア(ストア準備)
:020A7B44 E1A00006 mov r0,r6     ← r0=r6; なんのために待避したんだ?www
:020A7B48 E5C51009 strb r1,[r5, #+0x9] ←[r5, #+0x9]をゼロクリア。なんのフラグだろう
以下、:020A7B4C番地以下は、>>99 のとおり

・どうやら、こちらは、floatで最大レベル×1.5+最大再生回数×5.0 を計算しているらしい(なので、max198.5)
・[r5, #+0x9]が2か否かで分岐する。他分岐は整数演算でr0=最大レベル+最大転生回数×5+地図レベル
・[r5, #+0x9]は必ずゼロクリアされる。


あと少しなんだけどなー。壁はデータ構造・・・特に、[r5, #+0x9]???
同[r5, #+0x7]は99氏の解析によれば、地図レベルらしいのだが・・・
104名無しさん@お腹いっぱい。:2009/09/01(火) 14:14:02 ID:801uMyiX
ああ、なるほど、

  最大レベル(max99)+最大転生回数×5(max50)+地図レベル(max99) = max248

だから、マップランクは最大でF8(十進248)になってるのか



レベル99で地図99とすると、それだけで 0xc6
加えて

 転生1回×5=0xcb
 転生2回×5=0xd0
 転生3回×5=0xd5
 転生4回×5=0xda
             ←0xddの壁w
 転生5回×5=0xdf

実際はさらに乱数要素が±10%つくわけかー
105名無しさん@お腹いっぱい。:2009/09/01(火) 14:20:14 ID:+48qcfBw
mapSEEDに対してRANKで用いる乱数が固定されるとすると
最大レベル+最大転生回数×5+地図レベル
が2〜248をとっても生成できないRANKとか出てくるんだろうか
106名無しさん@お腹いっぱい。:2009/09/01(火) 14:48:10 ID:801uMyiX
>>105
おもしろそうなので、計算してみましたw
題材は例によって川崎ロッカー(B7-3CA2)です。

中断秒数は、2B3A(3時間4分27秒)とわかってるので、ランク用乱数計算すると、361Aですね。

下記ペアは (最大レベル+最大転生回数×5+地図レベル:10進数 、 ランク:16進)です

(2 02) (3 03) (4 04) (5 05) (6 06) (7 07) (8 08) (9 09) (10 0b) (11 0c) (12 0d)
(13 0e) (14 0f) (15 10) (16 11) (17 12) (18 13) (19 14) (20 12) (21 13) (22 14)
(23 15) (24 16) (25 17) (26 18) (27 19) (28 1a) (29 1b) (30 1f) (31 20) (32 21)
(33 22) (34 23) (35 24) (36 25) (37 26) (38 27) (39 28) (40 2c) (41 2d) (42 2e)
(43 2f) (44 30) (45 31) (46 32) (47 33) (48 34) (49 35) (50 2e) (51 2f) (52 30)
(53 31) (54 32) (55 33) (56 34) (57 35) (58 36) (59 37) (60 3b) (61 3c) (62 3d)
(63 3e) (64 3f) (65 40) (66 41) (67 42) (68 43) (69 44) (70 44) (71 45) (72 46)
(73 47) (74 48) (75 49) (76 4a) (77 4b) (78 4c) (79 4d) (80 54) (81 55) (82 56)
(83 57) (84 58) (85 59) (86 5a) (87 5b) (88 5c) (89 5d) (90 63) (91 64) (92 65)
(93 66) (94 67) (95 68) (96 69) (97 6a) (98 6b) (99 6c) (100 65) (101 66)
(102 67) (103 68) (104 69) (105 6a) (106 6b) (107 6c) (108 6d) (109 6e) (110 67)
(111 68) (112 69) (113 6a) (114 6b) (115 6c) (116 6d) (117 6e) (118 6f) (119 70)
(120 6c) (121 6d) (122 6e) (123 6f) (124 70) (125 71) (126 72) (127 73) (128 74)
(129 75) (130 8f) (131 90) (132 91) (133 92) (134 93) (135 94) (136 95) (137 96)
(138 97) (139 98) (140 8f) (141 90) (142 91) (143 92) (144 93) (145 94) (146 95)
(147 96) (148 97) (149 98) (150 9f) (151 a0) (152 a1) (153 a2) (154 a3) (155 a4)
(156 a5) (157 a6) (158 a7) (159 a8) (160 a7) (161 a8) (162 a9) (163 aa) (164 ab)
(165 ac) (166 ad) (167 ae) (168 af) (169 b0) (170 b2) (171 b3) (172 b4) (173 b5)
(174 b6) (175 b7) (176 b8) (177 b9) (178 ba) (179 bb) (180 ae) (181 af) (182 b0)
(183 b1) (184 b2) (185 b3) (186 b4) (187 b5) (188 b6) (189 b7) ←★ (190 b0) (191b1)
(192 b2) (193 b3) (194 b4) (195 b5) (196 b6) (197 b7) (198 b8) (199 b9) (200 d5)
(201 d6) (202 d7) (203 d8) (204 d9) (205 da) (206 db) (207 dc) (208 dd) (209 de)
(210 c1) (211 c2) (212 c3) (213 c4) (214 c5) (215 c6) (216 c7) (217 c8) (218 c9)
(219 ca) (220 e9) (221 ea) (222 eb) (223 ec) (224 ed) (225 ee) (226 ef)
(227 f0) (228 f1) (229 f2) (230 ef) (231 f0) (232 f1) (233 f2) (234 f3) (235 f4)
(236 f5) (237 f6) (238 f7) (239 f8) (240 f8) (241 f8) (242 f8) (243 f8) (244 f8)
(245 f8) (246 f8) (247 f8) (248 f8)

なので、この地図ゲットしたときは、最大レベル+最大転生回数×5+地図レベル=189 だった
189といえば、レベル99+地図90台だよゆうでクリアできますから=つまり川崎ロッカーは正規版!

確かにトビトビなので、「あり得ないランク」も・・・また新たなチート地図疑惑騒動がw
本スレには、ナイショにしときましょう
107名無しさん@お腹いっぱい。:2009/09/01(火) 15:12:26 ID:+48qcfBw
B5〜C8の範囲でみるとBC,BD,BE,BF,C0がないですね

大半が抜け落ちるようならチート判定に使えそうだけど
抜ける可能性の方が低いとなると役にはたたなそうか
108名無しさん@お腹いっぱい。:2009/09/01(火) 21:07:43 ID:kUq3CMn5
まとめると、
つまり、ランクのbase(最後はbase±10% 乱数つきになる)は

 @ floatで最大レベル×1.5+最大再生回数×5.0 
 A 最大レベル(max99)+最大転生回数×5(max50)+地図レベル(max99)

っであって、[r5, #+0x9]が分岐フラグ


[r5, #+0x9]が何を意味するのは今のところ unknown


==2で、Aになるところからすると、0=ツェ浜まで、 1=船入手、 2=箱船ゲットという
あたりだろうか?
109名無しさん@お腹いっぱい。:2009/09/01(火) 21:26:26 ID:kUq3CMn5
ndis2のバグ?みつけちゃたw
たとえば、メモリイメージ:0200C4DC (ファイル:0000C4DC) で、

× > :0200C4DC E1A00231 mov r0,lsr r1

とか逆汗されるけと、E1A00231解析すると

1110 00 0 1101 0 0000 0000 0010 0 01 1 0001
cond 00↑ mov s src  dst shiftR LSR ↑ R1
   オペランドはレジスタ      シフト長はレジスタ

となるから、

○ :0200C4DC E1A00231 mov r0, r1, lsr r2

なのでは?(そもそも、mov r0,lsr r1 て意味不明w)
110名無しさん@お腹いっぱい。:2009/09/03(木) 09:25:33 ID:VYpdj7p0
良スレAGE!
111名無しさん@お腹いっぱい。:2009/09/03(木) 14:39:05 ID:C58TvsLk
検索サイト人です。

ややスレ違いですがw  ttp://dq9.hustle.ne.jp/mapsearch.cgi にjavascript版を用意したのですが、
乱数計算がうまくできず結局(ソースみていただければわかりますけど)

   var low=SEED & 0xffff; //javascriptは馬鹿なので16bitずつ分解
   var hi=SEED>>16;


   for(j=0;j<boxNum;j++){//おなじみの乱数関数(0〜32767)×自宝箱序列数(1〜3いずれか固定)
      low=low * 1103515245 + 12345;
      carry=low >> 16; low=low & 0xffff;
      hi=(hi * 1103515245 + carry) & 0xffff;
      rand =(hi & 32767);
   }

こんな不細工なコードになってます。なんでも javascript内部では浮動小数点になっていて、ビット演算
するときだけ整数に倒すという謎しようのようで、32bitでやってると符号とかメチャクチャになってしまいまうので。

なんかもっとスマートな解決方法ないんでしょうかねー > 詳しい方
112名無しさん@お腹いっぱい。:2009/09/03(木) 18:15:22 ID:1QIxqiSW
>>111
内部的に倍精度(有効桁53bit)なので、32bit*32bitで下位32bitを取り出すのはどうしてもむりですね
検索サイト人さんが実装されてるように16bit*32bitを2回するしかないと思います
113名無しさん@お腹いっぱい。:2009/09/03(木) 22:08:10 ID:3MBuzb1w
>>7に挙げられている本ってARMの命令エンコーディングについても解説してる?してるなら買おうと思うんだけど
114名無しさん@お腹いっぱい。:2009/09/04(金) 01:21:33 ID:zJ+Lnsx7
>>111
関係ないレスで申し訳ないです。ここでしか聞くことができないもので

末尾が-A以外でも、たまに場所候補がひとつも現れない地図があるのですがこれは何故でしょうか?

例:あらぶる神々の火口 Lv70 魔剣神レパルド 火山 0B8F-L

その場合、地図自体は存在するが実際には場所候補がないため正規の手段では入手不可なのか、
あるい計算結果からは導き出されない(表示されない)別の場所候補があるということなのでしょうか
もし後者なら、場所候補に表示されないから黒、とは言い切れないのではないかと思いまして
115名無しさん@お腹いっぱい。:2009/09/04(金) 06:27:06 ID:Jj12jPgc
111ではないですが…

>>114
RANK,SEED,場所についてそれぞれ独立に乱数を振るのではなくて
経過時間から乱数の組を作ってそこから計算している仕様

経過時間は0000〜FFFFでSEEDは0000〜7FFFなので
平均すると1つのSEEDを生む乱数組は2通りになるのだが
均等分配ではなく0通りのものから3通りのものまであった

@乱数組が3通りのものについてはRANKを決めた時に場所候補が3箇所までありえる
A乱数組が2通りのものについてはRANKを決めた時に場所候補が2箇所までありえる
B乱数組が1通りのものについてはRANKを決めた時に場所候補が1箇所までありえる
C乱数組が0通りのものは地図そのものがありえない

0B8FはCに該当するので場所候補がない

地図の構造はRANKがどの範囲[02〜37(末尾がAに相当),38〜3C,3D〜4B,…]に入っているかで決まる
RANKを決めてしまえば場所を決める関数は1通りで場所候補は3通りまでと言えるんだけど
場所を決める関数の分岐が02〜32,33〜50,51〜F8となっているため
末尾がAのものは場所候補が02〜32について3箇所まで&33〜37について3箇所までとなり
場所候補が3箇所以上出てくる可能性があるので割愛

検索で表示されないというのは同じでも事情はだいぶ異なります



経過時間から乱数の組を作るという処理をせずに地図を生成すれば0B8Fもできると思うので
そういう地図が存在するかと問われるとどう答えたらいいかわかりませんが
116名無しさん@お腹いっぱい。:2009/09/04(金) 07:38:09 ID:zJ+Lnsx7
>>115
お答えありがとうございます
ということは前者になるわけですね。よくわかりました

あと訂正です。例:あらぶる神々の火口 Lv70 →Lv79 でした。
117名無しさん@お腹いっぱい。:2009/09/04(金) 15:52:09 ID:7xuYLE/F
魔王の強さってどんな感じの計算になってるの?
http://p.pita.st/?m=dbcwa7ie
Lv0とかLv250ってどうなってるんだろう?
強さって配列?足し算?それともこのレベルは表示だけ?
118名無しさん@お腹いっぱい。:2009/09/05(土) 08:13:54 ID:6y678cRp
>>113
> >>7に挙げられている本ってARMの命令エンコーディングについても解説してる?してるなら買おうと思うんだけど

いわゆる「データシート」並みの詳しさはないけど、各命令ごとに「どのビットが何を意味しているか?」が
各節ごとに図解してあり、また、条件のハーフバイトとかは美しく統一されているから、それなりの知能(笑)が
あれば、ハンドアセンブルできる程度には解説してある。
119名無しさん@お腹いっぱい。:2009/09/05(土) 19:43:44 ID:00p0vyh/
>>118
ありがとう
120名無しさん@お腹いっぱい。:2009/09/07(月) 13:08:54 ID:UcVmnYrw
121名無しさん@お腹いっぱい。:2009/09/07(月) 13:45:16 ID:gs/Q1CfH
■ルーレット・超レア解析依頼■
http://schiphol.2ch.net/test/read.cgi/ff/1252223436/666 より



  666 名前:名前が無い@ただの名無しのようだ[sage] 投稿日:2009/09/07(月) 13:42:13 ID:bZRIymc30
  >>660
  それなら@中断再開〜超必殺技選択までの時間(ふつうの中断技類似)でいいはず、だが、
  中断再開タイミング関係なく、A4人目必殺〜超必殺技選択なのだから、4人目選択の
  段階でタイマー更新されるのでは?

  (たしかに、DSにはタイマーが4つある → ttp://www.bottledlight.com/ds/index.php/System/Timers ※warning 注意w
122名無しさん@お腹いっぱい。:2009/09/07(月) 13:59:46 ID:gs/Q1CfH
いつも使っているタイマーは04000100番地の(制御レジスタは04000102)だが、

:020CA8C8 E59F0004 ldr r0,[r15, #+0x4]  //r15+0x4=*(020ca8d4)==#0x04000100
:020CA8CC E1D000B0 ldrh r0,[r0, #+0x0]  //r0=*[04000100]
:020CA8D0 E12FFF1E bx r14 (Jump to addr_04000100?)
:020CA8D4 04000100

この直後に確かに、04000104番地タイマー2(制御レジスタ2は04000106)をいじっているようだ

:020CA8D8 E92D4038 stmdb r13!,{r3,r4,r5,r14}
:020CA8DC E1A04000 mov r4,r0
:020CA8E0 EBFFFFD0 bl 020CA828
:020CA8E4 E59F3068 ldr r3,[r15, #+0x68]   //;r15+0x68=*(020ca954)==#0x04000106
:020CA8E8 E3A02000 mov r2,#0x0 ;r2=0(0x0)
:020CA8EC E1C320B0 strh r2,[r3, #+0x0]  //タイマ制御2クリア *[04000106]=#0
:020CA8F0 E594C00C ldr r12,[r4, #+0xc]
:020CA8F4 E5943010 ldr r3,[r4, #+0x10]
:020CA8F8 E05C5000 subs r5,r12,r0
:020CA8FC E0C34001 sbc r4,r3,r1
:020CA900 E59F1050 ldr r1,[r15, #+0x50]  ;r15+0x50=*(020ca958)=#34384980(0x020cac54)
:020CA904 E3A00001 mov r0,#0x1    ;r0=1(0x1)
:020CA908 EBFFF781 bl 020C8714
:020CA90C E2550000 subs r0,r5,#0x0
:020CA910 E3A03000 mov r3,#0x0 ;r3=0(0x0)
:020CA914 E2D40000 sbcs r0,r4,#0x0
:020CA918 B59F303C ldrlt r3,[r15, #+0x3c]   ;r15+0x3c=*(020ca95c)=#65534(0x0000fffe)
:020CA91C BA000005 blt 020CA938
:020CA920 E2550801 subs r0,r5,#0x10000
:020CA924 E0D40003 sbcs r0,r4,r3
:020CA928 AA000002 bge 020CA938
:020CA92C E1E00005 mvn r0,r5       //MVN(論理否定)命令は、論理演算により値の1 の補数を生成
:020CA930 E1A00800 mov r0,r0,lsl #0x10
:020CA934 E1A03820 mov r3,r0,lsr #0x10
:020CA938 E59F2020 ldr r2,[r15, #+0x20]   ;r15+0x20=*[020ca960]==#0x04000104
:020CA93C E3A010C1 mov r1,#0xC1     ;r1=0xc1==1100 0001
:020CA940 E1C230B0 strh r3,[r2, #+0x0]  ;r2+0x0=*(04000104)
:020CA944 E3A00010 mov r0,#0x10     ;r0=16(0x10)
:020CA948 E1C210B2 strh r1,[r2, #+0x2]   ;*[04000106 タイマ制御2]←1100 0001 セット
:020CA94C EBFFF78D bl 020C8788
:020CA950 E8BD8038 ldmia r13!,{r3,r4,r5,r15}

【dataセクション】
:020CA954 04000106←■
:020CA958 020CAC54
:020CA95C 0000FFFE
:020CA960 04000104←■ 
123名無しさん@お腹いっぱい。:2009/09/07(月) 14:19:43 ID:gs/Q1CfH
020CA94C番地で呼んでるサブルーチン。Interrupt enableがらみ

:020C8788 E59F3024 ldr r3,[r15, #+0x24]    ;r15+0x24=*(020c87b4)==#0x04000208
:020C878C E3A01000 mov r1,#0x0 ;r1=0(0x0)
:020C8790 E1D320B0 ldrh r2,[r3, #+0x0] ;*[04000208 IEマスター])→r2に待避
:020C8794 E1C310B0 strh r1,[r3, #+0x0]    ;*[04000208]クリア
:020C8798 E5931008 ldr r1,[r3, #+0x8]     ;*[04000210 IE]をr3に待避
:020C879C E1810000 orr r0,r1,r0
:020C87A0 E5830008 str r0,[r3, #+0x8]     ;*[04000210]=*[04000210] | r0;
:020C87A4 E1D300B0 ldrh r0,[r3, #+0x0]    //謎
:020C87A8 E1A00001 mov r0,r1         //せっかくロードした r0 を書きつぶしw 馬鹿?
:020C87AC E1C320B0 strh r2,[r3, #+0x0]   //*[04000208]←さっき待避したr2
:020C87B0 E12FFF1E bx r14

【dataセクション】
:020C87B4 04000208
124名無しさん@お腹いっぱい。:2009/09/07(月) 18:17:58 ID:5zzJrpMF
>>121
戦闘中の乱数は解析中ですけど、解析途中のメモを投下しときます

・複数の乱数生成器を使用している?
02003c30のルーチンはダメージ計算に使われてるが、行動順、命中判定、敵の行動決定には使われていない
スーパールーレットの判定は02003c30が使われている

・02003c30の乱数シードの設定は行われない
戦闘開始などでは乱数シードは変わらない
ボス前で中断再開すると、戦闘終了まで、乱数シードの設定は行われない

・02003c30が時間経過でたまに使われる
数分毎に1〜8個ぐらい乱数消費
素材の復活判定?
戦闘中でもこの判定が入る

スーパールーレットの結果を再現しようとすると、中断再開後、02003c30の乱数消費を固定するしかない
時間経過の乱数消費は、中断再開後すぐの時もあるし、数分ないときもある
命中判定もまだわかってないんで、自分にはまだむりです
行動順、命中判定などに使われている乱数?は戦闘開始時のタイミングに影響を受けるみたいだけど、
スーパールーレットの結果判定の乱数はタイミングに影響を受けないんで、13秒はオカルトみたいですね

ちなみに乱数生成器をもうひとつ見つけたが、使われてる形跡がなかった
0202d238: カウンタ(027ffc3c)を絡ませた乱数ルーチン
0202d458: 乱数ルーチン
02101300: 乱数シード
125名無しさん@お腹いっぱい。:2009/09/07(月) 21:19:48 ID:2cNZOoff
ほしゅ
126名無しさん@お腹いっぱい。:2009/09/07(月) 22:22:50 ID:f/oelqan
■ルーレット・超レア解析依頼■
http://c.2ch.net/test/-39.-lA!mail=sage/ff/1251760796/543 より
543:09/07(月) 20:10 QkpAh2hCO [sage]
さっきの事あるから、あんまりスパルの話はしたくないが…
多分要約すると
手順@とりあえずスパル発動(この時点で取る時間が@)
手順A全員チャージ終了して四人目が必殺発動(13秒の時の開始時間、この時間をA)
手順Bこの@からAの時間を計測して、8で割る
例えば3分11秒なら191秒
8で割ると23余り7
手順Bでレア確したなら以降@とAの時間を8の倍数秒+7で常にレア確可能
手順Bでレア確しなかったら、@とAの時間を+1秒しながら計測してレア確するまで繰り返す
長くなったがこんなだと思う
で、以降は各自の判断で使って、この件は終了で良いんじゃね?
127名無しさん@お腹いっぱい。:2009/09/07(月) 23:05:19 ID:5zzJrpMF
>>124の訂正
スーパールーレット時に02003c30は消費されるが、判定には使われていないようだ
行動順などの判定と同じ乱数が消費されているっぽい
この乱数は戦闘開始のタイミングで固定されてるっぽい
この乱数生成器を探しているが、まだ見つからんので、憶測しかできん
128名無しさん@お腹いっぱい。:2009/09/08(火) 08:35:11 ID:iN+XRYXv
ようやく戦闘時の乱数生成器をみつけた

020753C4: 設定関数
0207544C: 乱数ルーチン
02385F0C,02385F10: 乱数シード(もしかしたら固定領域ではない?)

戦闘時のみ作成される乱数生成器
rand()
{
rand_seed = rand_seed * 0x5d588b656c078965 + 0x269ec3;
return (rand_seed >> 32) & 0xffffffff;
}

乱数シードは戦闘突入時に1回だけ設定されている
おそらく高速のタイマー(04000100)から
戦闘時の乱数制御は無理みたい
129名無しさん@お腹いっぱい。:2009/09/08(火) 11:52:56 ID:B75RWiFW
>>128
結論と思われるレスでしたので、こちらのレスを祈願スレに貼らせて頂きました
もしこれが結論ならば、釣り師がへるので良かったです
ありがとうございます、スレ汚しすみません
130名無しさん@お腹いっぱい。:2009/09/08(火) 14:38:34 ID:q1HOc1hd
>>128
超乙!SUGEEEEEEEEEE!!!! 貴殿解析力すごすぎ
さっそくいきましょう


■乱数設定関数
引数 r0:ベースアドレス、r1→[r0, #+0x0]、r2→,[r0, #+0x4]

:020753C4 E5801000 str r1,[r0, #+0x0]  ;r0+0x0=*(02108d20)=#-436080699(0xe601efc5)

:020753C8 E59F1020 ldr r1,[r15, #+0x20] ;r15+0x20=*(020753f0)=#0x6c078965
:020753CC E5802004 str r2,[r0, #+0x4]  ;r0+0x4=*(02108d24)=#159393009(0x098024f1)

:020753D0 E59F201C ldr r2,[r15, #+0x1c] ;r15+0x1c=*(020753f4)=#1566083941(0x5d588b65)
:020753D4 E5801008 str r1,[r0, #+0x8] ;r1は、定数#1812433253(0x6c078965)

:020753D8 E59F1018 ldr r1,[r15, #+0x18] ;r15+0x18=*(020753f8)=#2531011(0x00269ec3)
:020753DC E580200C str r2,[r0, #+0xc] ;r2は、定数#159393009(0x098024f1)

:020753E0 E5801010 str r1,[r0, #+0x10] ;r1は、定数#2531011(0x00269ec3)

:020753E4 E3A01000 mov r1,#0x0 ;r1=0
:020753E8 E5801014 str r1,[r0, #+0x14] ;r1は、定数#0

:020753EC E12FFF1E bx r14 ;RETURN

.DATA
:020753F0 6C078965
:020753F4 5D588B65
:020753F8 00269EC3


つまり、
外生r1→[r0, #+0x0]  +0
外生r2→,[r0, #+0x4]  +4
#1812433253(0x6c078965)→[r0, #+0x8] +8
#159393009(0x098024f1)→[r0, #+0xc]  +12
#2531011(0x00269ec3)→[r0, #+0x10]  +16
#0→[r0, #+0x14]  +20
131名無しさん@お腹いっぱい。:2009/09/08(火) 15:14:34 ID:q1HOc1hd
■乱数ルーチン

:0207544C E92D4008 stmdb r13!,{r3,r14}
:02075450 E5902000 ldr r2,[r0, #+0x0]  ; r2 ← [r0, #+0x0] 設定関数呼び出し時の r1
:02075454 E990000A ldmib r0 ,{r1,r3}  ;複数レジスタロード ib=空・下降
:02075458 E08CE293 umull r14,r12,r3,r2  ; unsigned乗算 (r12, r14) = r3 * r2 ;
:0207545C E02CC193 mla r12,r3,r1,r12  ; r12 = r3 * r1 + r12 [31:0] ;
:02075460 E590100C ldr r1,[r0, #+0xc]  ;r1←[r0, #+0xc]=#159393009(0x098024f1)←設定関数で
:02075464 E5903010 ldr r3,[r0, #+0x10]  ;r3←[r0, #+0x10]=#2531011(0x00269ec3)←設定関数で
:02075468 E02CC291 mla r12,r1,r2,r12  ; r12 = r1 * r2 + r12 [31:0] ;
:0207546C E5901014 ldr r1,[r0, #+0x14]  [r0, #+0x14]=#0(0x00000000)←設定関数で

:02075470 E093200E adds r2,r3,r14  ;r2=#2531011(0x00269ec3)+r14
:02075474 E5802000 str r2,[r0, #+0x0]  ;加算結果 r2 → [r0, #+0x0]

:02075478 E0A1100C adc r1,r1,r12 ; r1 += r12 + c ;
:0207547C E5801004 str r1,[r0, #+0x4]  ;加算結果 r1 → [r0, #+0x0]

:02075480 E1A00001 mov r0,r1
:02075484 E8BD8008 ldmia r13!,{r3,r15}
132名無しさん@お腹いっぱい。:2009/09/09(水) 10:24:02 ID:zopPnnO0
>>128
> おそらく高速のタイマー(04000100)から

なるほど。>>42あたりからずっと出てた疑問だけど
04000100タイマーの単位は秒ではないのですね → ttp://www.bottledlight.com/ds/index.php/System/Timers

<引用>
:020CA768 E59F3038 ldr r3,[r15, #+0x38] ;r15+0x38=*(020ca7a8)=#67109122(0x04000102)
:020CA76C E580200C str r2,[r0, #+0xc] ;r0+0xc=*(021112e4)=#0(0x00000000)
 <中略>
:020CA77C E3A020C1 mov r2,#0xC1 ;r2=193(0xc1)
:020CA780 E3A00008 mov r0,#0x8 ;r0=8(0x8)
:020CA784 E1C320B0 strh r2,[r3, #+0x0] ;r3+0x0=*(04000102)=#0(0x00000000)

【データ部】
:020CA7A8 04000102
<ここまで引用>

タイマ制御レジスタ(0)に入れた値がC1(1100 0001)だから、

・Enable=ON
・IRQ=ON
・Prescaler=01=Every 64 clocks

つまり、33.4MHz=33,400,000÷Every 64 clocksだから、521,875 tick/sec
すなわち、1tick = 1/521,875秒 ってことか

だから、宝の地図のランク、シード、場所とかドロップアイテムを中断技的にいじるには、


       ■ 1 / 52万1,875 秒 の反射神経が必要■


ということか。

以上をひとこでいえば「制御不可能」
133名無しさん@お腹いっぱい。:2009/09/09(水) 10:25:41 ID:zopPnnO0
ま、むしろ、宝地図の青箱乱数が、システムタイマー使わずに「秒」をシードに
してるほうが不思議かw

設計仕様の瑕疵
134名無しさん@お腹いっぱい。:2009/09/09(水) 14:20:24 ID:8iBVASjq
戦闘時の乱数制御は無理だけど、結果から乱数シードを逆算するのは可能かもしれない
戦闘開始時の乱数シードは020CA828から得ているっぽいんだけど、
電源投入からの秒数を合わせれば、1秒内のずれは100万ぐらいのパターンに収まりそう
100万からの検索なら、2,3ターンの結果から、絞り込めるかも
やるには、戦闘時のルーチンをほぼ全て解析しないといけないけど…
135名無しさん@お腹いっぱい。:2009/09/09(水) 14:31:33 ID:DVCWDeze
わざわざ秒単位なのは、意図的なものを感じるけどね。
かつての裏技みたいなのか、はたまたデバッグを楽にしたかったとか。
136名無しさん@お腹いっぱい。:2009/09/09(水) 14:45:52 ID:Yym6V6jl
電池の消耗抑えるために、秒単位のタイマーかとおもったが、
高速タイマーも実装されてるのか。


青宝箱はわざとにしか思えない。
137名無しさん@お腹いっぱい。:2009/09/09(水) 15:34:19 ID:zopPnnO0
戦闘時乱数はSEEDが64ビットだから「シラミつぶし」法は、無理ではないかと。
(地図場所解析のときは、せいぜい6万5536程度だったからそれでできた)

クロックの早いPC(たとえば、3GHz)で計算したとしても、上のARMソースで出てるのと同じくらいの
ステップ(20tickくらい)かかるから、1秒でせいぜい1.5億演算程度。実際、総数的にメモリにおいて
おくことは不可能だから(明示にHDDカキコするか仮想メモリかはおいておいて、いずれにせよ)
ファイルIOが発生するので、効率は1/10程度になるでしょう

そうすると、毎秒1500万演算程度。1日(86,400sec)で1.3兆演算、1年で475兆演算。

シラミつぶしで全SEED(2の64乗)計算すると、

 2**64 ÷ 475兆/年 = 16×1024**6 ÷ (475 × 1000**4)
                ≒ 16÷475 × 1000**2
                = 0.034 × 1000 × 1000
                = 3万4000年

人類が滅亡するまでに計算が終わるか微妙なような・・・
138名無しさん@お腹いっぱい。:2009/09/09(水) 15:42:51 ID:yY49n/cS
タイマーの分だけ乱数列が出来るだけじゃないの?
139名無しさん@お腹いっぱい。:2009/09/09(水) 15:44:31 ID:zopPnnO0
タイマーが「秒」しかない、とか「16bitの1個」しかないなら楽なんですけどね
140名無しさん@お腹いっぱい。:2009/09/09(水) 16:50:22 ID:8iBVASjq
SEEDは64bitだが、単純にタイマーの数値を並べているだけだから
1秒間で変化があるのは20bitぐらいだよ
使っているのは、高速な順に04000100,021112e0,021112e4
なので、電源投入後1分後に戦闘開始などと決めて、ずれを少なくできれば、
100万程度のしらみつぶしで探索可能、十分計算可能な範囲だよ
141名無しさん@お腹いっぱい。:2009/09/09(水) 18:44:10 ID:qOXouKrH
ID:zopPnnO0
142名無しさん@お腹いっぱい。:2009/09/09(水) 20:49:00 ID:pt1kUVpE
>>140
> 1秒間で変化があるのは20bitぐらいだよ

はぁ?

> タイマ制御レジスタ(0)に入れた値がC1(1100 0001)だから、
>
> ・Enable=ON
> ・IRQ=ON
> ・Prescaler=01=Every 64 clocks

Every 64 clocksってことは1秒間に52万回回る
だから、16bitのレジスタ(65535)は、1秒で約8回転するんだよ?
(1/8秒でオーバフロー割り込み発生)
143名無しさん@お腹いっぱい。:2009/09/09(水) 20:57:59 ID:ZshRHN75
>>140
> 使っているのは、高速な順に04000100,021112e0,021112e4

何言ってるのおまい??? さっきから妙なことばっか書いてるけど???

04000104だって使ってるし、制御C1だから速度同じだし
021112e0〜021112e4 ってふつうのメモリだし

こいつ触らない方がいいぽ? > ID:8iBVASjq
144名無しさん@お腹いっぱい。:2009/09/09(水) 20:58:08 ID:yY49n/cS
16bit×8なら20bitでいいのでは
145名無しさん@お腹いっぱい。:2009/09/09(水) 21:08:52 ID:ZshRHN75
>>144
カスケイドビットは立ってませんが何か?w
詰んだ?
146名無しさん@お腹いっぱい。:2009/09/09(水) 23:02:40 ID:8iBVASjq
>>143
とりあえず落ち着け

SEEDの設定値の取得ルーチンのアドレス(020CA828)を出してるんだから、中身を見なさい
021112e0と021112e4はソフト制御のカウンターのアドレス
04000100にこの2つのアドレスの値をあわせてSEEDにしている
147名無しさん@お腹いっぱい。:2009/09/09(水) 23:12:25 ID:8iBVASjq
補足すると、020ca828は04000100を元に作られるタイマーの値を64bitで出力する関数だね
148名無しさん@お腹いっぱい。:2009/09/09(水) 23:28:22 ID:/VmdbqkW
■「マジコンとPAR」の違いをエンエンと書いてる馬鹿って何なの?■

通常人(インチキせずに普通に遊んでる人)にとって


    マジコン = PAR = チートで

FA
違いをグダグダ書いてるのはチータ。このスレに来んな!
149名無しさん@お腹いっぱい。:2009/09/10(木) 09:32:09 ID:hoCRsb/E
>>148
いや、それは別だと思う。
150名無しさん@お腹いっぱい。:2009/09/10(木) 21:55:27 ID:Gir9Q9f+
コピペに触るな
151名無しさん@お腹いっぱい。:2009/09/11(金) 14:12:15 ID:H/X5jnHW
マジコンとPARの違いが分からん奴が
このスレに来るわけなかろうて
152名無しさん@お腹いっぱい。:2009/09/11(金) 15:10:38 ID:X/b8olw5
ノシ
153名無しさん@お腹いっぱい。:2009/09/12(土) 21:12:11 ID:fNQXC/se
各フロアの宝の数はSeedとRankから求まるのだすか?
154名無しさん@お腹いっぱい。:2009/09/13(日) 01:24:56 ID:CbSLYdZM
私も各フロアの宝箱の数の求め方(SEEDとRANKを使用?)が知りたいです
155名無しさん@お腹いっぱい。:2009/09/13(日) 06:19:39 ID:c09MuAMu
>>153 >>154
ちゃんと計算するには
フロア構造の計算も必要になる。
というのも乱数seedをセットしてから
宝箱の計算までに乱数生成が多数あるので。
各フロアの計算毎に、乱数seedは地図のseed + 階層で初期化。
数を求めている場所だけなら
if( floor >= 3 )
  1 + rand() % 3
こんだけ。
156名無しさん@お腹いっぱい。:2009/09/13(日) 09:04:49 ID:CbSLYdZM
>>155
ありがとうございます。

フロア構造の計算も既出なんですか!?
恐縮ですが、宜しければそれも知りたいです・・
157名無しさん@お腹いっぱい。:2009/09/13(日) 16:01:03 ID:c09MuAMu
>>156
いや、わたしはasa-o氏のセーブデータ改造ツールを解析して
ちょっと流れを見ただけなのであまりよくはわかってないです・・・
それに処理は結構長いのでここに載せるのは大変かと。
158名無しさん@お腹いっぱい。:2009/09/14(月) 10:10:31 ID:5Wq9d16Q
何フロア目まで存在するのかの算出方法もわかるとすっごい助かる。
159名無しさん@お腹いっぱい。:2009/09/14(月) 11:22:46 ID:5Wq9d16Q
>>155
川崎ロッカーで試してみたが、値がちがうっぽい。

floor B3, rand=5f32, 1+rand()%3=2
floor B4, rand=20f8, 1+rand()%3=2
floor B5, rand=62be, 1+rand()%3=1
floor B6, rand=2485, 1+rand()%3=2
floor B7, rand=664b, 1+rand()%3=1
floor B8, rand=2811, 1+rand()%3=1
floor B9, rand=69d8, 1+rand()%3=1
floor B10, rand=2b9e, 1+rand()%3=1
floor B11, rand=6d64, 1+rand()%3=3
floor B12, rand=2f2b, 1+rand()%3=1
floor B13, rand=70f1, 1+rand()%3=3
floor B14, rand=32b7, 1+rand()%3=3

何か根本的な勘違いをしているのだろうか…
160名無しさん@お腹いっぱい。:2009/09/14(月) 12:54:12 ID:zaDRsjTP
156です

私も159氏のように実験してみましたが値が違うようです。

地図解析ツールでの結果を見ると、各階区分(1〜4、5〜9、10〜14、15〜16)でそれぞれSEED毎にMAPが1つずつ後方にずれていっており
(分かりやすく言うと、SEED=0000の2〜4階と、SEED=0001の1〜3階が同じMAP)

宝箱数も同様なので、上記の各階区分毎に計算式が違うように思えます。

計算式までは分かりませんでしたが…orz
161名無しさん@お腹いっぱい。:2009/09/14(月) 12:58:04 ID:BBh30fxp
>>159
たとえば川崎ロッカー(Seed 0x3CA2)3階の場合
フロア計算の初期seedが
0x3CA2 + 3 = 0x3CA5 になる。
で、その後なんやかんやで宝箱の数の算出までに117回乱数生成がある。
118回目の乱数生成された値が 0x6E73 となる。
0x6E73 % 3 + 1 = 1
で、3階は1個の宝箱。
14階なら
seed = 0x3CB0
乱数生成235回目の値が宝箱の数
0x1A96 % 3 + 1 = 3
14階は3個の宝箱。
162名無しさん@お腹いっぱい。:2009/09/14(月) 14:09:47 ID:5Wq9d16Q
>>161
なるほど。
B3 -> 118回目に0x6e73
B14 -> 235回目に0x1a96
は確認できました。

>で、その後なんやかんやで宝箱の数の算出までに117回乱数生成がある。
この「なんやかんや」で乱数が使用される回数が算出できれば宝箱の個数が算出できるわけですね。
マップの生成処理っぽいんですごい複雑だとは思いますが。
163名無しさん@お腹いっぱい。:2009/09/14(月) 18:35:41 ID:zaDRsjTP
>>161
なるほど…
階が増える毎に乱数振る数増えてるのはMAPの大きさに関係あるんですかねぇ〜
例えばMAP作ってから(1マス毎に乱数振ってる?)宝箱の乱数振るとか…

118の近似値
 →10×10=100
 →11×11=121

235の近似値
 →15×15=225
 →16×16=256

帰宅したら色々やってみます^^
164名無しさん@お腹いっぱい。:2009/09/14(月) 23:34:09 ID:JcapU6z6
耳障りな話ですが、地図攻略スレ等で必要以上に知識を
ひけらかしたり、すぐに煽ったり、大人げない行動は止めましょう。
純粋に解析している人にも迷惑が掛るので。
165名無しさん@お腹いっぱい。:2009/09/15(火) 06:36:49 ID:PeeBAHqf
はしゃいでるの一人だけっしょ
166名無しさん@お腹いっぱい。:2009/09/15(火) 08:56:31 ID:dONa58bZ
>>164
誰に言っている…?
167名無しさん@お腹いっぱい。:2009/09/16(水) 04:05:31 ID:Z8SOM7gf
なにこの頭いいスレ
ハックロム作って宝箱の中身をリアルタイムに出せるゲームに改変できるレベルの人たちか
168名無しさん@お腹いっぱい。:2009/09/16(水) 08:16:56 ID:NltGM1j+
156です

人に頼りっぱなしは良くないと思い、初めて逆汗にチャレンジしてみました(笑)

思ったより簡単で、知りたかったことは大枠分かりました。MAP生成ロジックがかなり難しく苦戦中です^^;

書き込み頂きました皆さん、ありがとうございました^^
169名無しさん@お腹いっぱい。:2009/09/19(土) 04:51:02 ID:bW6TyFTp
ほしゅ
170名無しさん@お腹いっぱい。:2009/09/19(土) 09:22:48 ID:qOUqOxMz
42 名前:名前が無い@ただの名無しのようだ[sage] 投稿日:2009/09/18(金) 18:06:58 ID:NW4hEYQO0
>>41
>>27を参照すると
rankが161以上181以下になればいーんかな?間違ってたらごめんけど。
172でプラマイ10パーの影響あってとる値は155~189
数値の個数は35
161~181の数値の個数は21
21/35×100=60
で60パーでいーんでない?中学レベルの回答だけどな。

43 名前:名前が無い@ただの名無しのようだ[sage] 投稿日:2009/09/18(金) 18:09:45 ID:NW4hEYQO0
ああ、勿論、上の回答はプラマイ10パーの値が均等に出る場合な。
まあ解析で均等に出るって分かってるからいいけども。

44 名前:名前が無い@ただの名無しのようだ[sage] 投稿日:2009/09/18(金) 18:19:02 ID:NW4hEYQO0
あとあくまで最浅が出るランクが出る可能性だから。
最浅がその内の何パーか分かれば掛ければいい。

…ついでに調べたら1039/32768か
電卓で…約1.9%と出た。まあ、がんがれ。
171名無しさん@お腹いっぱい。:2009/09/21(月) 09:19:03 ID:dgIDTKOe
イタイ子が解析してくれって頼んでますよ
ttp://jbbs.livedoor.jp/bbs/read.cgi/game/48853/1252553347/

193 :名無し:2009/09/21(月) 08:44:49
>>192
「DS本体を変えると乱数が変わるのでは」という話を解析者がしていたが
数字的に立証できるレベルの人はあそこにはいないような気がします
(もし解析するならうちの妹の友達のプロの人のほうがよっぽど信頼できる
でも、そこまでするのは自分自身がグレーゾーンへ突入する可能性がある)

それを体感的に検証できないか?というのが今回の実験なんです
ここまで書くと「あいつは改造者と同じスレ覗いてる」と言われて
地図の改造疑惑が立つといけないので
このスレを利用して
「私の地図がどのような状況でどうやって取得したか」
を予防線として書き続けてたのです
172名無しさん@お腹いっぱい。:2009/09/21(月) 11:21:54 ID:LuYlYQ2q
アンチコテうざい
173名無しさん@お腹いっぱい。:2009/09/24(木) 20:04:07 ID:dYwZD93Z
156です

>>162
なんやかんやで乱数振る回数がMAP生成処理によってだいぶ変わってくるようなので、MAP生成処理を計算せずに乱数回数を求めるのはほぼ不可能っぽいです^^;

ほぼ解析完了したはずなのに、プログラムに落としてみると結果が微妙に違うorz
どこか勘違いしているのだろうか・・・
174名無しさん@お腹いっぱい。:2009/10/09(金) 12:45:38 ID:jxx+P4sU
wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
175名無しさん@お腹いっぱい。:2009/10/09(金) 12:53:23 ID:tPpabCme
>>174
保守乙
176名無しさん@お腹いっぱい。:2009/10/16(金) 01:47:39 ID:0z9EEAIr
SEEDから地図の場所を絞り込む計算式を
誰か張ってくれませんか?
177名無しさん@お腹いっぱい。:2009/10/16(金) 12:16:10 ID:u6MHTlZq
解析職人の人。
これ分からない?

13 :名前が無い@ただの名無しのようだ :sage :2009/10/15(木) 16:36:41 ID:U9Y+Vj5/P
dq9tmap101.exeで無無無判定なのに、B13Fウーオンリー

RANK,SEED=DD 1314(221 4884)
あらぶる空の水脈LV67
BOSS=スライムジェネラル
階層=14
敵RANK=9
B13 16x16 ElistOfs=1E30
178名無しさん@お腹いっぱい。:2009/10/26(月) 03:33:22 ID:EkYd8swv
>>176
そんなものはない
総当りでSEEDと場所の組み合わせを求めるなら出来るけど
179名無しさん@お腹いっぱい。:2009/11/10(火) 08:03:58 ID:Dri/bCED
ほしゅのあき
180名無しさん@お腹いっぱい。:2009/11/10(火) 20:26:34 ID:7U9PmDp0
SSBの法則とかわかんないかな
181名無しさん@お腹いっぱい。:2009/11/13(金) 15:26:51 ID:nZ97ZZWa
地図の解析のことでこのスレにきたんですがやり方を教えて下さい。
182名無しさん@お腹いっぱい。:2009/11/14(土) 15:12:59 ID:eN8UVOu0
183名無しさん@お腹いっぱい。:2009/11/16(月) 20:51:42 ID:vvA1+ox+
このスレにこれたのは質問した時につないでもらったからでそこからしかこのスレこれません。
どうやったらこのスレに簡単にこれますか。
あと今さらですがソースってなんですか。
184名無しさん@お腹いっぱい。:2009/11/16(月) 23:43:16 ID:Q52BxaMQ
>>12のやり方でtxtの容量が増えまくったよ・・
1G越えた辺りで強制終了したけど死ぬかと思った
185名無しさん@お腹いっぱい。:2009/11/19(木) 20:26:05 ID:gRClyDF7
これを解析してください。とどろく魂のじごくレベル98
B15ボスフォロボス
186名無しさん@お腹いっぱい。:2009/11/20(金) 02:53:20 ID:3Ol2uWRb
>>185
解析した。あんまり面白くなかった。
187名無しさん@お腹いっぱい。:2009/11/20(金) 19:58:21 ID:nf7eTjmw
>>186
解析してくれてありがとうございます。
面白くなかったんですね。名前にじごくがついていたんで期待してたんですが。
188名無しさん@お腹いっぱい。:2009/11/29(日) 12:49:24 ID:alMeCIni
遅ればせながら、最近になってこのスレを知り解析を始めました。
ところが、乱数ルーチンは見つかったけど、それを呼び出している部分がひとつも見つからない。
と思ったら、どうやら ARM9 コードに暗号化が施されているということのようですね。
>>12 の方がその場合のやり方を書かれてますが +αで自分のやったやり方を書いてみます。

1.ROM を吸い出す(自分は SMS2 で一晩かかって吸い出しました)
2.>>1 のツールで「ndsdis2 -9 吸い出したファイル名 > dq9asm.txt」で逆アセする
3.>>12 の方法で desmume と haste を使用し、4MB のダンプファイルを作る
4.「ndsdis2 -NH9 2000000 ダンプファイル名 > dq9nh9.txt」で逆アセする
  ワークエリアまで含めて逆アセされるため、ファイルサイズは 40MB ほどになるので注意
5.dq9asm.txt を開き、ヘッダ情報から ARM9 コードの開始・終了アドレスを調べる
  ARM9_copy to address : 02000000 , ARM9_binary size : 0009bcf8 なので、
  ARM9 コードの範囲は、02000000 から 0209bcf8 の直前までということになります
6.dq9nh9.txt を開き、上で調べた範囲をクリップボードへコピーするか、ファイルに書き出す
  具体的には、最初の :02000000 から :0209BCF4 までとなります
7.dq9asm.txt を開き、上のをヘッダ情報と ARM7 コードの間に挿入して上書き保存する

以上の方法により、ヘッダ付・ARM7 コード付・ワークエリアなしの逆アセリストができます。
189名無しさん@お腹いっぱい。:2009/11/29(日) 16:37:44 ID:BvI9O9jn
>>188
ありがと
少し進展した
190名無しさん@お腹いっぱい。:2009/11/30(月) 00:59:53 ID:nuT0fIeP
armお勧めの基本書ないですか?
リファレンスが難しすぎる
191名無しさん@お腹いっぱい。:2009/11/30(月) 15:58:55 ID:kA5+YjGf
>>190
ネット上で無料で見ることができるものでは >>5 で紹介されているサイトや、
ndsdis2 の作者さんが書かれた次のサイトが参考になるかと。
ttp://hp.vector.co.jp/authors/VA018359/nds/dip_top.htm
その2つのサイトとこのスレを読むだけで、かなりの部分は理解できる。
書籍については持ってないので残念ながらわかりません。
192名無しさん@お腹いっぱい。:2009/11/30(月) 18:59:17 ID:nuT0fIeP
>>191
ありがとうございます。

:02012564 E59F1020 ldr r1,[r15, #+0x20] ;r15+0x20=*(0201258c)=#99999999(0x05f5e0ff)

↑で#が定数、0xが16進数というわかったんですが「;」以降が理解不能でした
=*なんかも・・
193名無しさん@お腹いっぱい。:2009/11/30(月) 20:13:59 ID:kA5+YjGf
>>192
「;」以降は ndsdis2 の仮想レジスタ解析機能によって追加されています。(作者さんに感謝)
これにより、どのアドレスを参照していて何を読み込んでくるかわかるので大変便利です。

:02012564 E59F1020 ldr r1,[r15, #+0x20] ;r15+0x20=*(0201258c)=#99999999(0x05f5e0ff)

ldr r1,[r15,#+0x20] だけじゃ r15+0x20 つまり pc+0x20 がどこを指しているのかわかりにくい。
それを「;」以降で、r15+0x20 は 0201258c になるということ(このちょっと先にあるはずですね)、
そして、そのアドレスのメモリ値は 99999999(0x05f5e0ff) であることを教えてくれているわけです。
なお、*(アドレス) というのは C言語的な表現で、そのアドレスのメモリ値ということです。
上記の場合は ldr なので 4バイト値ですが、ldrh なら 2バイト値、ldrb なら 1バイト値となります。

ということは、mov r1,#99999999 と言い換えることができますが、ARM ではこのような複雑な値を
直接扱うことができないので、上記のような解析しづらい間接参照を用いるのが定石のようです。
>>3 で add r0,r0,#0x39 add r0,r0,#0x3000 と分けているのも 0x3039 を一気に足せないからです。
そういうわけで、このような間接参照は鬼のように出てきますが、「;」以降のお陰で怖くないですね。

とまぁ、わかっている方には何を今さら的な内容をだらだら書いてしまい、もうしわけない。
194名無しさん@お腹いっぱい。:2009/11/30(月) 20:54:03 ID:nuT0fIeP
>>193
素晴らしい解説ありがとうございます。
ほんと感謝です。
195名無しさん@お腹いっぱい。:2009/12/01(火) 21:18:21 ID:3T2S3buu
そういや最近SSB技とか言うのが出てきてるけど、最強錬金時の処理ってどうなってんだろ?
196 ◆d3chvFcvi. :2009/12/23(水) 22:02:16 ID:Fg86J8Bp
テス
197 ◆kEa6fbWxOE :2009/12/23(水) 22:12:03 ID:Fg86J8Bp
テス
198名無しさん@お腹いっぱい。:2010/01/05(火) 18:24:11 ID:rIBTH+8/
某所で話題のホイミテーブルの乱数生成器を見つけたのでこっそり投下
>>128と同様な乱数で、こちらはデータ領域(乱数シードなど)が02108d20にある

ホイミの回復量から乱数シードを検索して、その後の回復量(確率)を計算するプログラム
回復量を5,6個入れれば特定できるはず
タイマーで乱数シードを初期化しているので、電源オン時はここで探索している範囲に入るはず

使い方はこんな感じ
$ ./a.out 32 30 31 31 37 37

#include <stdio.h>
unsigned long long rand_seed; //0x02108d20
unsigned long rand(void)
{
rand_seed = rand_seed * 0x5d588b656c078965ULL + 0x269ec3ULL;
return (rand_seed >> 32) & 0xffffffff;
}
int main(int argc, char *argv[])
{
unsigned int i;
unsigned long long i_max=0x100000000ULL,first_seed;
double d;
int hoimi[6];

if(argc < 3) return 0;
argc--;
for(i=0;i<argc;i++)
{
hoimi[i] = strtol(argv[i+1],NULL,10)-30;
}
for(first_seed=0x10000;first_seed<0x50000;first_seed++)
{
rand_seed = first_seed;
for(i=0;i<argc;i++)
{
d = rand();
d /= i_max;
if((d<(double)hoimi[i]/10-0.05) || (d>(double)hoimi[i]/10+0.05)) break;
}
if(i!=argc)
{
continue;
}
printf("%016llx",first_seed);
rand_seed = first_seed;
for(i=0;i<100;i++)
{
d = rand();
d /= i_max;
if(!(i%10)) printf("\n");
printf("%.0f(%.1f%%) ",30+d*10,d*100);
}
printf("\n");
}
return 0;
}
199名無しさん@お腹いっぱい。:2010/01/05(火) 22:22:13 ID:GoUk1kN/
何だこのスレ。
高度すぎて、
荒らしが意味不明な文字列を並べてるようにしか見えん。
200名無しさん@お腹いっぱい。:2010/01/05(火) 23:23:32 ID:f7ize32G
Youもプログラムかじっちゃいなyo
201名無しさん@お腹いっぱい。:2010/01/05(火) 23:56:50 ID:GoUk1kN/
VBかじったけどわかんねえんだよ!!!
202名無しさん@お腹いっぱい。:2010/01/06(水) 00:21:13 ID:kVOZabPD
>>198
数パターンですが検証してみました。完璧です。
レアドロップ(2%)はもちろん
種ドロップ(0.39%)も判定できるな。
203名無しさん@お腹いっぱい。:2010/01/06(水) 17:44:37 ID:00LNQ3M1
ほんとこういうの作れるひとはすごいわ
204名無しさん@お腹いっぱい。:2010/01/08(金) 02:14:03 ID:/30j4RI9
最低回復量で悩んでるみたいなので投下

ホイミ 30+(回復魔力- 50)*125/949 + 乱数(0〜10)
ベホイミ 75+(回復魔力-100)*215/899 + 乱数(0〜20)
ベホイム 165+(回復魔力-200)*415/799 + 乱数(0〜40)
205名無しさん@お腹いっぱい。:2010/01/08(金) 02:22:57 ID:/30j4RI9
ザコ戦についてもちょっとだけ
エンカウント時に、(シンボル別のテーブルと)乱数で、どんな構成の敵が出るかを
決めている。(お供の種類とか、それぞれの匹数とか)

ので、逃げても無駄
206名無しさん@お腹いっぱい。:2010/01/08(金) 22:02:39 ID:HVolwcDA
>ので、逃げても無駄

素でどういう理論なのかワカンネ。
207名無しさん@お腹いっぱい。:2010/01/09(土) 03:11:11 ID:pAAmdJYn
>>206
逃げても乱数が進んじゃうってことだよ。
208名無しさん@お腹いっぱい。:2010/02/06(土) 17:34:11 ID:vOymGHGV
保守保守
209名無しさん@お腹いっぱい。:2010/02/23(火) 09:52:23 ID:22bfcziQ
俺も保守
210名無しさん@お腹いっぱい。:2010/03/12(金) 14:42:15 ID:M/6p0Wlq
AT消費量検証用

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

long SEED0=0x3ca2; // 川崎ロッカー
long seed;
int dq9rand(){seed=seed*1103515245+12345;return (int)((seed>>16)&0x7FFF);}
void skip(int n){while(n-->0) dq9rand();}

int main(int argc,char **argv){
int i,j, buf[12][10],idx[12],mem[60];
int chk[12];
int searchLast=1000;
chk[0]=-1;

i=1;
if( argc>1 && strnicmp(argv[i],"/S=",3)==0 ) SEED0=strtol(argv[i++],0,16),argc--;
if( argc>1 && strnicmp(argv[i],"/n=",3)==0 ) searchLast=atol(argv[i++]),argc--;
if( argc>1 ){
char *p=argv[1];
for( i=0; i<12; i++ ){
if( *p==',' ) p++;
if( *p==0 ) break;
sscanf(p,"%d%n,",&chk[i],&j);p+=j;
}
if( i<12 ){ printf("arg ERROR\n");return 1;}
}

for(int nSkip=0;nSkip<searchLast;nSkip++ ){
seed=SEED0;skip(nSkip);

for(i=0;i<12;i++) for(j=0;j<10;j++) buf[i][j]=-1;
for(i=0;i<12;i++) idx[i]=0;

for(i=0;i<60;i++){
j=dq9rand()%12;
while(idx[j]>=10) j=(j+1)%12;
buf[j][idx[j]++]=i;mem[i]=j;
}

for(i=0;i<12;i++) if( chk[i]!=idx[i] ){ i=-1;break;}
if( i>0 ){
printf("\n===== SEED=0x%04X nSkip=%d =====\n",SEED0,nSkip);
for(j=9;j>=0;j--){
for(i=0;i<12;i++) printf((buf[i][j]<0)?" ":" (%2d)",buf[i][j]);
printf("\n");
}
}
if( chk[0]<0 ){
for(i=0;i<12;i++) printf("%d,",idx[i]);
for(i=0;i<60;i++) printf("%d",mem[i]);
printf("\n");
}
}
return 0;
}

211210:2010/03/12(金) 15:10:40 ID:M/6p0Wlq

ごめんなさい。オプション追加したらミスりました。
/*** 誤 ***/
// if( argc>1 && strnicmp(argv[i],"/S=",3)==0 ) SEED0=strtol(argv[i++],0,16),argc--;
// if( argc>1 && strnicmp(argv[i],"/n=",3)==0 ) searchLast=atol(argv[i++]),argc--;
// if( argc>1 ){
// char *p=argv[1];
/*** 正 ***/
if( argc>1 && strncmp(argv[i],"/S=",3)==0 ) SEED0=strtol(argv[i++]+3,0,16),argc--;
if( argc>1 && strncmp(argv[i],"/n=",3)==0 ) searchLast=atol(argv[i++]+3),argc--;
if( argc>1 ){
char *p=argv[i];

使い方
(1) WiFi接続が失敗する環境を作る(無線を切る、離れる、ルータではじく、etc)
(2) 適当な地図(デフォルトでは3ca2=ロッカー)を使い、地図法
(3) 何かの行動をする
(4) WiFi接続をする。
(5) 落ちてくるスライムの最初のいくつかを覚える
(6) 最終的に60個落ちてきた時の形を左から、数える (例えば、左端に5個、左から2番目が8個…右端が8個)
(7) このプログラムを実行する
(8) 複数結果が出たときは、(5)で覚えたスライムで判断

実行例
cint.exe test.cpp "/S=3CA2" "/n=2000" "5,8,3,1,5,2,7,3,7,6,5,8"

著作権の放棄はしませんが、改変・再配布・その他、ご自由にどうぞ
もちろん各自でコンパイルして再配布して構いませんし、改良していただけるとなおうれしい
212名無しさん@お腹いっぱい。:2010/03/12(金) 20:06:06 ID:iGfD9QNi

for(int nSkip=0;nSkip<searchLast;nSkip++ ){
seed=SEED0;skip(nSkip);
...
}

というのは効率よくないね。

seed=SEED0;skip(nSkip);
for(int nSkip=0;nSkip<searchLast;nSkip++ ){
seed0 = seed;
...
seed = seed0;
drand();
}

とした方がいいよ。
213名無しさん@お腹いっぱい。:2010/03/12(金) 20:08:34 ID:iGfD9QNi
しまった drand() ではなく dq9rand() か
自作のツールと間違えたw
214210:2010/03/12(金) 22:37:42 ID:M/6p0Wlq
>>212
いやあ、効率を上げようと思えば、まだまだいくらでも
R[0〜59] = dq9rand()%12;
とかやっておいて、ループ毎に1つだけ更新するとか…

skip()だって、剰余の性質を利用すれば、ループ回数を減らせるし
#例えば ((S*A+B)*A+B)%M == (S*A*A+B*A+B)%M == (S*(A*A%M)+(B*A+B)%M)%M == (S*A2+B2)%M

ただそれをやってしまうと理解しにくくなって、公開した意味が薄れてしまうので、あえての非効率です
だからこその 「改変・再配布・その他、ご自由にどうぞ」 でもあります
というわけで、改変・再配布・その他、ご自由にどうぞ
215名無しさん@お腹いっぱい。:2010/03/12(金) 23:09:22 ID:iGfD9QNi
効率よりわかりやすさというのはいいと思います。
じっさいこのままで遅いというレベルではないですね。

ただ、情報エントロピーを簡単に計算してみた感じでは、(8) のケースはありえないと断言できるレベルですね。
ということで、山の出力をばっさり削ってしまうとこんな感じでしょうか

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

long SEED0=0x3ca2; // 川崎ロッカー
long seed, seed2;
int dq9rand(){seed=seed*1103515245+12345;return (int)((seed>>16)&0x7FFF);}
int dq9rand2(){seed2=seed2*1103515245+12345;return (int)((seed2>>16)&0x7FFF);}

int main(int argc,char **argv){
unsigned long long T=0,A=0,B;
unsigned long long w[12]={1};
int i,j,chk;
int searchLast=1000;

for( i=1; i<12; i++ ) w[i] = w[i-1]*10;

i=1;
if( argc>1 && strncmp(argv[i],"/S=",3)==0 ) SEED0=strtol(argv[i++]+3,0,16),argc--;
if( argc>1 && strncmp(argv[i],"/n=",3)==0 ) searchLast=atol(argv[i++]+3),argc--;
if( argc>1 ){
char *p=argv[i];
for( i=0; i<12; i++ ){
if( *p==',' ) p++;
if( *p==0 ) break;
sscanf(p,"%d%n,",&chk,&j);p+=j;
T += w[i]*chk;
}
if( i<12 ){ printf("arg ERROR\n");return 1;}
}

seed = seed2 = SEED0;
for (i=0; i < 60;i++) {
A += w[dq9rand()%12];
}

for(int nSkip=0;nSkip<searchLast;nSkip++ ){
B = A / 1000000000000ULL + A % 1000000000000ULL;
if (B == T) {
printf("SEED=0x%04X nSkip=%d \n",SEED0,nSkip);
}
A += w[dq9rand()%12]-w[dq9rand2()%12];
}
return 0;
}

216名無しさん@お腹いっぱい。:2010/03/12(金) 23:29:10 ID:iGfD9QNi
って間違ってるじゃん。>>215 のプログラムは忘れてください。
今日はもう寝よう。

217名無しさん@お腹いっぱい。:2010/03/13(土) 13:37:20 ID:SXdFX+N8
>>215
実際には、乱数列の連続した 60 個によってスライム落下の位置パターンが決まっているので、
n 番目と n+60 番目の乱数値を 12 で割った余りが同じなら、ほとんどの場合で n と n+1 の両方の候補が出ますね。
210 さんのソースを参考に cgi を作ってみましたが、例えば↓の例のような場合がそうなります。
ttp://www16.atpages.jp/hayao/slimedrop.cgi?seed=3ca2&pat=257344545A92

なお、↓で確認できますが、63 番目と 123 番目の乱数値を 12 で割った余りは共に 8 です。
ttp://www16.atpages.jp/hayao/rndcalc.cgi?seed=3ca2&skip=1¶2=12
218名無しさん@お腹いっぱい。:2010/03/13(土) 14:39:14 ID:pmnDMowS
>>217
>n 番目と n+60 番目の乱数値を 12 で割った余りが同じなら、ほとんどの場合で n と n+1 の両方の候補が出ますね。
ほとんどではなく、確実にですね。全部書いてみてから気づきました。
ということでこのままでは使いものになりませんが、>>215 の訂正版。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
long SEED0=0x3ca2; // 川崎ロッカー
long seed, seed2;
int dq9rand(){seed=seed*1103515245+12345;return (int)((seed>>16)&0x7FFF);}
int dq9rand2(){seed2=seed2*1103515245+12345;return (int)((seed2>>16)&0x7FFF);}
int main(int argc,char **argv){
int i,j;
int chk[12], num[12], c, n;
int searchLast=1000;
i=1;
chk[0]=-1;
if( argc>1 && strncmp(argv[i],"/S=",3)==0 ) SEED0=strtol(argv[i++]+3,0,16),argc--;
if( argc>1 && strncmp(argv[i],"/n=",3)==0 ) searchLast=atol(argv[i++]+3),argc--;
if( argc>1 ){
char *p=argv[i];
for( i=0; i<12; i++ ){
if( *p==',' ) p++;
if( *p==0 ) break;
sscanf(p,"%d%n,",&chk[i],&j);p+=j;
}
if( i<12 ){ printf("arg ERROR\n");return 1;}
}
for(i=0;i < 12; i++) num[i]=0;
seed = seed2 = SEED0;
for (i=0; i < 60;i++) num[dq9rand()%12]++;
for(int nSkip=0;nSkip<searchLast;nSkip++ ){
c=0;
for (i=6;i<12;i++) c = (c + num[i] > 10) ? c+num[i]-10 : 0;
for (i=0;i<12;i++) {
n = c + num[i];
if (n > 10) {c = n - 10; n=10;} else c=0;
if (n != chk[i]) break;
}
if (i == 12) {
printf("SEED=0x%04X nSkip=%d\n",SEED0,nSkip);
}
num[dq9rand2()%12]--;
num[dq9rand()%12]++;
}
if (chk[0] < 0) {
c=0;
for (i=6;i<12;i++) c = (c + num[i] > 10) ? c+num[i]-10 : 0;
for (i=0;i<12;i++) {
n = c + num[i];
if (n > 10) {c = n - 10; n=10;} else c=0;
printf("%d(%d) ",n,num[i]);
}
printf("\n");
}
return 0;
}

219名無しさん@お腹いっぱい。:2010/03/13(土) 15:32:04 ID:SXdFX+N8
>>218
スライムが縦に 10 匹並んでいると、その位置が来ても右にずれますから、n 番目の時はその位置に落とせても、
n+60 番目ではその位置には落とせなくて、違う位置に落ちることにが考えられます。
よって、n と n+60 の位置が同じでも、同じではないパターンになることがありえます。
また、逆に、n と n+60 の位置が違っていても、同じパターンになることもありえます。
220名無しさん@お腹いっぱい。:2010/03/13(土) 16:10:50 ID:pmnDMowS
>>219 結局、11個以上落ちてきた列には10個残って、
その右の列にあふれた分が落ちて行くわけだから、形としては同じになります。
スライムの番号まで区別する場合には変わるけどね。
221名無しさん@お腹いっぱい。:2010/03/13(土) 16:33:37 ID:SXdFX+N8
>>220
失礼しました、よく考えたら、その通りですね。
n と n+60 の位置が同じ場合、n+1 で始まって n+60 で溢れるなら、n から始まっても同じ位置が溢れるはずですね。

さて、溢れの影響で、n と n+60 の位置が違っていても、同じパターンになるという確率は非常に低いので無視すれば、
約 1/12 の確率で前後賞が同じパターンになることになる、ということは、前後合わせて約 1/6 でしょうか?
結構確率が高いので、最初に落ちる数箇所ぐらい覚えておかないと更新回数が確定できないかもしれませんね。
222名無しさん@お腹いっぱい。:2010/03/14(日) 15:25:12 ID:KR7HszvE
参考になるかわかりませんが、とりあえず報告。

セント前、昼、まさゆき、4人、装備なし
地図開閉後、右の「おばけきのこ」単体に「にげる」
wifi接続
"7,10,4,4,5,2,4,5,6,3,6,4"
結果出力されず。
連続して、wifi接続
"9,5,4,6,4,7,7,4,3,3,4,4" → 285
285-88(連続wifi接続時増加分)で、最初のAT値は、197と思われます。
223名無しさん@お腹いっぱい。:2010/03/18(木) 21:03:11 ID:Ihq+nYpa
地図法1.5のスプレッドシートではAT値を計算する処理を工夫しましたので、その解説をします。
数学が嫌いな方には、ちょっときついかもしれませんが・・・。

まず、p1=1103515245, p2=12345 とすると seed=seed*p1+p2 がATで使われるSEED値更新の計算式です。
関数 seed(<地図SEED値>,<回数>) は<地図SEED値>を初期値とし、<回数>だけ更新した時のSEED値と定義します。
seed(n,m+1)=seed(n,m)*p1+p2 となり seed(n,0)=n です。(更新なしなので地図SEED値そのまま)

ここで、seed(n,1)〜seed(n,3) を展開してみます。
seed(n,1)=seed(n,0)*p1+p2=n*p1+p2
seed(n,2)=seed(n,1)*p1+p2=(n*p1+p2)*p1+p2=n*p1^2+p1*p2+p2
seed(n,3)=seed(n,2)*p1+p2=(n*p1^2+p1*p2+p2)*p1+p2=n*p1^3+p1^2*p2+p1*p2+p2

今度は、地図SEED値=0 だった時を考えてみます。
seed(0,1)=seed(0,0)*p1+p2=0*p1+p2=p2
seed(0,2)=seed(0,1)*p1+p2=p1*p2+p2
seed(0,3)=seed(0,2)*p1+p2=(p1*p2+p2)*p1+p2=p1^2*p2+p1*p2+p2

この2つを比較すると、次のようになることが判ります。
seed(n,1)=n*p1+seed(0,1)
seed(n,2)=n*p1^2+seed(0,2)
seed(n,3)=n*p1^3+seed(0,3)

ということで、次のように纏めることができます。
seed(n,m)=n*p1^m+seed(0,m)

ここで、p1^m と seed(0,m) は地図SEED値に左右されない定数となります。
つまり、この2つの定数が判れば、どんな地図SEED値の何回目でも1回の計算で出せるわけです。

では、今度はこの2つの定数について考えてみます。
関数 tmlt(m)=p1^m と定義します。
tmlt(m+1)=p1^(m+1)=p1^m*p1=tmlt(m)*p1
ということで、1つ前の値が判れば、それに p1 を掛ければ次の値は計算できます。
関数 tadd(m)=seed(0,m) と定義します。
tadd(m+1)=seed(0,m+1)=seed(0,m)*p1+p2
ということで、1つ前の値が判れば、SEEDと同様に、それに p1 を掛けて p2 を足せば次の値は計算できます。

さて、地図開閉即接続の場合に参照されるのは、154回更新したSEED値です。
seed(n,154)=n*tmlt(154)+tadd(154) で普通に計算すると tmlt(154)=4094391497, tadd(154)=2268227462 です。
その時のAT値は seed(n,154) >> 16 & 0x7fff=(n*tmlt(154)+tadd(154)) >> 16 & 0x7fff で求まります。
そして、155回目の定数は tmlt(155)=tmlt(154)*p1, tadd(155)=tadd(154)*p1+p2 で計算できますし、その次も同様です。
もしくは、seed(n,154) をこの方法で求め、連続する次以降は seed(n,m+1)=seed(n,m)*p1+p2 で求めてもいいわけです。

なお、ここまで桁あふれのことは無視しましたが、加算でも乗算でもあふれた分は下位に影響しないので問題ありません。
224名無しさん@お腹いっぱい。:2010/03/18(木) 21:28:18 ID:Ihq+nYpa
ををっと、ちょっと式に追加。
tadd(m+1)=seed(0,m+1)=seed(0,m)*p1+p2

tadd(m+1)=seed(0,m+1)=seed(0,m)*p1+p2=tadd(m)*p1+p2
です。
225名無しさん@お腹いっぱい。:2010/03/18(木) 21:45:52 ID:JlN8Y2s0
スレ違いとは思うんだが、保守の代わりに
seed(0,m) = p2 × (p1^(n-1)+p1^(n-2) + … + 1) = p2 × (p1^n - 1)/(p1 - 1)
でよくね?
226名無しさん@お腹いっぱい。:2010/03/18(木) 22:06:03 ID:JlN8Y2s0
と思ったが合同算術論( mod 0x100000000 )で考えないとだめなのか。
単純な割り算はできないな。オイラーの定理とか使えるんだろうか。
227名無しさん@お腹いっぱい。:2010/03/18(木) 23:03:04 ID:Ihq+nYpa
そうですね、p1はでかいので、n乗なんてすれば、すぐに下の方が丸められて全然違う値に化けてしまいますね。
単に p1=1103515245 を掛けるのさえ、スプレッドシートでは 129749 と 8505 の 2回に分けて掛け、その都度 mod 取ってます。
そうしないと、前の値によっては mod 関数で扱える範囲を超えてしまい、エラーが出てしまいますから。
228名無しさん@お腹いっぱい。:2010/03/19(金) 22:37:11 ID:8m1Omxwm
>>223 の理論をホイミテーブルツール >>198 に応用して、ホイミの回復量から
seed と位置の両方を検索するようにしてみた。(出力は位置が小さい順)
>>198 の計算はわかりやすくていいんだけど、ARM で double 型を経由して計算
しているとは思えないので、整数演算に直してみた。

#include <stdio.h>
unsigned long long rand_seed; //0x02108d20

unsigned long brand(void) {
rand_seed = rand_seed * 0x5d588b656c078965ULL + 0x269ec3ULL;
return (rand_seed >> 32) & 0xffffffff;
}

int main(int argc, char *argv[]) {
unsigned int i, skip;
unsigned long long first_seed, seed0, an;
int hoimi[20];
unsigned long r;

if(argc < 3) return 0;
argc--;
for(i=0;i<argc;i++) {
hoimi[i] = strtol(argv[i+1],NULL,10)-30;
}
rand_seed = 0; an = 1;
for (skip = 0; skip < 1000; skip++) {
seed0 = rand_seed;
for(first_seed=0x20000;first_seed<0x40000;first_seed++) {
rand_seed = seed0 + first_seed*an;
for(i=0;i<argc;i++) {
if (((brand()*20ULL>>32)+1)/2 != hoimi[i]) break;
}
if(i==argc) {
printf("seed = %08llx at %d",first_seed, skip);
rand_seed = seed0 + first_seed*an;
for(i=0;i<argc;i++) {
r = brand();
if(!(i%5)) printf("\n");
printf(" %d (%4.1f%%) ", (int)(30+((r*20ULL>>32)+1)/2), 0.1*(r*1000ULL>>32) );
}
printf("\n");
}
}
an *= 0x5d588b656c078965ULL;
rand_seed = seed0;
brand();
}
return 0;
}
229名無しさん@お腹いっぱい。:2010/03/20(土) 12:51:23 ID:ylyqYjmx
>>228
> ARM で double 型を経由して計算
> しているとは思えないので、整数演算に直してみた。
実際のコードは、float(IEEEの単精度浮動小数点)だったりする。
armが浮動小数点演算をもってないとか意識してないコードみたい。
逆汗の一番の障害かもしれん。
230名無しさん@お腹いっぱい。:2010/04/11(日) 01:34:12 ID:73xR/fRj
良スレ保守
231名無しさん@お腹いっぱい。:2010/04/30(金) 08:47:29 ID:mFQIHaON
ほしゅ
232名無しさん@お腹いっぱい。:2010/08/01(日) 00:56:39 ID:MTLtB9VE
z
233名無しさん@お腹いっぱい。:2010/08/12(木) 22:29:46 ID:whlnb0Si
DQ6も解析してくれ
エビルフランケンからドロップ100%法とか
234名無しさん@お腹いっぱい。:2010/11/06(土) 02:05:34 ID:OwmUEDxm
はいはいageますよっと
235名無しさん@お腹いっぱい。:2010/12/29(水) 12:12:13 ID:RnsAVcNb
age
236名無しさん@お腹いっぱい。
暇な人GBA・PSPFF1の時の迷宮でてんしのゆびわが取れるパターンは
絶対選ばれないといわれている理由を教えてちょ