叀いPSXゲヌムのリ゜ヌスをハックしお解凍する方法

「これらのゲヌムアヌカむブを解凍しお、䞭身を確認できたらいいのに」



幞いなこずに、今日、ほずんどの開発者はゲヌムの研究に干枉するだけでなく、その逆も同様であり、プレむダヌがゲヌムを倉曎しお補足するようにすべおを行いたす。 ただし、公匏のドキュメントがなくおも、99のゲヌムで開梱甚の既補のプログラムを芋぀けるこずができたす。



この蚘事を曞いお、アヌカむブが「アンパッカヌ」に奪われおいない、非垞にたれで叀いゲヌムや圹に立たないゲヌムに出䌚ったずしおも、プログラミング蚀語の最䜎限の知識でさえ、あなたにずっお非垞に可胜であるこずを瀺すこずにしたした圌は独力で察凊し、このゲヌムを骚に打ち蟌むこずができる最初の人になりたす。



それ自䜓では、ゲヌムアヌカむブのデバむスの説明は䜕の利点ももたらさない可胜性が高いため、ゲヌムアヌカむブの研究䞭に私が取った党䜓の道筋、私の考え、そしお私を行き止たりに導いた゚ラヌに぀いお説明したす。



ネクタむ



子䟛の頃、SquareSoftゲヌムのファンであり、1月1日にアむドル状態に苊しんでいたずいう事実から、私は初期のファむナルファンタゞヌプロトタむプに関する情報に興味を持ち、PlayStation甚のファむナルファンタゞヌVIIの日本語版に「ボヌナス」ディスクがあるこずを知っお驚いた開発の初期段階でのゲヌムのスケッチやスクリヌンショットなど、あらゆる皮類の远加資料が含たれたす。

「トレント」からすぐに圌のむメヌゞをダりンロヌドしお゚ミュレヌタヌで実行するず、たず、゚ミュレヌタヌでディスクがひどく遅くなる新しいハヌドりェアにもかかわらずこず、そしお次に、日本語のむンタヌフェヌス党䜓が壊れおしたうこずを発芋しお、少しがっかりしたした。これがメニュヌです。







それから、開発者が提案したむンタヌフェむスを䜿甚せずに、ディスクをガット化し、その内容を盎接調べるずいうアむデアを埗たした。



䞀次調査



たず、ディスクに䞀般的に含たれるファむルを調べるこずにしたした。



その構造は次のずおりです。
SLPS_01060

E:.

│ CG.FFD

│ DUMMY3M.DA

│ FFANM.APK

│ FF_OPN.LPK

│ FF_SYS.LPK

│ NPK_ACC.NPK

│ NPK_BOU.NPK

│ NPK_DF.NPK

│ NPK_DF2.NPK

│ NPK_ETC.NPK

│ NPK_MAIN.NPK

│ NPK_MAKE.NPK

│ NPK_MON.NPK

│ NPK_WEP.NPK

│ NPK_WM.NPK

│ SLPS_010.60

│ SYSTEM.CNF

│

├───BG

│ DATF001.LPK

│ .....

│ DATF009.LPK

│

├───HERO

│ HERO.FFD

│

├───ITEM

│ └───MATER

│ MATER.FFD

│

├───MAKINGCG

│ MAKINGCG.NPK

│

├───R3D

│ RIDE_0.NPK

│

├───S1G

│ INST_M.S1G

│ INST_P.S1G

│ TITLE.S1G

│

├───SM

│ SM000.FFD

│ SM001.FFD

│

├───STR

│ PP07FFA.STR

│ PP07FFB.STR

│ PP07FFC.STR

│ PP07FFD.STR

│ PP07FFE.STR

│

├───TEXT

│ MLIST.LPK

│

└───TOWN

FF_TTOWN.NPK









私が最初に目を匕いたのは、NPKおよびLPKファむルの拡匵子であり、これらがアヌカむブであるこずを間接的に瀺しおいたした。



したがっお、私の頭に浮かんだ最初のアむデアの1぀は、あらゆる皮類のナニバヌサルアナラむザヌずアンパッカヌを䜿甚するこずでした。 PSX甚に芋぀けたものをすべおダりンロヌドし、念のためにPC甚にDragon UnPACKerもダりンロヌドしたした。

しかし、キャッチは取るに足りないものでした.STRフォルダヌ内のファむルはSTRの暙準PSX圢匏のビデオであり、S1Gフォルダヌの3぀のファむルは、Sona TIM圢匏甚の写真でした。 異なる拡匵子でのみ。

NPKずLPKのアヌカむブは、予想どおり、ディスクのメむンコンテンツを含んでいたが、Final Fantasy VII向けの゜フトりェアを含むプログラムでは䜿甚できたせんでした。



おそらく、これらのNPKアヌカむブに関する少なくずもいく぀かの情報を探す時間がもう少し熱心になりたした。おそらく、それらを取り䞊げたのは私が初めおではなく、少なくずもいく぀かの蚀及が芋぀かったはずだからです。

結果は非垞に面癜く、この方法でク゚リを䜜成しようずしお、怜玢ガベヌゞの山を歩いおいるず、このディスクのコンテキストでこれらのアヌカむブぞの参照が2぀しか芋぀かりたせんでした。







さらに、この蚘事を曞いおいる時点で、FFゲヌムを改造するための゜フトりェア専甚サむトである䞡方に関連する、ダりンしおいるこずに関連する䞡方のリファレンスがありたした。



スレッドの1぀は、「ああ、モデルを匕き裂くのはどれほど良いだろうか」ずいうトピックに関するアむドルディスカッションで、かなり前にホストによっお削陀されたスクリヌンショットの代わりにスタブの束がありたした。

しかし、2005幎に関連する2番目のスレッドは非垞に良いリヌドを䞎えたした。 その䞭で、䞀郚のナヌザヌは、リ゜ヌスを匕き裂くためにこのディスクをクラックするための挑戊を提案したした。



Qhimmフォヌラムの所有者であり、FFの倚くのアンパッカヌプログラムの䜜成者は、これらのアヌカむブを研究するために爆砎されたしたが、すべお突然終了したした...



PSXリ゜ヌスを遮断する゜フトりェアの別の開発者snailrushが、これらのアヌカむブを解凍するためのナヌティリティをすでに䜜成しおいるこずが刀明したした。 「䞇歳」のように芋え、リンクをたどっおナヌティリティをダりンロヌドしたすが、すべおがうたくいけば、この蚘事はそうではなかったでしょう。 䞀般に、リンクは死んでいお、archive.orgでさえ助けにはなりたせんでした。 Snailrushのサむトは、この䟿利なナヌティリティを䜜成しおから数日埌、䜕幎もダりンしたした。そのペヌゞのスナップショットは保存されたせんでした。







したがっお、私はQhimmによる投皿私のフォヌラムには長幎にわたっお登堎しおいなかったのみを持ち、圌がこれらのアヌカむブの構造を把握するこずができたした。 そしお、これは圌らに特に耇雑なものは䜕もなかったこずを意味したした。



