ã¯ããã«
ClockTowerïŒæ¥æ¬ã§ã¯Clocktower-The First FearãšããŠç¥ãããŠããŸãïŒã¯ãã¹ãŒããŒä»»å€©å åãã«ãã¥ãŒãã³ãšã³ã¿ãŒãã€ã¡ã³ããæåã«ãªãªãŒã¹ããã²ãŒã ã§ãã
![](https://habrastorage.org/getpro/habr/post_images/1fd/36d/1d7/1fd36d1d72dbfc1aa7e60b637cd0a11d.jpg)
ããã¯ããã€ã³ãã¢ã³ãã¯ãªãã¯ã¢ããã³ãã£ãŒãžã£ã³ã«ã®ã²ãŒã ã®1ã€ã§ããããµãã€ãã«ãã©ãŒãžã£ã³ã«ã®åµèšè ã®1人ã«ããªã£ãŠããŸãã é°è¬ã¯ãã·ã§ã«ã¿ãŒã®ééåŸã®4人ã®å€å ãéžå® ã«è¡ãçããäžäººãã€åœŒããæ¶ãå§ãããšããããšã§ãã ãã¬ã€ã€ãŒã¯å€å ã®äžäººã§ãããžã§ããã¡ãŒãæäœããéãéãå人ãæ¢ããéžå® ã§äœãèµ·ãã£ãŠããã®ããèŠã€ããããšããŸãã
ã²ãŒã ã®é°å²æ°ã¯å³ããã家ã®äžã®åºæ¥äºã¯å¶ç¶ã«èµ·ãããŸãããæãããªçç±ããªãïŒèšãæããã°ã家ã¯éåã«æºã¡ãŠããŸãïŒãæã«ã¯äœããããªãã殺ãããšãã§ããŸããã¯ãªãããŒã®ãµã€ã³ãã¹ã家äžãè¿œããããŠããŸãïŒãã€ãªãã¶ãŒã3ãã¡ã·ã¹ã¯æåã®ãã®ãããªæåã§ã¯ãããŸããïŒïŒ
![](https://habrastorage.org/getpro/habr/post_images/9ef/f81/ba4/9eff81ba4f71635a7088b0d8a2c70f17.gif)
ã²ãŒã ã§ã¯ãè¿ éãªæèãå¿ èŠãšããå±éºãªç¶æ³ããã°ãã°çºçããå¯äžã®æãã¯çãæ®ããéããé ããããšã§ãããããããžã§ããã¡ãŒã®å¿ãä¿ã€ããšãéèŠã§ããããããªããšããžã§ããã¡ãŒã¯å¿èçºäœã§åããŠæ»ã¬ãããããŸããïŒã²ãŒã Illbleedã®ã¹ã¿ã€ã«ã§ïŒã
ãã®ã²ãŒã ã¯1994幎ã«SNESã§ãªãªãŒã¹ããã1997幎ã«PSXã§åŒ·åãããã³ã³ãã³ãã§åãªãªãŒã¹ãããWonderswanã³ã³ãœãŒã«ã§ãªãªãŒã¹ãããŸããïŒããããWonderswanãæ°ã«ãã人ã¯ããŸããã§ããïŒã
ã¯ããSNES ROMã«ã€ããŠã¯ãAeon Genesisãè±èªã®ç¿»èš³ããªãªãŒã¹ããŸããïŒããã ã£ãããã§ãïŒããSNESã®ããŒãžã§ã³ã¯PCã®ããŒãžã§ã³ãããå£ã£ãŠãããPCã®ããŒãžã§ã³ã®æ¹ãã¯ããã«åªãããµãŠã³ãã§ãããFMVã®çŽ¹ä»ãããªãªã©ããããŸãã ãããããããå€ãã®ã³ã³ãã³ããå«ãå¯äžã®ããŒãžã§ã³ã¯PSXããŒãžã§ã³ã§ãããããã«ã€ããŠã¯åŸã§èª¬æããŸãã
æåã«ãCDããã²ãŒã ããé¢ä¹³ãããŸãããã
ããŒã1-ç 究
次ã®ãããªã²ãŒã ãã©ã«ããŒããããŸãã
![](https://habrastorage.org/getpro/habr/post_images/242/bba/3f9/242bba3f947fdf040b3ab9c8bfe4acba.jpg)
BGãã©ã«ããŒãããããã®äžã«ã¯ãåå²åœ¢åŒã®éšå±ã®èæ¯ã«äŒŒããã®ããããããã«ä»éãã.MAPãã¡ã€ã«ããããŸãã
![](https://habrastorage.org/getpro/habr/post_images/a64/01a/017/a6401a017d73f7afb12e2f9f5d588172.jpg)
PTNãã¡ã€ã«ãšPYXãã¡ã€ã«ãå«ãDATAãã©ã«ããŒããããŸã...ãããäœãªã®ãããããŸãã...ã¬ãã«ç»é¢ãããžãã¯ãªã©ã«é¢é£ä»ããŠããã®ãããããŸããã
ãã€ã¢ãã°ã§äœ¿çšããã人ã ã®é¡ãæã€bmpãå«ãFACEãã©ã«ããŒããããŸãã
![](https://habrastorage.org/getpro/habr/post_images/422/a3a/2e2/422a3a2e2b47e8dbb774bcd1b5ec3120.jpg)
ãžã§ããã¡ãŒã䜿çšã§ããã¢ã€ãã ãå«ããã©ã«ããŒããããŸãã
![](https://habrastorage.org/getpro/habr/post_images/483/297/ae8/483297ae88fe04d0cbcd995f36394d53.jpg)
PATTERNãã©ã«ããŒã«ã¯ABMãã¡ã€ã«ãå«ãŸããŠããŸãã ã¹ãã©ã€ãã¢ãã¡ãŒã·ã§ã³ã«äœ¿çšããããšæããŸãããééã£ãŠããå¯èœæ§ããããŸãã
SCEãã©ã«ããŒã«ã¯ãCT.ADOãšCT.ADTã®2ã€ã®ãã¡ã€ã«ãå«ãŸããŠããŸãã ããããèæ ®ããŸã-ãããã¯ãã²ãŒã å šäœã§çºçããè«çã¢ã¯ã·ã§ã³ã¹ã¯ãªããã§ãããç¬èªã®ãã€ããªã¹ã¯ãªããèšèªã§èšè¿°ãããŠããŸã...ãããŠãã»ãšãã©ã®æéããããã«è²»ãããŸãã
SNDDATAãã©ã«ããŒã«ã¯ãé³æ¥œãšå¹æé³ã®MIDIãã¡ã€ã«ãšWAVãã¡ã€ã«ãå«ãŸããŠããŸãã
VISUALãã©ã«ããŒã«ã¯ããã¹ãŠã®é«è§£å床ã¬ã³ããªã³ã°ãã¡ãã¥ãŒãªãã·ã§ã³ãªã©ãå«ãŸããŠããŸãã BMP圢åŒã 玹ä»ãããªãããã«ä¿åãããŠããŸãã
![](https://habrastorage.org/getpro/habr/post_images/7dd/01e/0d8/7dd01e0d853793a2102137005cdd6f2e.jpg)
æåŸã«ãDATA.BINãã¡ã€ã«ããããŸãããããäœãããã®ããŸã ããããŸããã ããã«ãã²ãŒã ct32.exeã®å®è¡å¯èœãã¡ã€ã«ããããŸãã
CDãªãã§ã²ãŒã ãå®è¡ãããšã次ã®ã¡ãã»ãŒãžã衚瀺ãããŸãã
![](https://habrastorage.org/getpro/habr/post_images/3d1/568/05b/3d156805b7c39563d2734fa115c9b759.jpg)
ãããã¬ã§ã²ãŒã ãå®è¡ããŠããã®è¡ãèŠã€ããŸãã 圌女ã¯ãã²ãŒã ãã²ãŒã ããŒã¿ã®å Žæãç¥ããªãïŒã€ãŸããCDãæ¿å ¥ãããŠããªãïŒããšãå ±åããã ãã§ããããšãããããŸãã
ããŒã2-NoCDã®äœæ
IDAãèŠããšãRegQueryValueExã䜿çšãããŠããããšãããããŸããã€ãŸããã¬ãžã¹ããªå€ãèªã¿åãããŠããŸãã ã²ãŒã ã¯ããããäœãåŸãŸããïŒ
![](https://habrastorage.org/getpro/habr/post_images/61c/09d/81f/61c09d81f4de119ad6eb66c7898557eb.jpg)
ãŸã...ç§ã¯ãããçãã ãšæããŸãã
ãŸãåæ¢ããŸãã
äœãåå ã§ãããã確èªããŸããããã³ãŒãå ã§ãããããŒãã³ãŒãã£ã³ã°ã§ããŸãã
![](https://habrastorage.org/getpro/habr/post_images/7e3/141/a05/7e3141a05a17fd2fc3e8c21ea315b80f.jpg)
äœåãªäœæ¥ã¯ç¡é§ã§ã¯ãªãã£ãããã§ãïŒ ã²ãŒã ã¯NOREGåŒæ°ãæ¢ããŠããŸãã èŠã€ãããªãå Žåãã¬ãžã¹ããªå€ããã§ãã¯ããã¹ãã£ã³ãã¹ãããããŠã芪ãã£ã¬ã¯ããªã«ãããšæ³å®ããŠã²ãŒã ãèµ·åããŸãã ããã§ã¯ãç°¡åãªãããã圹ç«ã¡ãŸããããã«ãããã²ãŒã ã¯åžžã«NOREGåŒæ°ã§å§ãŸããšèããããã«ãªããŸãã ãããè¡ãã«ã¯ãjzã0xEBïŒãŸãã¯ç¡æ¡ä»¶ã®JMPïŒã«çœ®ãæããŸãã
å®è¡ããŠååŸïŒ
![](https://habrastorage.org/getpro/habr/post_images/12d/1be/f08/12d1bef0850fb15d739dfb75ed112f1a.jpg)
ã¯ãïŒ
ããŒã3-ã²ãŒã å ããã¹ãã®æ€çŽ¢
å°ãèããŠã¿ãŸããã-ãã¹ãŠã®ããã¹ããå®è¡å¯èœãã¡ã€ã«ã«ãããšæåŸ ã§ããŸããïŒ ããã¯å¯èœã§ããå€ãã®ã²ãŒã ã§èµ·ãããŸãã ãã€ããªãã¡ã€ã«ã«ã¯éçãªè¡ããããŸãïŒããšãã°ãCDããªãããšã§èŠã€ãã£ããšã©ãŒïŒããããã¹ãã¯ä»ã®å ŽæïŒããŒã¿ãã¡ã€ã«ã«ããã®ãããããŸããïŒã«é ãããŠãããšæããŠããŸãã èŠãŠã¿ãŸãããïŒ
![](https://habrastorage.org/getpro/habr/post_images/e12/538/bf2/e12538bf24b564b18706d399745a52b6.jpg)
SHIFT-JIS圢åŒïŒéåžžã«äžè¬çïŒã䜿çšããæ¥æ¬èªã®ããã¹ãã¯ãéåžž0x80-0x8Fã®ç¯å²ã®å¶åŸ¡æåã§å§ãŸããŸã...å®è¡å¯èœãã¡ã€ã«ã§é¡äŒŒãããã®ãæ¢ãããšããå§ããã®ãããã§ãããã
次ã«ããããã®è¡ãæ°ãããã¡ã€ã«ã«ã³ããŒããŠã¡ã¢åž³++ã§éããGoogle翻蚳ã«è²Œãä»ããŸãã
![](https://habrastorage.org/getpro/habr/post_images/082/be7/6cc/082be76ccc7ff5170d2a8c25aa5c4eb4.jpg)
ãã®ãããã²ãŒã ãã€ã¢ãã°ã§ã¯ãªããšã©ãŒã¡ãã»ãŒãžã«äŒŒãŠããŸãã ä»ã®ãã¡ã€ã«ãæ¢ãæéã§ãïŒ
![](https://habrastorage.org/getpro/habr/post_images/8fe/2d2/071/8fe2d207151af2a0223b568ca7b4952f.jpg)
ããŒããç解ã§ãã-PTNããã³PYXãã¡ã€ã«ã«ã¯ããã¹ãããããŸããã SCEãã©ã«ããŒã確èªããŸãããã
![](https://habrastorage.org/getpro/habr/post_images/514/88c/8ce/51488c8ce0f3bd513f66bd168719f2a9.jpg)
CT.ADTãã¡ã€ã«ã«ã¯4ãã€ãã®ãªãã»ãããå«ãŸããŠããããã§ãïŒãã¡ã€ã«ã®æåŸãŸã§ã¯0x100ãŸã§ã«ãŠã³ãããäžåºŠã«4ãã€ãïŒã
ããããCT.ADOãã¡ã€ã«ã§ã¯...
![](https://habrastorage.org/getpro/habr/post_images/cb1/cce/7d5/cb1cce7d561c0c0c5c4f54f9b6e5cbf0.jpg)
![](https://habrastorage.org/getpro/habr/post_images/cb3/f51/c6a/cb3f51c6a9f42de0b3896844d8bd9699.jpg)
ããã§ããã¡ã€ã«ãã¹ã«é¡äŒŒããASCIIæååã ãã§ãªããSHIFT-JIS圢åŒã®ããã¹ãæååãèŠã€ãããŸããã ãã®ãã¡ã€ã«å ã®ããŒã¿ã¯å¥åŠã«èŠããŸã...ãããããããç解ã§ãããã©ãããèŠãŠã¿ãŸãããã ãããã解æãããå Žåã¯ãããããå¿ èŠããããŸãã
ããŒã4-ADO / ADTã®è©³çŽ°
ADTãã©ã®ããã«æ©èœãããã«ã€ããŠã¯ãã§ã«å°ãããã£ãŠããã®ã§ãADOãã©ã®ããã«èŠããããèŠãŠã¿ãŸãããã
![](https://habrastorage.org/getpro/habr/post_images/a17/7e8/934/a177e8934112bf869860ad6af4f3250f.jpg)
æäžéšã§ããžãã¯ïŒADCãªããžã§ã¯ããã¡ã€ã«ïŒãéå§ãããããã0xFFã®æã256ãã€ãªãã»ãããããããŒã¿ãéå§ãããããã§ãã æ¬ç©ã®ã³ã³ãã¥ãŒã¿ãŒç§åŠè ã®ããã«èããæã§ãïŒ
ãããã®è¡ã¯ãã¹ãŠãæçœãªæ€çŽ¢ã®ãªããã€ããªåœ¢åŒã§ãããããADTãã¡ã€ã«ãé€ããŸãã å éšã«ã¯ã解ææã«ã²ãŒã ã«è¡šç€ºãããå 容ãã²ãŒã ã«ç解ãããå¶åŸ¡ã³ãŒããšããŒã¿ãæ··åšããŠããå¿ èŠããããŸãããããã¯ãã¹ãŠäœããã®æ§é ãæã£ãŠããŸãã
.BMPã§æååã調ã¹ããšãåããã¿ãŒã³ãããããšã«æ°ä»ãã§ãããã
39FFã®åŸã«ã¯ãŒãã®2ãã€ãå€ïŒã»ãšãã©ã®å Žåãããã0x0100ã§ãããããããã¯WORDã®å€ã ãšæããŸãïŒããŒãå€ã§çµããASCIIè¡ãããã³ã€ã³ãã³ããç¶ããŸãã å®éãFACEã®BMPãããŒããããã³ã«ãå€ã¯0xFF39ã«ãªããŸãïŒ
å®è¡å¯èœãã¡ã€ã«ã確èªããŸãããã
![](https://habrastorage.org/getpro/habr/post_images/616/b76/0bc/616b760bc005ca014b2bcd82d9430dc8.jpg)
ããïŒ ããã ãã§ãªããä»ã®æå³ããããŸãã Shift-JISã®æ°è¡ããã§ãã¯ããŠããã¿ãŒã³ãèŠã€ãããã©ããã確èªããŸãããã
![](https://habrastorage.org/getpro/habr/post_images/56c/74f/7a4/56c74f7a47d4cf79f88d72ff0ff58d05.jpg)
ãããïŒ ãã¹ãŠã®è¡ã¯0xFF33ã§å§ãŸãã2ã€ã®16ãããå€ïŒ0x0F00ïŒãããããã®åŸã«Shift-JISã®è¡ãç¶ããŸãã
æ³šïŒ SHIFT-JISããã«å€ã§çµäºããªãããšã«æ°ä»ãå ŽåããããŸãããããã¯äžå¯èœã§ãã äžéšã®ããã°ã©ã ã¯ã·ã³ã°ã«ãã€ããšãã«ããã€ãã®äž¡æ¹ã®æåå€ãåŠçã§ããŸãããå€ãããã°ã©ã ã§ã¯ããã¯æ·±å»ãªåé¡ã§ããã ãã®çµæãã芧ã®ãšããããã¹ãŠã®æ¹è¡ïŒ0x0aïŒã®åŸã«0x00ãç¶ããŸãã å®éãALL ALL ASCIIæåã®åŸã«ã¯0x00ïŒäž¡æ¹ã®æ°åãŸãã¯è±åïŒãç¶ããŸãã ãããã£ãŠãããã¹ãã¬ã³ããªã³ã°ã¯ãASCIIæåïŒ0-127ïŒã®ãã«ããã€ã解éããµããŒãã§ããå¶åŸ¡ãã€ãã§ããŒã¿ãã€ããèªã¿åããšãã«æ··ä¹±ãããéããŸãåæ§ã§ãã
ãããã£ãŠãã²ãŒã ã®ããžãã¯ã¯ãäœããã®æ¹æ³ã§çµäºãèŠã€ãããŸã§ïŒããããæ°ãããªãã³ãŒãïŒéåžžã¯0x28FFïŒãèŠã€ããããšã«ãã£ãŠïŒæååã解æããå¿ èŠããããšçµè«ä»ããŠããŸãã
ãããã£ãŠãADOãã¡ã€ã«ã«ã¯ãã¹ã¯ãªããåãããããªãã³ãŒãããšããã«ç¶ãããŒã¿ãè©°ã蟌ãŸããŠããŸãã çè«çã«ã¯ãã²ãŒã ãããããèªã¿åãã以åã®ãªãã³ãŒãã«åºã¥ããŠãã©ã®ããŒã¿ãäºæãããããç¥ã£ãŠãããšæ³å®ã§ããŸãã ããã§ãïŒãã¹ãŠã®ã±ãŒã¹ã§ïŒäžèšã§èŠã€ããå®è¡å¯èœãã¡ã€ã«ã®ã¹ã€ããã³ã³ã¹ãã©ã¯ããèŠãŠãã²ãŒã ã§äœ¿çšããããã¹ãŠã®ãªãã³ãŒãã匷調衚瀺ã§ããŸãïŒåœ¢åŒãããå®å šã«ç解ããããïŒã
å€ïŒ0xFF20ã0xFF87ïŒã«æ³šç®ããADOãã¡ã€ã«ã§ããããæ¢ãã次ã®ãªãã³ãŒãã®åã«åãæ°ã®ããŒã¿ãã€ãããããã©ãããå€æããŸãã ãããã2ãã€ãå€ãæååãªã©ã§ãããã©ããã調ã¹ãŠã¿ãŸãããã
![](https://habrastorage.org/getpro/habr/post_images/677/f81/f41/677f81f417dfa02cbf948dfdc1c1b03f.jpg)
ããã«ãå®è¡å¯èœãã¡ã€ã«ã«ã¯éåžžã«èå³æ·±ãããã¹ããå«ãŸããŠããããšã«æ°ä»ãã§ãããã
![](https://habrastorage.org/getpro/habr/post_images/e91/7c2/4be/e917c24bea46ab4ccdc8da43adb31b2a.jpg)
ããã¯å®éã«ã¯ãªã¹ãã§ããããªãã³ãŒãã®ååã®ããã«çãããèŠããŸãã 幞ããªããšã«ãããã§ãïŒ ããã§ããªãã³ãŒãã®ååãããããŸããã
![](https://habrastorage.org/getpro/habr/post_images/b4b/5e6/49f/b4b5e649fc030fd7207027355318a755.jpg)
ãã®æ®µéã§ããããã¬ãŒã䜿çšããŠã²ãŒã ãéå§ããæ§æã®å®è¡ãäžæããŠãç°ãªããªãã³ãŒãã®ã¢ã¯ã·ã§ã³ã芳å¯ã§ããŸãã ç§ãã¡ã®èå³ã®1ã€ã¯JMPã§ã...
å®éãæåã®JMPïŒ0xFF22ïŒã®åŸã«ã¯2ãã€ãå€0x17ããããŸãã
ã²ãŒã ã§ããã芳å¯ããADO_offsetãIDAã§èŠ³å¯ãããå€æ°ãšããŠèšå®ãããšãã²ãŒã ã¯ãã®å€ãã0x1B32ã«ç§»è¡ããããšãããããŸãã 圌女ã¯ãããè¡ãå¿ èŠãããããšãã©ã®ããã«ç¥ã£ãŠããŸããïŒ ããã¯èŠå ã§ã¯ãããŸãã...ããããïŒ
![](https://habrastorage.org/getpro/habr/post_images/3f9/898/0ac/3f98980accd66ab7f0885b6c2f3b0bbe.jpg)
ããïŒ
0x17 * 4 = 0x5Cãã€ãŸããADTã¯ããŸããŸãªã·ãŒã³ã®é·ç§»ããŒãã«ã§ãã CALLïŒ0xFF23ïŒé¢æ°ãåæ§ã«æ©èœããŸããããã°ãããããšãã®ãªãã»ããã«æ»ããŸã...æåã®ããã€ãã®ADTãªãã»ããã¯0xFF00ãæããŸãã ããã¯ã²ãŒã ã§ã¯éåžžã«éèŠã§ãããšæããããã©ã³ãžã·ã§ã³ã¯å®éã«ããããã¹ãããããŸãïŒãã©ã³ãžã·ã§ã³åŸã«ãªãã»ããã«+2ãè¿œå ããŸãïŒã ããã¯RETNãªãã³ãŒãã®ãããªãã®ã§ããïŒ ããæãã
ãã ããADTãã¡ã€ã«ã®æåŸã«ã¯ç°ãªãå€ãå«ãŸããŠãããADOãã¡ã€ã«ã®ãµã€ãºã倧ããè¶ ããŠããããšã«æ°ä»ãã§ãããã 圌ãã¯äœãäžããŸããïŒ ãããç解ããŸããããŸãããããã®é·ç§»ãã©ã®ããã«æ©èœããããç解ããããã«ãã²ãŒã ã®å®è¡ããã»ã¹ã詳ããèŠãŠã¿ãŸãããïŒç¹å¥ãªæ³šæãæããŸãïŒã
![](https://habrastorage.org/getpro/habr/post_images/3db/8c4/488/3db8c4488987ac19c99f404c76265c5b.jpg)
ã¡ã¢ãªãã³ããäœæãããšãã¡ã¢ãªå ã®ADCãªããžã§ã¯ããã¡ã€ã«ïŒCT.ADOïŒã®å€ã0x8000 int16ã§ããã0x8000ãŸãã¯32 KBããšã«æžã蟌ãŸããŠããããšãããããŸãã ãŸããADOã¯å€æŽãããŠããŸããã ãŸããå®è¡å¯èœãã¡ã€ã«ã§ãé¢æ°ãå€ã解æãããã®å€ãèŠã€ãã£ãå ŽåïŒNOPãªã©ïŒã2ãã€ããã¹ãããããããšãããããŸãã
![](https://habrastorage.org/getpro/habr/post_images/7ed/118/d19/7ed118d1928a80864203301b4aea19d1.jpg)
ã²ãŒã ã¯ããŒã¿ã32 KBã®ãã©ã°ã¡ã³ãã«åå²ããããïŒã»ãšãã©ã®å Žåãããå€ãã®ã»ã°ã¡ã³ãã«ã¡ã¢ãªã«ã¢ã¯ã»ã¹ããããã2ãã€ãå€ã«ééããããšãå€ã-ããã¯éèŠã§ãïŒãADTã«ã¯äœããã®çš®é¡ã®ã¢ãã¬ã¹å€æãå¿ èŠã§ãïŒADTã¯ã¢ãã¬ã¹ã®ãªãã»ããã䜿çšããããïŒ 4ãã€ãïŒã
![](https://habrastorage.org/getpro/habr/post_images/ef5/e65/545/ef5e65545658e85626eac9fc7a974d8c.jpg)
ããã«å€ãã®æ°åŠããããŸãããããã¬ã§èŠ³å¯ããå Žåãããã¯æ¬¡ã®ããã«ãªããŸãã
![](https://habrastorage.org/getpro/habr/post_images/2e2/cbe/b93/2e2cbeb931f72abc38e85d4dc50d2a1f.jpg)
æåã«é¢æ°ãèŠã€ããããADOãã¡ã€ã«ã®æåŸãžã®ãã€ã³ã¿ãŒããããšä»®å®ããŠãADTãã¡ã€ã«ã®æåŸã«å°éããŸããïŒæåŸã®RETNã®ãªãã»ããã¯0x253F4ã§ãïŒã ADTãªã¹ãã§ã¯ã0x453F4ãšããŠãªã¹ããããŠããŸãã ä»ã®ããŸããŸãªã¢ãã¬ã¹ãæ¢ããåŸãå€æã«2ã€ã®æå¹ãªãã€ãã䜿çšãããããããååã«åå²ããŠæåŸã«æ¿å ¥ããŠããããšã«æ°ä»ããŸããã
æªãã¯ãããŸããããADTãã¡ã€ã«ãçæã§ããããã«ãªããŸããïŒéã®æäœïŒééãã0x8000ã®ééã«å¿ããŠãæãéèŠãªãã®ãä¹ç®ããããšã«ããïŒã ãŸããäžè¬çãªãªãã³ãŒãã¹ããŒã ããããè¡ã®å Žæãããã£ãŠããŸãã å解ããåã«ãè³ãèŠãŠæåãå°œãããŸãããïŒç¿»èš³ãæåïŒã
ããŒã4ïŒCTTDTIã®çª
æ ŒçŽãããŠãããã©ãŒãããæååãšãADOãã¡ã€ã«ããããããèªã¿åãæ¹æ³ãç¥ã£ãŠããŸãã ãã¡ãããããããæ¿å ¥ãçŽãã«ã¯ãADTãªãã»ãããå€æŽããå¿ èŠããããŸããããã¯ãæååã®ãµã€ãºãã¯ããã«å€§ãããªãå Žåãšå°ãããªãå Žåãããããã§ãã ãŸããADOè¡ãããã¹ããã¡ã€ã«ã«ã«ããããéåžžã«ç°¡åã«ç·šéã§ãããã®ã«ããããšãæ€èšããŠãã ãããããã¯å¥ã®ããã°ã©ã ãšèŠãªãããšãã§ããŸãã æ°ããADOãã¡ã€ã«ã«è¡ãç°¡åã«æ¿å ¥ãããªãã»ãããç°¡åã«å€æŽã§ãã圢åŒãäœæããŸãããã ããã«ã¯äœãå¿ èŠã§ããïŒ
ãã®ãããè¡ã®éå§äœçœ®ã®ãªãã»ãããå ã®è¡ã®ãµã€ãºïŒãã€ãåäœïŒã次ã«è¡èªäœã次ã®ãããªãã®ã§ãã
0xE92 25 blahblahblah
cttd.pyãäœæããŸãã
''' CTD - Clocktower Text Dumper by rFx ''' import os,sys,struct,binascii f = open("CT_J.ADO","rb") data = f.read() f.close() g = open("ct_txt.txt","wb") for i in range(0,len(data)-1): if(data[i] == '\x33' and data[i+1] == '\xff'): # 6 - , . i+=6 str_offset = i str_end = data[i:].index('\xff') -1 newstr = data[i:i+str_end] strlen = len(newstr) newstr = newstr.replace("\x0a\x00","[NEWLINE]") # ASCII, . newstr = newstr.replace("\x00","") g.write("%#x\t%d\t" % (str_offset,strlen)) g.write(newstr) g.write("\n") g.close()
åŸã§æ°ãããã¡ã€ã«ãçæããããã«ãCT.ADOãCT_J.ADOã«ååå€æŽããŸããã
ãã®ããã°ã©ã ã¯ãADOãã¡ã€ã«ãèªã¿åãã0xFF33ãèŠã€ããŠ6ãã€ããã¹ããããïŒãªãã³ãŒããš2ã€ã®2ãã€ãå€ããã€ãã¹ããããïŒãæåã®è¡ãªãã»ãããè¡ã®é·ããããã³è¡èªäœãã¿ãåºåã圢åŒã§æžã蟌ã¿ãæ°ãããã¡ã€ã«ã§æ°ããè¡ã§çµãããŸãã
ãã¹ãŠã®å€0x0aïŒæ¹è¡ïŒã[NEWLINE]ã«çœ®ãæããŠããããšã«æ°ã¥ãã§ãããã ããã¯ãè¡å šäœã1è¡ã§åŠçããããã¹ããã¡ã€ã«ã®åœ¢åŒãå€æŽããã«æ°ããè¡ãå¿ èŠãªå Žæã«å®çŸ©ã§ããããã§ãã
楜ãã¿ã®ããã«ããã«ãªããšãããŸãããããã®ããã¹ãã翻蚳è ã§è§£æããŸãã ããã¯ãGoogle翻蚳ã«ããŒã¿ãããŒãããèšèªãèªåçã«èªèãã翻蚳ããŠç®çã®èšèªã®ããã¹ããè¿ãPythonã¢ãžã¥ãŒã«ã§ãã
cttt.pyïŒ
#!/usr/bin/env python # -*- encoding: utf-8 -*- ''' Clocktower Auto Translator by rFx ''' import os,sys,binascii,struct from translate import Translator translator = Translator(to_lang="en") #Set to English by Default f = open("ct_txt.txt","rb") g = open("ct_txt_proc2.txt","wb") proc_str = [] for line in f.readlines(): proc_str.append(line.rstrip()) for x in range(0,len(proc_str)): line = proc_str[x] o,l,instr = line.split("\t") ts = translator.translate(instr.decode("SHIFT-JIS").encode("UTF-8")) ts = ts.encode("SHIFT-JIS","replace") proc_str[x] = "%s\t%s\t%s" % (o,l,ts) g.write(proc_str[x]+"\n") #for pc in proc_str: # g.write(pc) g.close()
ã€ã³ãžã§ã¯ã¿ãŒã§æ°è¡è©ŠããŠã¿ãŸããã-ãã®ããã±ãŒãžã®æåŸã®ããã°ã©ã ã¯ãããã¹ããã¡ã€ã«ã解æããè¡ã®ãã¹ãŠã®ASCIIæåã«ãŒããè¿œå ããèŸæžã«è¡ãèªã¿èŸŒãã§ãã©ã®ãªãã»ãããå«ãŸããŠãããã確èªããŸãã ããã«ãADOããŒãããåäœæãïŒADTãèªã¿åãããã¹ãŠã®ãã·ãŒã³ãããªãã»ãããšãšãã«é åã«ããŒãããè¡éããã³ãã®åŸã®ãã¹ãŠã®ããŒã¿ãã³ããŒããŸãïŒãADOã®ãã·ãŒã³ãã®ãµã€ãºã«åºã¥ããŠADTãåçæããŸãã
ctti.pyïŒ
''' Clocktower Text Injector by rFx ''' import os,sys,struct,binascii def is_ascii(s): return all(ord(c) < 128 for c in s) def get_real_offset(offset): # high_val = offset & 0xFFFF0000 high_val /= 2 low_val = offset & 0xFFFF return high_val+low_val def get_fake_offset(offset): # mult = int(offset / 0x8000) shft_val = 0x8000 * mult low_val = offset & 0xFFFF return offset + shft_val f = open("CT_J.ADO","rb") data = f.read() f.close() offset_vals = [] adt_list = [] newdata = "" f = open("ct_txt_proc.txt","rb") lines = f.readlines() o,l,s = lines[0].split("\t") first_offset = int(o,16) o,l,s = lines[0].split("\t") last_offset_strend = int(o,16) + int(l) newdata = data[:first_offset] for i in range(0,len(lines)): line = lines[i] offset, osl, instr = line.split("\t") offset = int(offset,16) instr = instr.rstrip('\n') instr = instr.replace("[NEWLINE]","\x0a") # ASCII. instr = instr.decode("SHIFT-JIS") newstr = "" for char in instr: if(is_ascii(char)): newstr+=char+'\x00' else: newstr+=char instr = newstr instr = instr.encode("SHIFT-JIS") newstrlen = len(instr) osl = int(osl) strldiff = newstrlen - osl # if(i < len(lines)-1): nextline = lines[i+1] nextoffset,nsl,nstr = nextline.split("\t") offset_vals.append({"offset":offset,"val":strldiff}) nextoffset = int(nextoffset,16) newdata += instr+data[offset+osl:nextoffset] else: offset_vals.append({"offset":offset,"val":strldiff}) newdata += instr + data[offset+osl:] # EOF f.close() # ADO. g = open("CT.ADO","wb") g.write(newdata) g.close() # ADT. f = open("CT_J.ADT","rb") datat = f.read() f.close() g = open("CT.ADT","wb") for i in range(0,len(datat),4): cur_offset = get_real_offset(struct.unpack("<I",datat[i:i+4])[0]) final_adj = 0 for offset in offset_vals: if(cur_offset > offset["offset"]): final_adj += offset["val"] g.write(struct.pack("<I",get_fake_offset(cur_offset + final_adj))) g.close()
ä»çµã¿ã確èªããŸãããã
![](https://habrastorage.org/getpro/habr/post_images/7e6/70c/100/7e670c10068e9e538d854f6c5797c5c6.png)
ãããïŒ
幞ããªããšã«ãè±èªã¯Clocktowerãã¡ã³ãã©ãŒã©ã ã§ç¿»èš³ãããrtfãã¡ã€ã«ãèŠã€ãã倧ãŸããªç¿»èš³ã«åºã¥ããŠè¡ãæåã§ç·šéããããšãã§ããŸããã
![](https://habrastorage.org/getpro/habr/post_images/7b2/0b8/6df/7b20b86df9f8929f14441c4d6c9049d2.jpg)
ãã¹ãŠã翻蚳ãããæºåå®äºã§ãïŒ å®è¡ããŸãããïŒ
![](https://habrastorage.org/getpro/habr/post_images/3c4/e0d/b75/3c4e0db7552dd97080bbe399d6fa89de.jpg)
ãããŒïŒ
äœãåé¡ããããŸããIDAã«ãã¡ã€ã«ãããããããŠãäœãèµ·ãããèŠãŠã¿ãŸãããã
![](https://habrastorage.org/getpro/habr/post_images/c7b/311/81b/c7b31181b328fd144a4505a3383fec65.jpg)
![](https://habrastorage.org/getpro/habr/post_images/45f/204/f09/45f204f0942b5435aa29e6a5aca0634b.jpg)
ADOãã¡ã€ã«ãã¡ã¢ãªã«èªã¿èŸŒãã§ããããã«èŠããŸããããã€ã³ã¿ã䜿çšããããšããŠããŸããããã®å Žæã«ã¯äœããªããã䜿çšã§ããŸããã
![](https://habrastorage.org/getpro/habr/post_images/984/86e/9a6/98486e9a69c90a7d53db1487e0b1c1c2.jpg)
ããããæ§é äœa1ãšãããå®è¡ããmallocã芳å¯ããŸãããããã¯ããããåé¡ã§ãã ããå°ãæãäžããåŸããããã®ãã€ã³ã¿ãŒãããã§äœæãããŠããããšãããããŸãã
![](https://habrastorage.org/getpro/habr/post_images/28b/8ef/756/28b8ef756fbff6c8562a73ca9ed73a23.jpg)
ã€ãŸããã²ãŒã ã¯ïŒcmp5ãªãã³ãŒãã«åºã¥ããŠïŒADO 5 * 0x8000ã®ãã©ã°ã¡ã³ãã«å¯ŸããŠã®ã¿ãã€ã³ã¿ãŒãäœæããŸãããEOFã®åã«ADOããŒã¿ãèªã¿åããŸãïŒããã¯ééãã§ãïŒã ãã®çµæã0x28000以äžã®ãµã€ãºã®ADOãã¡ã€ã«ãããŒãã§ããŸãã ç§ãã¡ãæ¢ããŸããïŒ ãã¡ããéããŸãïŒ ã¡ã¢ãªå ã®SCEæ§é ã詳ããèŠãŠã¿ãŸããã...
ADOãã€ã³ã¿ãŒãèªã¿èŸŒããã¹ãŠã®ã±ãŒã¹ã5ãã6ã«å€æŽããŠå¥ã®ãã€ã³ã¿ãŒãè¿œå ã§ããŸããããã®æåŸã®ãã€ã³ã¿ãŒã®åŸã«äœãèµ·ããã§ããããïŒ ãã¡ãããADTã·ãããéå§ãããŸã
![](https://habrastorage.org/getpro/habr/post_images/853/62a/f08/85362af08c6eac09cb49aae9825b5830.jpg)
ãªãã»ããADT 0x00ã¯struct_head + 0x2Aã«ããã0x7D0ã«ç§»åããŠããããšãããããŸã... 0x7D0ãžã®ãã€ã³ã¿ãŒ??? 0x8000ã®ããã«èŠããŸãã
ãã®çµæãADTãã¡ã€ã«ã«ã¯0x4800ãã€ããããããŸããã æåã®ADTã€ã³ããã¯ã¹ãããšãã°0x2Eã«äžãããšãå¥ã®ADOãã€ã³ã¿ãŒãæžã蟌ãããã«4åã®ãã€ããåŸãããæåŸã«ãŸã å€ãã®ç©ºãã¹ããŒã¹ããããšèšããŸã
0x2Aãžã®æ§é äœãªã³ã¯ãèŠã€ããŠã0x2Eã«å€æŽããŸã
![](https://habrastorage.org/getpro/habr/post_images/ae1/815/fe0/ae1815fe0ce615a6c9c923634561e934.jpg)
ã¯ãïŒ ãªããžã§ã¯ãæåã®ãªããŒã¹ãšã³ãžãã¢ãªã³ã°ã倧奜ãã§ãã
çŽ æŽããããä»ã²ãŒã ã¯å®å šã«ç¿»èš³ãããŠããŸãã 次ã¯ïŒ
16é²ãšãã£ã¿ã䜿çšããŠCT32.exeã«ãã€ããªå€æŽãå ããå¿ èŠããããŸãã
529B: 74 EB BC7B: 2A 2E BC8D: D0 CC BD35: 2A 2E BD62: 2A 2E D4DA: 2A 2E D4FC: 2A 2E DA58: 2A 2E DA79: 2A 2E 103DA: 2A 2E 10407: 2A 2E 104F8: 2A 2E 105BB: 2A 2E 105E8: 2A 2E 10703: 2A 2E 10730: 2A 2E 115FA: 2A 2E 116B2: 05 06 116E8: 05 06 11720: 2A 2E 11729: D0 CC 1195D: 05 06 1C50F: 20 00
Work for the Future-ããŒã5-SCEDASM-SCEéã¢ã»ã³ãã©ãŒ
次ã®è«çã¹ãããã¯ãä»ã®ãã¹ãŠã®ãªãã³ãŒããéã¢ã»ã³ãã«ããŠãã²ãŒã /ãšãã£ã¿ãŒã§èªã¿åãããããã¹ããã¡ã€ã«ãäœæããããšã§ãã
ãã®ãããªãã®ïŒ
''' Clocktower ADC Object File Disassembler by rFx ''' import os,sys,binascii,struct ADO_FILENAME = "CT_J.ADO" ADT_FILENAME = "CT_J.ADT" ADO_OP = { 0xFF00:"RETN", #Scene Prologue - 0 bytes of data. - Also an END value... the game looks to denote endings. 0xFF01:"UNK_01", # varying length data 0xFF02:"UNK_02", # 3 bytes of data 0xFF03:"UNK_03", # 3 bytes of data 0xFF04:"UNK_04", # 3 bytes of data 0xFF05:"UNK_05", # 3 bytes of data 0xFF06:"UNK_06", # 3 bytes of data 0xFF07:"UNK_07", # 3 bytes of data 0xFF0A:"UNK_0A", # 4 bytes of data. Looks like an offset to another link in the list? 0xFF0C:"UNK_0C", # 4 bytes of data 0xFF0D:"UNK_0D", # 4 bytes of data 0xFF10:"UNK_10", # 4 bytes of data 0xFF11:"UNK_11", # 4 bytes of data 0xFF12:"UNK_12", # 4 bytes of data 0xFF13:"UNK_13", # 4 bytes of data 0xFF14:"UNK_14", # 4 bytes of data 0xFF15:"UNK_15", # 4 bytes of data 0xFF16:"UNK_16", # 4 bytes of data 0xFF1F:"UNK_1F", # 0 bytes of data 0xFF20:"ALL", # 0 bytes of data. Only at the end of the ADO (twice) #All opcodes above this are like... prologue opcodes (basically in some other list) 0xFF21:"ALLEND", # 2 bytes of data 0xFF22:"JMP", # 2 bytes of data - I think it uses the value for the int offset in adt as destination +adds 2 0xFF23:"CALL", # 6 bytes of data 0xFF24:"EVDEF", # Not used in the game 0xFF25:"!!!!!!", #Not used in the game 0xFF26:"!!!!!!", #Not used in the game 0xFF27:"!!!!!!", #Not used in the game 0xFF28:"!!!!!!", #0 bytes of data. 0xFF29:"END_IF", # 4 bytes of data 0xFF2A:"WHILE", # 4 bytes of data 0xFF2B:"NOP", # 0 bytes of data 0xFF2C:"BREAK", # Not used in the game 0xFF2D:"ENDIF", # 2 bytes of data 0xFF2E:"ENDWHILE", # 2 bytes of data 0xFF2F:"ELSE", # 2 bytes of data 0xFF30:"MSGINIT", # 10 bytes of data 0xFF31:"MSGTYPE", # Not used in the game 0xFF32:"MSGATTR", # 16 bytes of data 0xFF33:"MSGOUT", # Varying length, our in-game text uses this. :) 0xFF34:"SETMARK", #Varying length 0xFF35:"SETWAIT", #Not used in the game 0xFF36:"MSGWAIT", #0 bytes of data 0xFF37:"EVSTART", #4 bytes of data 0xFF38:"BGFILEDISP", #Not used in the game. 0xFF39:"BGLOAD", #Varying length, normally a path to a BMP file is passed in. 0xFF3A:"PALLOAD", #Varying length. Also takes BMP files. 0xFF3B:"BGMREQ", #Varying length - loads a MIDI file into memory. 0xFF3C:"SPRCLR", #2 bytes of data. 0xFF3D:"ABSOBJANIM", #Not used in the game 0xFF3E:"OBJANIM", #Not used in the game. 0xFF3F:"ALLSPRCLR", #0 bytes of data 0xFF40:"MSGCLR", #0 bytes 0f data 0xFF41:"SCREENCLR", #0 bytes of data 0xFF42:"SCREENON", #0 bytes of data 0xFF43:"SCREENOFF", #0 bytes of data 0xFF44:"SCREENIN", # Not used in the game. 0xFF45:"SCREENOUT", # Not used in the game. 0xFF46:"BGDISP", # Always 12 bytes of data. 0xFF47:"BGANIM", #14 bytes of data. 0xFF48:"BGSCROLL",#10 bytes of data. 0xFF49:"PALSET", #10 bytes of data. 0xFF4A:"BGWAIT", #0 bytes of data. 0xFF4B:"WAIT", #4 bytes of data. 0xFF4C:"BWAIT", #Not used in the game. 0xFF4D:"BOXFILL", #14 bytes of data. 0xFF4E:"BGCLR", # Not used in the game. 0xFF4F:"SETBKCOL", #6 bytes of data. 0xFF50:"MSGCOL", #Not used in the game. 0xFF51:"MSGSPD", #2 bytes of data. 0xFF52:"MAPINIT", #12 bytes of data. 0xFF53:"MAPLOAD", #Two Paths... Sometimes NULL NULL - Loads the background blit bmp and the map file to load it. 0xFF54:"MAPDISP", #Not used in the game. 0xFF55:"SPRENT", #16 bytes of data. 0xFF56:"SETPROC", #2 bytes of data. 0xFF57:"SCEINIT", #0 bytes of data. 0xFF58:"USERCTL", #2 bytes of data. 0xFF59:"MAPATTR", #2 bytes of data. 0xFF5A:"MAPPOS", #6 bytes of data. 0xFF5B:"SPRPOS", #8 bytes of data. 0xFF5C:"SPRANIM", #8 bytes of data. 0xFF5D:"SPRDIR", #10 bytes of data. 0xFF5E:"GAMEINIT", #0 bytes of data. 0xFF5F:"CONTINIT", #0 bytes of data. 0xFF60:"SCEEND", #0 bytes of data. 0xFF61:"MAPSCROLL", #6 bytes of data. 0xFF62:"SPRLMT", #6 bytes of data. 0xFF63:"SPRWALKX", #10 bytes of data. 0xFF64:"ALLSPRDISP", #Not used in the game. 0xFF65:"MAPWRT", #Not used in the game. 0xFF66:"SPRWAIT", #2 bytes of data. 0xFF67:"SEREQ", #Varying length - loads a .WAV file. 0xFF68:"SNDSTOP", #0 bytes of data. 0xFF69:"SESTOP", #Varying length - specifies a .WAV to stop or ALL for all sounds. 0xFF6A:"BGMSTOP", #0 bytes of data. 0xFF6B:"DOORNOSET", #0 bytes of data. 0xFF6C:"RAND", #6 bytes of data. 0xFF6D:"BTWAIT", #2 bytes of data 0xFF6E:"FAWAIT", #0 bytes of data 0xFF6F:"SCLBLOCK", #Varying length - no idea. 0xFF70:"EVSTOP", #Not used in the game. 0xFF71:"SEREQPV", #Varying length - .WAV path input, I think this is to play and repeat. 0xFF72:"SEREQSPR", #Varying length - .WAV path input, I think this is like SEREQPV except different somehow. 0xFF73:"SCERESET", #0 bytes of data. 0xFF74:"BGSPRENT", #12 bytes of data. 0xFF75:"BGSPRPOS", #Not used in the game. 0xFF76:"BGSPRSET", #Not used in the game. 0xFF77:"SLANTSET", #8 bytes of data. 0xFF78:"SLANTCLR", #0 bytes of data. 0xFF79:"DUMMY", #Not used in the game. 0xFF7A:"SPCFUNC", #Varying length - usage uncertain. 0xFF7B:"SEPAN", #Varying length - guessing to set the L/R of Stereo SE. 0xFF7C:"SEVOL", #Varying length - guessing toe set the volume level of SE 0xFF7D:"BGDISPTRN", #14 bytes of data. 0xFF7E:"DEBUG", #Not used in the game. 0xFF7F:"TRACE", #Not used in the game. 0xFF80:"TMWAIT", #4 bytes of data. 0xFF81:"BGSPRANIM", #18 bytes of data. 0xFF82:"ABSSPRENT", #Not used in the game. 0xFF83:"NEXTCOM", #2 bytes of data. 0xFF84:"WORKCLR", #0 bytes of data. 0xFF85:"BGBUFCLR", #4 bytes of data. 0xFF86:"ABSBGSPRENT", #12 bytes of data. 0xFF87:"AVIPLAY", #This one is used only once - to load the intro AVI file. 0xFF88:"AVISTOP", #0 bytes of data. 0xFF89:"SPRMARK", #Only used in PSX Version. 0xFF8A:"BGMATTR",#Only used in PSX Version. #BIG GAP IN OPCODES... maybe not even in existence. 0xFFA0:"UNK_A0", #12 bytes of data. 0xFFB0:"UNK_B0", #12 bytes of data. 0xFFDF:"UNK_DF", #2 bytes of data. 0xFFE0:"UNK_E0", #0 bytes of data. 0xFFEA:"UNK_EA", #0 bytes of data. 0xFFEF:"UNK_EF" #12 bytes of data. } if(__name__=="__main__"): print("#Disassembling ADO/ADT...") #Read ADO/ADT Data to memory. f = open(ADO_FILENAME,"rb") ado_data = f.read() f.close() f = open(ADT_FILENAME,"rb") adt_data = f.read() f.close() scene_count = -1 #Skip ADO Header i = 256 while i < (len(ado_data) -1): cur_val = struct.unpack("<H",ado_data[i:i+2])[0] if(cur_val in ADO_OP.keys()): #0xFF00 if(cur_val == 0xFF00): scene_count +=1 print("#----SCENE %d (Offset %#x)" % (scene_count,i)) print(ADO_OP[cur_val]) i+=2 elif(cur_val == 0xFF1F or cur_val == 0xFF20 or cur_val == 0xFF84 or cur_val == 0xFFEA or cur_val == 0xFFE0 or cur_val == 0xFF88 or cur_val == 0xFF78 or cur_val == 0xFF73 or cur_val == 0xFF6E or cur_val == 0xFF6B or cur_val == 0xFF6A or cur_val == 0xFF68 or cur_val == 0xFF60 or cur_val == 0xFF5F or cur_val == 0xFF5E or cur_val == 0xFF57 or cur_val == 0xFF4A or cur_val == 0xFF43 or cur_val == 0xFF42 or cur_val == 0xFF41 or cur_val == 0xFF40 or cur_val == 0xFF36 or cur_val == 0xFF3F or cur_val == 0xFF36 or cur_val == 0xFF2B or cur_val == 0xFF28): print(ADO_OP[cur_val]) i+=2 #0xFF22 elif(cur_val == 0xFF22 or cur_val == 0xFF51 or cur_val == 0xFF21 or cur_val == 0xFF2D or cur_val == 0xFF2E or cur_val == 0xFF2F or cur_val == 0xFF3C or cur_val == 0xFF56 or cur_val == 0xFF58 or cur_val == 0xFF59 or cur_val == 0xFF66 or cur_val == 0xFF6D or cur_val == 0xFF83 or cur_val == 0xFFDF): i+=2 jmpdata = struct.unpack("<H",ado_data[i:i+2])[0] print("%s %d" % (ADO_OP[cur_val],jmpdata)) i+=2 #0xFF23 elif(cur_val == 0xFF23): i+=2 val_1 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 val_2 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 val_3 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 print("%s %#x %#x %#x" % (ADO_OP[cur_val],val_1,val_2,val_3)) elif cur_val == 0xFF29 or cur_val == 0xFF2A or cur_val == 0xFF37: i+=2 val_1 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 val_2 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 print("%s %d %d" % (ADO_OP[cur_val],val_1,val_2)) elif cur_val in range(0xFF02,0xFF08): i+=2 pri_val = struct.unpack("b",ado_data[i])[0] i+=1 sec_val = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 print("%s %d %d" % (ADO_OP[cur_val],pri_val,sec_val)) elif cur_val in range(0xFF0A,0xFF17): i+=2 pri_val = struct.unpack("<I",ado_data[i:i+4])[0] i+=4 print("%s %#x" % (ADO_OP[cur_val],pri_val)) elif (cur_val == 0xFF30): i+=2 val_1 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 val_2 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 val_3 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 val_4 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 val_5 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 print("%s %#x %#x %#x %#x %#x" % (ADO_OP[cur_val],val_1,val_2,val_3,val_4,val_5)) elif (cur_val == 0xFF33): i+=2 val_1 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 val_2 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 endstr_offset = ado_data[i:].index("\xff") endstr_offset -=1 instr = ado_data[i:i+endstr_offset] i+= len(instr) #Decode to UTF-8 instr = instr.replace("\x0a\x00","[NEWLINE]") instr = instr.replace("\x00","[NULL]") instr = instr.decode("SHIFT-JIS") instr = instr.encode("UTF-8") print("%s %#x %#x ``%s``" % (ADO_OP[cur_val],val_1,val_2,instr)) elif (cur_val == 0xFF32): i+=2 val_1 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 val_2 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 val_3 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 val_4 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 val_5 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 val_6 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 val_7 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 val_8 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 print("%s %#x %#x %#x %#x %#x %#x %#x %#x" % (ADO_OP[cur_val],val_1,val_2,val_3,val_4,val_5,val_6,val_7,val_8)) elif(cur_val == 0xFF34): i+=2 endval_offset = ado_data[i:].index("\xff") - 1 instr = ado_data[i:i+endstr_offset] i+= len(instr) print("%s %s" % (ADO_OP[cur_val],binascii.hexlify(instr))) i+=2 elif(cur_val in range(0xFF39,0xFF3C) or cur_val == 0xFF67): i+=2 val_1 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 endstr_offset = ado_data[i:].index("\xff") - 1 instr = ado_data[i:i+endstr_offset] i+= len(instr) if(instr.find("\x00\x00\x00") != -1): finstr = instr[:instr.index("\x00")] val_2 = struct.unpack("b",instr[instr.index("\x00")+1:instr.index("\x00")+2])[0] val_3 = struct.unpack("b",instr[instr.index("\x00")+2:])[0] print("%s %#x %s %#x %#x" % (ADO_OP[cur_val],val_1,finstr,val_2,val_3)) elif(instr.find("\x00\x00") != -1): finstr = instr[:instr.index("\x00")] val_2 = struct.unpack("b",instr[instr.index("\x00")+1:])[0] print("%s %#x %s %#x" % (ADO_OP[cur_val],val_1,finstr,val_2)) elif(cur_val == 0xFF69): i+=2 endstr_offset = ado_data[i:].index("\xff") - 1 instr = ado_data[i:i+endstr_offset] i+= len(instr) if(instr.find("\x00\x00\x00") != -1): finstr = instr[:instr.index("\x00")] val_2 = struct.unpack("b",instr[instr.index("\x00")+1:instr.index("\x00")+2])[0] val_3 = struct.unpack("b",instr[instr.index("\x00")+2:])[0] print("%s %s %#x %#x" % (ADO_OP[cur_val],finstr,val_2,val_3)) elif(instr.find("\x00\x00") != -1): finstr = instr[:instr.index("\x00")] val_2 = struct.unpack("b",instr[instr.index("\x00")+1:])[0] print("%s %s %#x" % (ADO_OP[cur_val],finstr,val_2)) elif(cur_val == 0xFF71 or cur_val == 0xFF72): i+=2 val_1 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 val_2 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 val_3 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 endstr_offset = ado_data[i:].index("\xff") - 1 instr = ado_data[i:i+endstr_offset] i+= len(instr) if(instr.find("\x00\x00\x00") != -1): finstr = instr[:instr.index("\x00")] val_4 = struct.unpack("b",instr[instr.index("\x00")+1:instr.index("\x00")+2])[0] val_5 = struct.unpack("b",instr[instr.index("\x00")+2:])[0] print("%s %#x %#x %#x %s %#x %#x" % (ADO_OP[cur_val],val_1,val_2,val_3,finstr,val_4,val_5)) elif(instr.find("\x00\x00") != -1): finstr = instr[:instr.index("\x00")] val_4 = struct.unpack("b",instr[instr.index("\x00")+1:])[0] print("%s %#x %#x %#x %s %#x" % (ADO_OP[cur_val],val_1,val_2,val_3,finstr,val_4)) elif(cur_val == 0xFF87): i+=2 val_1 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 val_2 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 val_3 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 val_4 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 val_5 = struct.unpack("<H",ado_data[i:i+2])[0] i+=2 endstr_offset = ado_data[i:].index("\xff") - 1 instr = ado_data[i:i+endstr_offset] i+= len(instr) if(instr.find("\x00\x00\x00") != -1): finstr = instr[:instr.index("\x00")] val_6 = struct.unpack("b",instr[instr.index("\x00")+1:instr.index("\x00")+2])[0] val_7 = struct.unpack("b",instr[instr.index("\x00")+2:])[0] print("%s %#x %#x %#x %#x %#x %s %#x %#x" % (ADO_OP[cur_val],val_1,val_2,val_3,val_4,val_5,finstr,val_6,val_7)) elif(instr.find("\x00\x00") != -1): finstr = instr[:instr.index("\x00")] val_6 = struct.unpack("b",instr[instr.index("\x00")+1:])[0] print("%s %#x %#x %#x %#x %#x %s %#x" % (ADO_OP[cur_val],val_1,val_2,val_3,val_4,val_5,finstr,val_6)) #NOT DONE YET else: i+=1 else: i+=1
ãã®åŸããã¡ãããããããã¹ãŠãADO / ADTãã¢ã«æ»ãå¿ èŠããããŸãã
Work for the Future-ããŒã6-PSXããŒãžã§ã³
ã²ãŒã ã®PSXããŒãžã§ã³ãADO / ADTã䜿çšããŸãã ãªãœãŒã¹ãå€æããPSXããPCããŒãžã§ã³ã«æä»çãªã³ã³ãã³ããè¿œå ã§ããããã§ãã