制作日記

こういうの作った方が、逃げにくいじゃない

親ID判定

このへんがステート処理の関数の頭ぐらいで呼ばれてる
ステート移動後に再度ステート処理開始するときも呼ばれる


00424EF0 /$ 8B5424 04 MOV EDX,DWORD PTR SS:[ESP+4]
00424EF4 |. 837A 1C 01 CMP DWORD PTR DS:[EDX+1C],1
00424EF8 |. 74 03 JE SHORT winmugen.00424EFD
00424EFA |. 33C0 XOR EAX,EAX
00424EFC |. C3 RETN
00424EFD |> 8B8A 20260000 MOV ECX,DWORD PTR DS:[EDX+2620]
00424F03 |. 56 PUSH ESI
00424F04 |. 8BB2 1C260000 MOV ESI,DWORD PTR DS:[EDX+261C]
00424F0A |. 8B41 04 MOV EAX,DWORD PTR DS:[ECX+4]
00424F0D |. 2BC6 SUB EAX,ESI
00424F0F |. 5E POP ESI
00424F10 |. F7D8 NEG EAX
00424F12 |. 1BC0 SBB EAX,EAX
00424F14 |. F7D0 NOT EAX
00424F16 |. 23C1 AND EAX,ECX
00424F18 \. C3 RETN


判定処理はここ

00424F04 |. 8BB2 1C260000 MOV ESI,DWORD PTR DS:[EDX+261C]
00424F0A |. 8B41 04 MOV EAX,DWORD PTR DS:[ECX+4]
00424F0D |. 2BC6 SUB EAX,ESI
00424F0F |. 5E POP ESI
00424F10 |. F7D8 NEG EAX
00424F12 |. 1BC0 SBB EAX,EAX
00424F14 |. F7D0 NOT EAX
00424F16 |. 23C1 AND EAX,ECX

上から、
所謂影のIDを取得
parent,idを取得
2つを引き算
使わないレジスタを戻す
引き算の結果の正負反転(元の値が0ならCFが0、それ以外なら1になる)
同じ値同士で引き算、CFが1なら更に1引く(上の引き算結果が0なら0、それ以外なら-1になる)
引き算結果を反転(0なら0xFFFFFFFF、-1なら0になる)
反転結果とparent,idで論理積を取る

要は、parent,idと影のIDが一致してたらparent,id
一致してなければ0になる

ちゃんとは見てないけど、この演算結果が使いまわされてるっぽい

このへんが、parentvarsetのステコン固有処理の入り口で

0047106E |> 8BAC24 A010000>MOV EBP,DWORD PTR SS:[ESP+10A0] ; Case 130 of switch 0046E830
00471075 |. 837D 1C 01 CMP DWORD PTR SS:[EBP+1C],1
00471079 |. 0F85 01050000 JNZ winmugen.00471580
0047107F |. 85DB TEST EBX,EBX
00471081 |. 75 1B JNZ SHORT winmugen.0047109E
00471083 |. 68 74C24A00 PUSH winmugen.004AC274 ; ASCII "no parent for parentvarset"
00471088 |. 55 PUSH EBP
00471089 |. E8 6245FAFF CALL winmugen.004155F0



0047106E |> 8BAC24 A010000>MOV EBP,DWORD PTR SS:[ESP+10A0] ; Case 130 of switch 0046E830
00471075 |. 837D 1C 01 CMP DWORD PTR SS:[EBP+1C],1

ここでishelperが1か否かを見てて


0047107F |. 85DB TEST EBX,EBX

ここでさっきの演算結果が0か否かを見てる
ここで0に流れるってことはヘルパーだけど親がいない
つまり、parentvarsetの相手がいない警告を出す対象で


00471083 |. 68 74C24A00 PUSH winmugen.004AC274 ; ASCII "no parent for parentvarset"
00471088 |. 55 PUSH EBP
00471089 |. E8 6245FAFF CALL winmugen.004155F0