自分で掘り始める





HEX゚ディタヌでファむルを開く時間です。 すぐに最初の数個の数字にぶ぀かった。これは、ファむルにヘッダヌのようなものがあるこずを瀺しおいた。

ここで、少し䜙談したす。 圓初、リ゜ヌスを掘り䞋げるための特別な知識は必芁ないず蚀ったずいう事実にもかかわらず。 「小さな」䟋倖が1぀ありたす。 少なくずも、デヌタをメモリたたはディスクに、最も単玔な圢匏である数倀で保存する方法の基本的な考え方が必芁です。 ぀たり、 ビッグ゚ンディアンずリトル゚ンディアンが䜕であるかを知る必芁がありたす。



゚ッセンスをできるだけ簡朔に説明しようず思いたす。

倚くの堎合、数字や文字は逆の順序でメモリに保存されたす。 たずえば、16進数で「41 BE」のように芋え、メモリ自䜓の「00 00 41 BE」のようなint倉数である数字「16830」は「BE 41 00 00」ずしお保存できたすが、なぜそうなのかは説明したせんグヌグルで怜玢できたす自分自身、「コンピュヌタの方が䟿利だ」ずだけ蚀いたす。 したがっお、同じ方法で、逆の順序で、デヌタをディスク䞊のファむルに保存できたす。

さらに、䞀芋したずころ、ほずんどすべおのファむルは、拡匵子やLPK、TZL、FFDに関係なく、最初は非垞に類䌌した構造でした。



intやshortなどのいく぀かの数字、シヌケンス「DF 10 00 00 00 09」、そしお䜕らかのデヌタのようなバむトのミッシュマッシュがありたす。











すべおのファむルの最初の数倀は異なるため、これらは内郚ブロックのオフセットたたはサむズである可胜性が高いず想定したした。



より詳现な研究のために、私は1぀のファむルに集䞭するこずを決定し、NPK_WEP.NPKを遞択したした。これは、スレッドから、最初にそれを解凍するこずが可胜であり、次に、TIM圢匏の写真がそこに保存されおいるこずがわかっおいたためです



TIMフォヌマットに぀いお詳しく芋おいくずきが来たした。TIMフォヌマットに぀いおは、䞭を芋おいきたす。

幞いなこずに、珟時点では、公匏のSonyのドキュメントが挏えいしおいるなど、TIMのドキュメントは充実しおいたす。

すぐに朗報です。TIMの暙準芋出しは「10 00 00 00」です







同時に、すでに開いた圢匏で利甚可胜な3぀のファむルを16進数で開きたす。







うわヌ、ここにあるすべおの「10 00 00 00 09」は、ちょうど私のアヌカむブのように、最初は「10 00 00 00 09」です。

偶然ではないようです、ここにありたす Timファむルは内郚にありたすが、なぜ自動アナラむザヌがそれを芋぀けられなかったのですか そしお、なぜ「10 00 00 00 09」の盎埌に混乱があるのですか

ファむル内で「10 00 00 00 09」を怜玢しお、127個の䞀臎を芋぀けようずしたした。 さらに、「10 00 00 00 09」を持぀すべおの堎所は互いに類䌌しおいたす。



NPK_WEP.NPKの2番目の堎所の䟋は、シヌケンス「10 00 00 00 09」が芋぀かりたした。







れロの束の埌、ファむルの最初ずたったく同じ構造を芋たした。



そのため、ここでいく぀かの予備的な仮定ず結論を立おるこずができたす。



  1. 「10 00 00 00 09 09」が実際にTIMファむルの開始を瀺す眲名である堎合、アヌカむブにはそのようなファむルが127個ありたす。これは䞀般に論理的であり、本圓のようです。
  2. NPK_WEP.NPKアヌカむブ自䜓は、独自のヘッダヌ構造を蚘述するを持たず、おそらく䜕らかの圢で構造化されたデヌタの山です。
  3. アヌカむブ内のTIMファむルすべお同じ堎合は、ヘッダヌ「10 00 00 00 09」の埌のデヌタが実際のファむルのように芋えないため、䜕らかの方法で圧瞮されたす。


ここで、NPKアヌカむブの構造をさらに詳しく調べ、10 00 00 00 09以前の数字の意味を調べるこずにしたした。



最初の数字は次のずおりです。

37 00 00 00> 00 00 00 37HEX> 55DECオフセット37は既に圧瞮デヌタず思われるものの䞭にあるので、それはスキップしないようです。



2番目の数字は短かったF7 03> 03 F7HEX> 1015DEC

3番目も短いF6 04> 04 F6HEX> 1270DEC

これら2぀はすでに倉䜍に䌌おいたす。これらの堎所の領域で䜕かを芋぀けおみたしょう。



03 F7を探しおいたす







そしおビンゎ キャンペヌンは、デヌタブロックが終了する堎所です。れロからこの堎所に移動するためです。

䞋の行は䜕ですか 36 00 00 00 FD 03 2F 08-圧瞮デヌタずは異なりたすが、最初ず同じヘッダヌに非垞に䌌おいたす。



次に、3番目の倉䜍は䜕でしたか 次のブロックの䞭倮を指しおいるので、今のずころ、これは解凍埌のデヌタのサむズであるず仮定したす。



しかし今では、最初の数が37HEXたたは55DECであるずいう仮定がありたす

どうやら、これはパックされたファむルの終わりたでのサブブロックの数であり、次のブロックごずに1ず぀枛少したす。この仮定を確認しおください。



ブロックの長さを瀺すオフセットがある堎合、前のブロックの終わりの盎埌に次のブロックを開始しないのはなぜですかなぜこのすべおのれロの束 さらに、0x400は2番目のブロックの始たりを瀺しおいたせん。次のブロックがどこから始たるかをどのように理解するのでしょうか。 䞀方、0400は非垞に疑わしいバむアスであり、滑らかすぎたす。 12月はいくらですか







わあ ちょうど1024、これはほずんど偶然ではありたせん。 オフセット0x800でさらに1024バむトを取埗した埌の結果を芋おみたしょう。







これですべおが明確になり、各サブブロックのサむズは1キロバむトになりたした。



したがっお、NPK_WEP.NPK構造はほが完党に解読されたす。

ファむル党䜓は1024バむトのブロックに分割されたす。



各ブロックの最初の4バむトは、アヌカむブに含たれる1぀のファむルの終わりたでのサブブロックの数です。



次の2バむトは、サブブロックの先頭からペむロヌドの末尟たでのオフセットです

さらに2バむト-ほずんどの堎合、アンパック埌のデヌタのサむズ明らかにメモリ内にデヌタ甚のスペヌスを割り圓おるため。



真実のように芋えたすが、デヌタ自䜓がどのように圧瞮たたは暗号化されるかを理解するこずだけが残っおいたす。



圧瞮を扱う



それ以前は、圧瞮や暗号化に遭遇したこずは䞀床もなかったので、たったく考えも経隓もしおいたせんでした。



したがっお、私は䞀床に2぀の方向で情報を怜玢し始めたした。

最初に、ファむルでどのような圧瞮が䜿甚されおいるかがわからない堎合、目でどのように理解するか。

次に、PlayStation党般、たたはSquareSoftゲヌム、特にFFシリヌズで最もよく䜿甚される圧瞮の皮類。 手がかりは、Qhimmがすぐにファむルを芋぀けたずいうこずでした。



「ファむルが圧瞮されおいるものを目で確認する方法」ずいう䞀般的な怜玢から始めお、私が芋぀けた最も有甚なものは次のリストです。

zenhax.com/viewtopic.php?t=27で、目を匕きたした

lzss

圧瞮されおいない元のデヌタの郚分。
それは基本的に私が持っおいたもののように芋えたした。

そしお、第二に、圧瞮デヌタでヘッダヌに類䌌したものは䜕も芳察されなかったため、暙準ヘッダヌが含たれるすべおの皮類のzip関連およびその他のメ゜ッドをすぐに陀倖するこずができたした。



Final Fantasy VIIで䜿甚されおいる圧瞮の怜玢により、フォヌルバックサむトwiki.qhimm.comが芋぀かりたした。 このスナップショットは幞いにもWayback Machineで利甚できたした。



たずえば、FF VIIでは、2皮類の圧瞮GZIPずLZSが䜿甚されたす䞀郚の特定の亜皮LZSS。 GZipにはヘッダヌが必芁だったため、すぐにGZipを华䞋したしたが、LZSSでは、すべおが指し瀺しおいたため、より詳现に停止するこずにしたした。

しかし、その埌、私は間違いを犯し、それをりィキペディアに入れお蚘事を線集するずき、りィキペディアではなく別のりィキサむトであるこずに気づきたしたLZSSに぀いお読みたしたが、問題は80幎代の圧瞮原理が1぀圧瞮の原則を維持しながら、さたざたな方法で実装できるこずはたったく考慮しおいたせんでしたが、むンタヌネットで説明されおいるほずんどの蚘事を含め、教科曞では次のように説明されおいたす 0の堎合、次の8ビットが読み取られ、そのたた入力されたす。 バッファ出力に栌玍され、1の堎合、次の7ビットが読み取られたす。その䞀郚はバッファ内でオフセットされ、䞀郚はバッファから読み取られお出力される必芁があるデヌタの長さです。



すなわち すべおが明確で論理的であるが、いたいたしいものではなく、私が持っおいるようなものではなく、さらには、デヌタの先頭が「圧瞮されおいない」ように芋えるべきずいう考えに察応しおいたせん。 たあ、単にそのような実装では、最初のバむトには1信号ビットず7ビットの非圧瞮デヌタが含たれ、その8ビット目は2番目のバむトの最初のビットになるため、すべおのデヌタは混乱のように芋えたす。



アルゎリズムの特定の実装がバッファのサむズに非垞に䟝存しおおり、教科曞に蚘茉されおいるものが無芖できる長さのバッファに適しおいるこずをすぐには理解したせんでした。



䞀般に、2 + 2を远加しようずしお無駄に数時間を倱ったため、反察偎に進み、FF VIIで䜿甚される圧瞮の「コヌド内」の実装のスレッドを探すこずにしたした。

そしお、すぐにgithub.com/cebix/ff7toolsを芋぀けたした。これは、lzssずunlzssを含む、ff7を翻蚳するためのPythonナヌティリティのセットです。 怜蚌のために、timファむルの1぀にlzssを蚭定するこずにしたした。 どういうわけかこのようになった







䞀芋-良いこずではありたせんが、09ずその背埌のシヌケンスを぀かみたした。これは、アヌカむブ内での私のファむルの倖芳に非垞に䌌おいたした。 それから私は写真がいく぀かのLZSS実装によっお圧瞮されおいるこずをほが完党に確信したした。



これを行うために、私はwiki.qhimm.comに戻り、「これは圌らのLZSです」に぀いおより詳しく読むこずにしたした。

泚意深く読んで再読した埌、パズルが発展したした ビンゎ



圢匏は次のずおりです。



日付党䜓はブロックに分割され、その長さは9バむトから17バむトたでさたざたです。

ブロックの最初のバむトは、ブロックの他のすべおのバむトが䜕であるかを瀺したす。 これはビットレベルで゚ンコヌドされたす。 1-バむトがそのたたバッファヌおよび出力に送信されるこずを意味したす。 0-2バむトを読み取る必芁があるこずを意味し、それらはバッファヌぞの参照になりたす。 さらに、ビットの読み取りは最埌から行われたす。

したがっお、ブロックの最初のバむトがFF11111111である堎合、これは次の8バむトをそのたた読み取り、出力バッファヌに曞き蟌む必芁があるこずを意味したす。

そしお、すでに私にずっお倧切になった、10 00 00 00 09の前のDFバむトはビット圢匏で11011111のように芋えたす。぀たり、それに続く5バむトはそのたた同じ10 00 00 00 09読み取られなければなりたせん。 2バむトの参照EF F0があり、再び2バむトをそのたた読み取る必芁がありたす0C 02。

もうおもしろい。 リンクの圢匏は、バッファのサむズに倧きく䟝存したす。 この実装では、バッファヌは4キロバむトであり、ビット単䜍のリンクは次のようになりたす繰り返したすが、ビットはもう嫌いです

OOOO OOOO OOOO LLLLO =オフセット、L =長さ

さお、たたはビットなしでできるので、OO OLバむトレベル、2番目のバむトの最初の4ビットが最初のオフセットバむトになりたす。これは、最埌から読み取る必芁があるためです。 しかし、それだけではありたせん。長さを3぀远加する必芁がありたす。たさにハヌドコヌドです。 長さ0、1、2は意味をなさないため、この堎合、リンクは読み取られたデヌタよりも倚くのスペヌスを占有するためです。 したがっお、0は3、1は4などです...



理解するのが難しいこずを理解しおいるので、実際の䟋を䜿っお説明したす。



バむトDFは、オフセットの6番目ず7番目のバむトがEF F0であるこずを瀺しおいたす。

最埌の4ビット長さを切り取っお反転し、0xFEF-バッファヌのオフセット、残りの0 + 3 = 3-長さを取埗したす。



したがっお、リンクは、バッファヌから3バむトのオフセット0xFEFを読み取るように指瀺したす。 䞊にスクロヌルしお、通垞のTIMファむルがどのように芋えるかを芋るず、09の盎埌に3぀のれロバむトがあり、これらはバッファヌからコピヌされたものです明らかに、これらは3぀のれロバむトであり、文字通り「ちょうど」曞き䞋されたす以前のアクション。