これで警告出してる

常時監視ステートの処理とかステート移動でのループとかの制御は004414EEのあたり
常時監視ステートは0047F7D0、個別ステートは047F3E0で処理してる
どっちも上の処理は呼び出してるから、何かしらのステート処理開始時には呼ばれる
詳しい実行条件まで見てないから、無理やり何とかすればスキップできるのかもしれんが、そこまでは知らん

リダイレクト

http://samsara01.blog.fc2.com/blog-entry-18339.html
捏造なりでparent弄ったとして、parent,IDやらがいつ反映されるかってーと
書いた通り即時

たしか自キャラver1.19のヘルパー親捏造はparent,IDでいつものとこのアドレス取ってた気がする

で、こっちで書きたいのは↓の話、つまりソフトウェアの設計の話や
実装の都合から察するに、ほとんどのトリガーが勝手に反映されるはず

実装上の都合とザックリ書いたけど、拡張性とか使いやすさやね

get_trigger(const void* ch_addr,uint32_t trigger_id,const vod* data)
get_trigger(const void* ch_addr,uint32_t trigger_id,...)
みたいな感じかなーとは察してる
であとは各トリガー用に
get_ID(const void* ch_addr)
とか、第2引数以降はトリガー次第
戻り値は考慮してない、受け取る用の引数がもう一個あるか、ポインタ返すんじゃね?

以降、そこら辺の話を適当に

IDを取得するという関数を実装する場合
ダメなのはプレイヤーそれぞれにAPIを用意する、ID_P1、ID_P2~ID_Pxxって感じで
※常にダメなわけではない、MUGENのトリガーだとP1Name、P2Nameあたりは問題ない

なんでだめって、単純に全プレイヤー分書くのはあほらしい
それとヘルパーの数が可変だからダメ
winはヘルパー数の上限あるけど、新は上限廃止するとかいう話もある
上限1000になったら、1000個用意するのかと

じゃー、こいつのID欲しいってときの「こいつ」の情報も一緒に渡せば、
関数1つで事足りるんじゃね?ってなるそれが
get_ID(const void* ch_addr)
中身はアドレスからIDの場所計算してその値をとってくるだけ
これを上述のget_triggerみたいな関数でラップしてる

引数はアドレスじゃなくて管理用の番号のほうが良いとかそういうのは
プレイヤーが増えたらどうするんだとか、アドレス自体がすでにユニークなIDなのにまたID振るの?とか
同一アドレスで別キャラが仕様変更であり得るかもとか、面倒なので割愛
実際のとこ、アドレス引っ張ってくるときは番号から計算してたりする

で、リダイレクトの話で
これも関数的にはトリガーと変わらんはず
get_parent(const void* addr)とかあって、
自身のアドレス渡して、これ呼べば親のアドレス(parentに入っている値)がとれる
あとは、その親の値でget_ID呼べば、勝手に計算してやってくれる

ここの引数がIDだったらどうなってたかはわからん
そもそもparentがなくなって、所謂影のIDだけでの管理になってたかもだし
そうなったら、今の親捏造ほど自由度高くないね

と、いうわけで使いやすさとか拡張性考えたらそうなるよね


こういう話って要はオブジェクト指向とか仮想化の話なわけで、結構面白い
C++とかのクラスはどういう実装になっているのか、動的多態性はどう実現しているのかとか
OSだとHAL層とかVFS層みたいな仮想化層の話とか
自分が割と関わる範囲に絞っても、いくらでもネタを出せる話題

凍結

FC2ではいつものことやろ?

体を張って笑いを取るSAM氏ほんとすこ

SAM氏のブログが

凍結されてるwwwwwwwwwwwww
プロフィール

Author:drab
霊夢改変キャラ
「12 3 ! {V} [_]」
公開中
L霊夢でもl_reimuでも好きなように読んでください

最新記事
最新コメント
月別アーカイブ
カテゴリ
検索フォーム
RSSリンクの表示
リンク