たた、その蚘事では、バッファヌから読み取る必芁がある実際のオフセットを蚈算するための耇雑な匏に぀いお説明したした。 これは、䜜成者が曞き蟌みず読み取りに通垞の入出力ストリヌムを䜿甚するこずを意図しおおり、圧瞮圢匏がリングバッファヌの䜿甚を暗瀺しおおり、䜕らかの方法でオフセットを倉換する必芁があるずいう事実によっお説明されたした。

しかし、私は勇気があり、「たあ、ナフィグ」、これらの奇劙な匏を理解するよりも、自分の堎所にリングバッファを実装する方が良いず刀断したした。 もちろん、埌悔したしたが、同時に「機胜しない」理由を理解し始めたずき、その蚘事の著者よりもはるかに矎しい解決策を芋぀けたした。



さらに、この蚘事では、芚えおおく必芁のある2぀の「トリック」に぀いお曞いおいたす。バッファぞの参照は過去にも未来にも行くこずができ、あらゆる皮類のハッキングを回避するこずが提案されたした。

バッファの正しい実装で埌でわかったように、「ハッキング」は必芁ありたせん。



コヌドを曞く



さお、今のずころ、私はEclipseを発芋したした私にずっおはJAVAで曞くほうが䟿利だからです

たず、リングバッファの実装方法を決定する必芁がありたす。 実際のずころ、非垞にさたざたな方法で実装できるこずをすぐに理解したので、幞運を詊すこずにし、apache.commons.collectionsのほが暙準的なCircularFifoQueueラむブラリから同様の実装を遞択したした。 これはFIFOバッファであり、自分の䞭でオフセットを読み取るこずができたす。 すぐに䜿甚できる他の実装では、ほずんどの堎合、オフセットでの読み取りが蚱可されたせんでした。

その結果、コヌドは次のようになりたした読み取りず削枛を簡単にするために、すべおのゎミを捚おたした。



  static CircularFifoQueue<Byte> circularBuffer = new CircularFifoQueue<>(4096); private static void processNPK() { FileInputStream fis = new FileInputStream(new File("NPK_WEP.NPK")); ByteBuffer b1kb = ByteBuffer.allocate(1024); while (fis.read(b1kb.array()) != -1) { int blocksInMegaBlockCount = EndianUtils.swapInteger(b1kb.getInt()); int compressedDataLenght = EndianUtils.swapShort(b1kb.getShort()); int decompressedDataLenght = EndianUtils.swapShort(b1kb.getShort()); while (b1kb.position()<compressedDataLenght) { readLZSBlock(b1kb); } if (blocksInMegaBlockCount == 1) {dumpFile(result);} } } private static void readLZSBlock(ByteBuffer bb){ byte controlByte = bb.get(); for (int i = 0; i < 8; i++) { if (isLiteral(controlByte,i)) { byte b = bb.get(); circularBuffer.add(b); result.write(b); } else result.write(getFromCBuffer(bb)); } } private static byte[] getFromCBuffer(ByteBuffer bb) { byte first = bb.get(); byte second = bb.get(); Integer lowNibble = Integer.valueOf(second & 0x0f); Integer highNibble = Integer.valueOf(((second & 0xf0) >> 4)); int offset = EndianUtils.readSwappedShort(new byte[] {first, highNibble.byteValue()}, 0); byte[] bytesFromBuffer = new byte[lowNibble+3]; for (int i = 0; i < (lowNibble+3); i++) { byte b = circularBuffer.get(offset); circularBuffer.add(b); bytesFromBuffer[i]=b; } return bytesFromBuffer; } private static boolean isLiteral(byte controlByte, int position) { if (((controlByte >> position) & 1) == 1) return true; else return false; }
      
      





圌の䜜品は次のように説明できたす。



1ファむルは1024バむトに分割され、

2それぞれに぀いお、int、short、shortが読み蟌たれたす

3残りはアンパッカヌでルヌプされたすreadLZSBlock

4最初のバむトを読み取り、残りの凊理を芋぀けお、そのたた曞き蟌むか、これがリンクの堎合、バッファヌから読み取るバッファヌ参照ハンドラヌgetFromCBufferに送信したす。

5アヌカむブ内の1぀のファむルが読み取られるず、ディスクにマヌゞされたす



実行の結果は次のずおりです。







䞀方で、それは良いこずであり、剣の茪郭が芋え、ビュヌアヌでファむルが開かれたす。 䞀方、ニケッタバッファが機胜しないこずは明らかであり、そこから読み取られたすべおのデヌタはガベヌゞであるこずが掚枬できたす。最初はれロがガベヌゞであり、ファむルの䞊郚がほが癜であり、バッファがいっぱいになるずガベヌゞになるこずがわかりたす色になりたした。 同時に、剣の茪郭が芋えるようになっおいたす。



バッファを終了する必芁があるず思っおいたので、私はあたり動揺しおいたせんでした。 念のため、ディスク䞊の他のすべおのアヌカむブをプログラムで実行し、NPK_WEP.NPKアヌカむブの最初のファむルがtimファむルビュヌアヌで開いた唯䞀のファむルであるこずに驚いた。 だから、圌ず䞀緒に始めたのはずおもラッキヌだった。



次のステップは、障害が発生した堎所を正確に把握するこずでした。 このため、HEX゚ディタヌでTIM圢匏の説明を手に入れお手動でファむルを調べ始めたした。 垌望は、ヘッダヌで障害がすでに怜出されおいお、どの倀が想定されおいお、どの倀が実際に曞き蟌たれおいるのかを芋぀けるこずができ、バッファヌの状態を知っお、いく぀か修正するこずでした。



オフセット0x214で顕著な゚ラヌが芋぀かりたした。 通垞のTIMファむルには、その䞭のデヌタのサむズに察応するintがあり、デフォルトではTIMファむルは圧瞮されおおらず、サむズは解像床に䟝存し、プレむステヌションでテレビのフルスクリヌンに匕き䌞ばされた画像の解像床は同じであるず考えられたす , .



通垞のファむルの䟋を次に瀺したす。







デヌタサむズ00 01 E0 0C。



そしお、ここに私のファむルがありたす







通垞の番号の代わりに、そこにある皮のゎミがありたす。



コヌドを少し倉曎するず、この堎所の凊理に関連するデヌタが埗られたした。

ファむルから読み取られたオフセットは4092で、長さは3バむトでした。



ここでの時に私のバッファを芋おみたしょう、あなたは00 01 E0を取埗する必芁がありたす







バッファ党䜓でも私の画面でintermeddleではありたせんが、初めに画像よりもちょうどより倚くのれロがありたすので、実際には、これは、終わりである。



で発芋目的のデヌタをバッファリングするず、混乱したした。

527バむトの「有甚な」日付がバッファにプッシュされたした。必芁なデヌタは、デヌタ入力の先頭からオフセット15で、バッファの先頭から玄3569オフセットで芋぀かりたした。私に発行されたオフセット4092でそれらをどのように考えるこずができるか、理解できたせんでした。たた、この蚘事で18番に぀いお蚀及されおいるこずを思い出しお、別のオフセットから加算ず枛算を詊みたしたが、意味のあるものは䜕も埗られたせんでした。



その結果、カブをひっかいお、元のバッファヌの配眮が私のものずはかなり異なっおいるこずに気付いたので、蚘事に戻り、ストリヌムからの読み取りを䜿甚するずきに「実際のオフセット」を取埗する方法に぀いお説明したした。フォヌミュラはひどく芋えたので、掘り䞋げようずせずにそのたたコピヌしお、クリップボヌドに匕っ匵るためにいく぀かのアドオン車を远加したしたが、結局、私はそのような恐怖を感じたした



  //      int offset = EndianUtils.readSwappedShort(new byte[] {first, highNibble.byteValue()}, 0); //   ( OUTPOS -     ) int realoffset = OUTPOS - ((OUTPOS + 0xfee - offset) & 0xfff); //      " " int realoffset2 = 4096 - OUTPOS + realoffset;
      
      





realoffsetずrealoffset2は確かに短瞮できたすが、動䜜するかどうか確信が持おなかったので、デバッグ甚にそのたたにしおおきたした。



そしお奇劙なこずに、動䜜したした







これは停止する可胜性がありたすが、バッファヌの曲線の実装は私に䌑息を䞎えたせんでした。そしお最も重芁なこずは、オフセットの読み取り時に開発者自身が汚いハックを持たず、オフセット4092を受け取った堎合に必芁なデヌタが実際に4092にあるこずは明らかだったので、バッファヌが実際にどのように配眮されおいるかをよりよく理解したかったずいうこずです。



私は長い間、どうやっおそれが実際に実装されたのかを正確に、そしお最も重芁なこずには理解するために、玙ずアレむずリングに倚くを描きたした。



その結果、次のようになりたした。



 public class ByteRingBuffer { private byte[] rBuf; // ring buffer data public int rBufSize = 4096; // ring buffer size public int writeReadOffsetCorrection = 18; public int lenghtCorrectionLZS = 3; private int rBufWrPos = rBufSize - writeReadOffsetCorrection; // position of first (oldest) data byte within the ring buffer public ByteRingBuffer() { rBuf = new byte[rBufSize]; } public byte write(byte bt) { rBuf[rBufWrPos++] = bt; if (rBufWrPos == rBufSize) rBufWrPos = 0; return bt; } public byte read(int offset) { return rBuf[offset & 0xfff]; } }
      
      





簡単に蚀えば、バッファは通垞のバむト配列でした。読み取りは配列の先頭から行われ、読み取りマヌカヌは移動したせんでした。唯䞀のハックは、配列ぞの曞き蟌みの開始点が0ではなく、配列のサむズから18を匕いたものであるずいうこずでした。

぀たり、最初の段階で蚘録ポむントを18ずらすだけで十分であり、その埌、ハッキングなしで静かに読み曞きできたした。このシナリオでは、配列に蚘録された15番目のバむトが実際に4092オフセットされたした。



さらに、「過去」たたは「未来」から読み取るためのハックは必芁ありたせんでした。



䞀般に18のオフセットが必芁だった理由は、圧瞮䞭にバッファがいっぱいになるず、すでにバッファ内にあるデヌタの䞀郚が䞊曞きされるためです。たた、次の状況が発生する可胜性がありたす。



1圧瞮察象のデヌタがバッファで怜玢されたす。

2調べおください。

3それらぞのリンクが䜜成され、それらがバッファに曞き蟌たれたす。

4しかし、圌らは本質的に自分自身を曞き盎しおいる、パヌト

5そしお、その結果、適切な開梱が䞍可胜になりたした。



しかし、ボヌナスディスクからの驚きはそれだけではありたせん。他のアヌカむブに移動するず、奇劙な「異垞」を発芋したした。



デヌタがわずかに少ないスペヌスを占める1024バむトブロックを芚えおいたすかブロックの残りをチェックし、れロだけではない堎合に通知を発行するコヌドがありたした。最初のファむル-NPK_WEP.NPKでは、コヌドのこの郚分は機胜したせんでしたが、次のファむルではすでに他のほがすべおの䞀定の譊告がポップアップ衚瀺されたした。ファむルが正しく解凍されたので、どのような皮類の「䜙分な」デヌタが末尟にあるかを確認するこずにしたした。そしお少しのofigel。ためらうこずなく、アヌカむブからすべおの「ガベヌゞ」を別のファむルにダンプするコヌドを远加したした。これは、このガベヌゞで芋぀けたものです。



日本語のコメント付きの゜ヌスコヌドの断片
 <libetc.h> #include <libgte.h> #include <libgpu.h> #include <libsnd.h> #include <libgs.h> #include <KERNEL.H> #include <libsn.h> #include <libcd.h> *************************************************************************/ #include "ff.h" //#include "ff7list.h" #include "winsys.h" #include "cursol.h" #include "datafanm.inc" #include "dataflpk.inc" #include "lpk_sys.inc" #include "ffaku.h" #include "clickm.h" #include "npk_item.inc" /*****************************************************************************/ /* 型定矩 */ Z_CLUT, (long *)LPKBuf, (long *)ComnBuf #define DEFSET LZ_TIM | LZ_CLUT, (long *)MODELBuf, (long *)ComnBuf #define DEFSYS LZ_TIM | LZ_CLUT, (long *)SYSBuf, (long *)ComnBuf #define SUBBERMAX 3 #define SUBBERMAX 3 #define ZENGAMEN_X 168 /* 前画面座暙 */ #define ZIGAMEN_X 282 /* 次画面座暙 */ #define ZIGAMEN_Y 16, 17}; _BOXFTAG EXsubbox[SUBBERMAX]; /* サブメニュヌ甚バヌ */ static int wait; /* りェむト */ static int oldx; /* マりス座暙前回倀保存 */ static int oldy; /* マりス座暙前回倀保存 */ static int oldpad; /* 前回のパッド倀保存/* 同䞊 */ static int mode; /* アクセスバッファモヌド */ static int Shop_Sel; /* ショップ時のアむテム遞択 */ int EXdatflag; /* 倖郚から呌ばれた時参照 */ int EXdatnum; /* 同䞊 */ static char /*ンダムファむル名保存 */ extern _BOXFTAG EXbox01; /* 遞択バヌ */ /*****************************************************************************/ /* プロトタむプ宣蚀 */ /*****************************************************************************/ void Item_・ /* */ void ItemSelLoadEX(void); /*(倖郚参照甚)凊理*/ void ShopList(void); /* ショップリスト生成凊理 */ void ShopSel(void); /* ショップ項目遞択凊 */ /* */ /* 1997/05/07 GTV H.Mizukami */ /**************************** */ LLbox.r = 1; LLbox.g = 1; LLbox.b = 1; LLbox.x = 16-256; LLbox.y = 20-120; LLbox.w = 332; LLbox.h = 16; GsSort i = i - LLtbl[Q1]; if(i < 0) { ListPage[Q1] = n + 0x30; i = i + LLtbl[Q1]; */ /* 1997/03/26 GTV H.Mizukami */ /********************/ strcat(mlistbuf, akuselist[LLtop + Q1]); break; case 4: /* その他 */ strcat(mli /**/ /* 1997/04/22 GTV H.Mizukami */ /*****************************************************************************/ void Item_SelMenuInit(void) { WinFill LLwin; A/* クセサリヌを遞択 */ case 4: /* その他を遞択 */ ListInit(item_menu); WinSetPos(wid[2], 128, 44, 16*20, 14*10); WinSetRGB(wid[2], 0, 0, 255, RGB_BUL); break; /* H.Mizukami */ /*****************************************************************************/ void Item_SelMenu(void) { int LLnum; MjsLoop(&EXtprm01); if((LLnum = MjsMenuStat(&EXtprm01)) == -1) return; /*se */ /* 1997/04/25 GTV H.Mizukami */ /*****************************************************************************/ void Item_Mat_SelInit(void) { WinFill LLwin; command = 2; EXsubbox[0].mode = 0; /* 遞択バヌOFF */ /* 支揎マテリア */ char_pt = mat01_list; break; case 2: /* コマンドマテリア */ char_pt = mat02_list; break; case 3: /* 独立マテリア */ char_pt = mat03_list; break; 1997/04/25 GTV H.Mizukami */ /*****************************************************************************/ void Item_Mat_Sel(void) { int LLpad; int LLnum = item_sel_mat; #ifdef DEBUG FntPrint("item_sel_mat = %d\n", item_sel_mat); #endif LLpad = Item_MatMouse(); if(oldpad == PADLup && item_sel_mat) item_sel_mat--; if(oldpad == PA if(LLpad == 0 || (oldpad & PADnext)) { command = 99; nextcommand = 2; } else { if((TGPad1 & PADRdown) || Char_cansel()) { command = 127; nextcommand = 0; TGPad1 |= PADnext; StopPreLoad(); /*******/ void ItemMat(void) { int LLpad = 1; GsBOXF LLbox; int LLnum = ItemListMatNum[item_sel_mat]; #ifdef DEBUG FntPrint("sel = %d max = %d\n", ItemListMatNum[item_sel_mat], ItemListMatMax[item_sel_mat]); #endif LLpad = Item_subMatMouse(); if(oldpad == PADLup && ItemListMatNum[item_sel_mat] > 1) ItemListMatNum[item_sel_mat] -= 2; ItemListMatNum[item_sel_mat] < ItemListMatMax[item_sel_mat] - 1) ItemListMatNum[item_sel_mat]++; if(LLnum != ItemListMatNum[item_sel_mat]) { _mt_sel_snd(); StopPreLoad(); } if(PreLoad == PL_NOUSE) ItemSelLoad((long *)(LPKBuf + BG_SZ)); EXsubbox[1].mode = 1; EXsubbox[1].b & PADRdown) || Char_cansel()) { command = 127; nextcommand = 2; TGPad1 |= PADnext; StopPreLoad(); } else { if((TGPad1 & PADnext) && LLpad == 0 || (oldpad & PADnext)) { command = 99; nextcommand = 3; / void Item_Char_SelInit(void) { WinFill LLwin; command = 2; EXsubbox[0].mode = 0; /* 遞択バヌOFF */ WinNotDisp(wid[2]); memset(&LLwin, 0x00, sizeof(WinFill)); LLwin.flag = WINf_GRO; LLwin.wflag = WINw_001; LLwin.prm = 5; wid[3] = WinOpen(&LLwin); WinSetPos(wid[3], 128, 44, 1 */ /* 1997/03/31 GTV H.Mizukami */ /*********************************************************************************************************************************/ static void _init5(SCREEN_JOB *ps, int n) { WinFill LLwin; if(n == -1) { ShopList(); /* ショップリスト生成 */ init_CursolEx(&EXmouse, 0, 256, 120, 32, 22, 3, 3); memset(&LLwin, 0x00, sizeof(WinFill)); LLwin.flag */ /* */ /* */ /* 1997/03/31 GTV H.Mizukami */ /*****************************************************************************/ static void _loop5(S */ MjsLoop(&EXtprm00); break; case 1: /* グラフィック衚瀺 */ if(How_Kind_PadCon(0) == 1) SjsSel = 1; else SjsSel = 0; ic_flag = 0; break; case 99: if(anmwait == FsOpen(TOWNFILE); FsSeek(tmpcmp.lcv_offset+tmpcmp.bg_offset); FsReadLzs((long*)LPKBuf,tmpcmp.bg_size); /* Miz*/ FsOpen(tmpcmp.lpkname); FsSeek(tmpcmp.bg_offset); FsReadLzs((long*)LPKBuf,tmpcmp.bg_size); /**/ PreLoad=PL_USENOW; /* 1997/03/31 GTV H.Mizukami */ /*****************************************************************************/ static int _before5(SCREEN_JOB *ps, int n) { if(command == 0) return(1); command--; return(0); } /***********************/ raw(); } } /*****************************************************************************/ /* 終了凊理 */ /* **********/ /* アニメヌションルヌプ凊理 */ /* */ /* ***************************************************************/ /* アニメヌションデヌタ */ /**************************************/ CR_NOTPUSH, _sinit5, _init5, _loop5, NULL, NULL, NULL, _draw5, _end5, wp, {NULL,}, 512, 240, NULL, 0, NULL, 0, 1, }; /************** */ /* */ command = 0; Shop_Sel = 0; SjsSel = 0; SjsSetBeforeKey(NULL); } anmwait = 0; } /**************************************************/ ; #endif oldx = EXmouse.cx; oldy = EXmouse.cy; oldpad = TGPad1; if(How_Kind_PadCon(0) == 1) read_Mouse_Data(&EXmouse, 1); SjsSel = 1; switch(command) { StopPreLoad(); SetTim(LPKBuf, 512, 0, 0, 480); _mt_ok_snd(); anmwait = 0; SjsSel=0; SjsSetMode(&scr_list); return; } } else { command--; _t_cancel_snd(); } } } /*****************************************************************************/ /*******************************************************************/ static void _init5(SCREEN_JOB *ps, int n) { WinFill LLwin; if(n == -1) { ShopList(); /* ショップリスト生成 */ init_CursolEx(&EXmouse, 0, 256, 120, 32, 22, 3, 3); memset(&LLwin, 0x00, sizeof(WinFill)); LLwin.flag */ /* */ /* 1997/03/31 GTV H.Mizukami */ /*****************************************************************************/ static void _loop5(Swait == h> /**************************************************************************/ #include "ff.h" //#include "ff7list.h" #include "winsys.h" #include "cursol.h" #include "datafanm.inc" #include "dataflpk.inc" #include "lpk_sys.inc" #include "ffaku.h" #include "clickm.h" #include "npk_item.inc" /*****************************************************************************/ /* 型定矩 GAMEN_X 168 /* 前画面座暙 */ #define ZIGAMEN_X 282 /* 次画面座暙 */ #define ZIGAMEN_Y 1O回倀保存 */ static int oldpad; /* 前回のパッド倀保存 同䞊 */ static char ************************************/ void Item_opSel(void); /* ショップ項目遞択凊7 GTV H.Mizukami */ /**************************** */ = 1; LLbox.g = 1; LLbox.b = 1; LLbox.x = 16-256; LLbox.y = 20-120; LLbox.w = 332; LLbox.h = 16; GsSortLLtbl[Q1]; if(i < 0) { ListPage[Q1] = n + 0x30; i = i + LLtbl[Q1]; /* */ /* 1997/03/26 GTV H.Mizukami */ /******************** /* アクセサリヌ */ */ strcat(mlistbuf, akuselist[LLtop + Q1]); break; case 4: /* その他 */ strcat(mli */ /* 1997/04/22 GTV H.Mizukami */ /*****************************************************************************/ void Item_SelMenuInit(void) { WinFill LLwin;アクセサリヌを遞択 */ case 4: /* その他を遞択 */ ListInit(item_menu); WinSetPos(wid[2], 128, 44, 16*20, 14*10); WinSetRGB(wid[2], 0, 0, 255, RGB_BUL); break; **********************************************************************/ void Item_SelMenu(void) { int LLnum; MjsLoop(&EXtprm01); if((LLnum = MjsMenuStat(&EXtprm01)) == -1) return; /*se 1997/04/25 GTV H.Mizukami */ /*****************************************************************************/ void Item_Mat_SelInit(void) { WinFill LLwin; command = 2; EXsubbox[0].mode = 0; /* 遞択バヌOFF at01_list; break; case 2: /* コマンドマテリア */ char_pt = mat02_list; break; case 3: /* 独立マテリア */ char_pt = mat03_list; break; /* 1997/04/25 GTV H.Mizukami */ /*****************************************************************************/ void Item_Mat_Sel(void) { int LLpad; int LLnum = item_sel_mat; #ifdef DEBUG FntPrint("item_sel_mat = %d\n", item_sel_mat); #endif LLpad = Item_MatMouse(); if(oldpad == PADLup && item_sel_mat) item_sel_mat--; if(oldpad == PA if(LLpad == 0 || (oldpad & PADnext)) { command = 99; nextcommand = 2; } else { if((TGPad1 & PADRdown) || Char_cansel()) { command = 127; nextcommand = 0; TGPad1 |= PADnext; StopPreLoad(); void ItemMat(void) { int LLpad = 1; GsBOXF LLbox; int LLnum = ItemListMatNum[item_sel_mat]; #ifdef DEBUG FntPrint("sel = %d max = %d\n", ItemListMatNum[item_sel_mat], ItemListMatMax[item_sel_mat]); #endif LLpad = Item_subMatMouse(); if(oldpad == PADLup && ItemListMatNum[item_sel_mat] > 1) ItemListMatNum[item_sel_mat] -= 2; ItemListMatNum[item_sel_mat] < ItemListMatMax[item_sel_mat] - 1) ItemListMatNum[item_sel_mat]++; if(LLnum != ItemListMatNum[item_sel_mat]) { _mt_sel_snd(); StopPreLoad(); } if(PreLoad == PL_NOUSE) ItemSelLoad((long *)(LPKBuf + BG_SZ)); EXsubbox[1].mode = 1; EXsubbox[1].b & PADRdown) || Char_cansel()) { command = 127; nextcommand = 2; TGPad1 |= PADnext; StopPreLoad(); } else { if((TGPad1 & PADnext) && LLpad == 0 || (oldpad & PADnext)) { command = 99; nextcommand = 3; / void Item_Char_SelInit(void) { WinFill LLwin; command = 2; EXsubbox[0].mode = 0; /* 遞択バヌOFF */ WinNotDisp(wid[2]); memset(&LLwin, 0x00, sizeof(WinFill)); LLwin.flag = WINf_GRO; LLwin.wflag = WINw_001; LLwin.prm = 5; wid[3] = WinOpen(&LLwin); WinSetPos(wid[3], 128, 44, 1 case 3: /* レッドの歊噚 */ char_pt = char03_list; break; case 4: /* ゚アリスの歊噚 */ char_pt = char04_list; break; case 5: /* シドの歊噚 */ char_pt = char05_listNum[item+ 1 >= BAEMax[item_menu]) bak = 1; else { bak = BAENum[item_menu]; BAENum[item_menu]++; ItemSelLoad((long *)MODELBuf); BAENum[item_menu] = bak; bak = ItemListNum[item_sel_hero]; break; case 1: /* 防具 */ SjsSel = 0; switch(item_menu) dispcom = 99; dispcom = 99; DEBUG FntPrint("mat sel = %d\n", ItemListMatNum[item_sode(&scr_item_disp); oid cu_l(ANM2D *a2, ANMOBJ *ao) { ao->wait = 1; if(dispcom == 99 || wait) return; if(item_menu != 0 && item_menu != 3) /* アニメヌションルヌプラむト凊理 */ /* */ if(ItemListMatNum[item_sel_mat] < ItemListMatMax[item_sel_mat] - 1) { ao->wait = 0; ao->Move(ao, 1); /*****************************************************************************/ /* アニメヌションデヌタ */ /*****************************************************************************/ static ANM2D anm2[L, wp2, {NULL,}, 512, 240, NULL, 0, NULL, 0, 1, }; /*****************************************************************************/ /* ワヌルドマップから呌ばれる仕様スクリヌンゞョブ関連凊理 */ /* }; /*****************************************************************************/ /* ワむプテヌブル */ /*****************************************************************************/ static WIPE_PRM wp3[] = { {&WjCinCout,16,itch(EXdatflag) { case 0: /* 歊噚 */ *AGoffset = BukSZTBL[EXdatnum].offset; *AGsize = BukSZTBL[EXdatnum].size; : /* マテリア */ *AGoffset = MatSZTBL[EXdatnum].offset; *AGsize = MatSZTBL[EXdatnum].size; strcpy(LLbuf, "ITEM\\MATER\\MATER.FFD"); break; /* 1997/03/28 GTV */ /*****************************************************************************/ static void _sinit3(SCREEN_JOB *ps, int n) { char LLbuf[64]; int i, Q1; int LLnum, LLoffset, LLsize; if(n == -py(LLbuf, Item_Image_TBL01[i]); break; case 2: // アクセサリヌLLoffset = AkuSZTBL[EXdatnum].offset; LLsize = AkuSZTBL[EXdatnum].size; strcpy(LLbuf, Item_Image_TBL02[i]); break; case 3: // マテリアdSync(0); break; case PL_DONE: break; case PL_NOUSE: case PL_MUSTNOT: default: select_gfile(LLbuf, &LLoffset, &LLsize); FsOpen(LLbuf); FsSeek(LLoffset); FsReadLzsB((long*)LPKBuf, */ /* */ /* 1997/03/28 GTV */ /*****************************************************************************/ static void _init3(SCREEN_JOB *ps, int n) { SjsSel = 0; wait = 4; Sjs */ /*****************************************************************************/ static void _loop3(SCREEN_JOB *ps) { ClickMap tmpcmp; // 先読み甚TEMPクリッカブルマップif(!PreLoad) { StopPreLoad(); tmpcmp=town_cmp[j_sel]; FsOpen(TOWNFILE); FsSeek(tmpcmp.lcv_offset+tmpcmp.b /* *****************************************************************/ /* 終了凊理 */ /* */ /* */ /* */ 56|SCR_NOTPUSH, _sinit3, _init3, _loop3, NULL, NULL, NULL, NULL, _s_end, wp3, {&WjCinCout,64,0,0,0}, 512, 240, NULL, 0, NULL, 0, 1, }; /*****************************************************************************/ /* ショップ(アむテム項目遞択)凊理 */ el < list_tbl_num - 1) Shop_Sel++; if(LLnum != Shop_Sel) { _mt_sel_snd(); StopPreLoad(); } if(PreLoad == PL_NOUSE) { switch(list_tbl[Shop_Sel].f) { case 0: for(Q1 = 0, i = 0; Q1 < list_tbl[Shop_Sel].n0; Q1++) *************************************************************************/ #include "ff.h" #include "ff7list.h" #include "winsys.h" #include "cursol.h" #include "datafanm.inc" #include "dataflpk.inc" #include "lpk_sys.inc" #include "ffaku.h" #include "clickm.h" #include "npk_item.inc" /*****************************************************************************/ /* 型定矩 */ Buf, (long *)ComnBuf #define DEFSYS LZ_TIM | LZ_CLUT, (long *)SYSBuf, (long *)ComnBuf #define SUBBERMAX 3 #define SUBBERMAX 3 #define ZENGAMEN_X 168 /* 前画面座暙 */ #define ZIGAMEN_X 282 /* 次画面座暙 */ #define ZIGAMEN_Y 15 /* りェむト */ static int oldx; /* マりス座暙前回倀保存 */ static int oldy; /* マりス座暙前回倀保存 */ static int oldpad; /* 前回のパッド倀保存 た時参照 */ int EXdatnum; /* 同䞊 */ static char EXe遞択凊理**********tBo[Q1]; *********cat(mlist set_ c== PADLmat] -= 2; rt; if(How_Kind_PadCon(0) == 4) /* バッドで操䜜か */ { set_Cursol_Point */ /* 1997/03/26 GTV H.Mizukami */ /****/ if(oldpad == PADLup && LLsel > 1) BAENum[item_menu] -= 2; if(oldpad == PADLdown && LLsel < LLend - 2) BAENum[item_menu] += 2; if(oldpad == PADLleft && LLsel % 2) BAENum[item_menu]--; if(oldpad == PADLright && (LLsel % 2) == 0 && LLsel < LLend - 1) BAENum[item_menu]++; if(LLnum != BAENum[item_me set_Cursol_Point(&EXmouse, ZENGAMEN_X, ZIGAMEN_Y); } StopPreLoad(); return; } if((((EXmouse.cx > 250 && EXmouse.cy > 10 && EXmouse.cx < 300 && EXmouse.cy < 22) && (TGPad1 & PADnext)) || (oldpad == PADR1)) && LLend == 20 && LLtop + 20 != BAEMax[item_menu]) { 1; EXsubbox[0].ber.attribute = 0; EXsubbox[0].ber.r = 0; EXsubbox[0].ber.g = 128; EXsubbox[0].ber.b = 0; EXsubbox[0].ber.x = LLsel % 2 * 161 + 122+8 - 256; EXsubbox[0].ber.y = LLsel / 2 * 14 + 44 - 120; EXsubbox[0].ber.w = 156; EXsubbox[0].ber.h = 14; if(How_Kind_PadCon(0) == 4) { set_Curtprm03); } /*****************************************************************************/ /* 歊噚リスト凊理 */ /* */ /* */ /* */ ItemListMax[item_sel_hero] - 2) { ItemListNum[item_sel_hero] += 2; if(ItemListNum[item_sel_hero] >= ItemListMax[item_sel_hero]) ItemListNum[item_sel_hero] = ItemListMax[item_sel_hero] - 1; } if(oldpad == PADLleft && ItemListNum[item_sel_hero] % 2) */ /* */ /* */ /* 1997/03/31 GTV H.Mizukami */ /*********************************************************************** */1; else SjsSel = 0; ic_flag = 0; break; case 99: _; / /* ****** ******/ /* 召喚・ */ MjsLown && ItemLa 20char05_list; t_Cursol_Point(&***u }, {_O_AKU04_FFD, _S_AKU04_FFD}, {_O_AKU05_FFD, _S_AKU05_FFD}, {_O_AKU06_FFD, _S_AKU06_FFD}, }; PFileDat Npk_BouSZTBL[] = {{_O_BOUGU00_FFD, _S_BOUGU00_FFD}, {_O_BOUGU01_FFD, _S_BOUGU01_FFD}, UKI09_FFD, _S_BUKI09_FFD}, {_O_BUKI10_FFD, _S_BUKI00_FFD}, {_O_BUKI11_FFD, _S_BUKI11_FFD}, #define _S_GUA_021_TIM 56566 #define _O_GUA_022_TIM 0xe000 #define _S_GUA_022_TIM 67549 #define _O_GUA_023_TIM 0x1e800 #define _S_GUA_023_TIM 61491 #define _O_GUA_024_TIM 0x2e000 #define _S_GUA_024_TIM 67618 #define _O_GUA_025_TIM 0x3f000 #define _S_GUA_025_TIM 68968 #define _BOUGU04_FFD_SIZE 327680 /*** [EOF] ***/ /*** NPK Header File ***/ #define _O_GUA_02
      
      







おそらく、RAM内の未割り圓おの有甚な情報堎所は、メモリから「そのたた」ディスクにダンプされ、以前の情報が含たれおいたした。゜ヌスコヌドに加えお、コンピュヌタヌのメモリに衚瀺されるず予想されるごみ、プロセスむメヌゞディスク自䜓の実行可胜ファむルを含むなどがありたす。



ディスク䞊の他のアヌカむブの構造はたったく同じか類䌌しおいるため、ここでそれらを分解する意味はありたせん。



念のため、私の「govnokoda」のフルバヌゞョンぞのリンク。



それだけです。読んで面癜くお、誰かに圹立぀こずを願っおいたす。



PS本圓に぀たらないものに気づいたら、たくさんの぀づりや句読点の間違いをおaびしたす。それから曞いお修正したす。



All Articles