diff --git a/build/tools/MasterEditorTWL/MasterEditorTWL.ncb b/build/tools/MasterEditorTWL/MasterEditorTWL.ncb index dd137e78..012c4c93 100644 Binary files a/build/tools/MasterEditorTWL/MasterEditorTWL.ncb and b/build/tools/MasterEditorTWL/MasterEditorTWL.ncb differ diff --git a/build/tools/MasterEditorTWL/MasterEditorTWL.suo b/build/tools/MasterEditorTWL/MasterEditorTWL.suo index b63fbf00..53c4d216 100644 Binary files a/build/tools/MasterEditorTWL/MasterEditorTWL.suo and b/build/tools/MasterEditorTWL/MasterEditorTWL.suo differ diff --git a/build/tools/MasterEditorTWL/MasterEditorTWL/Debug/BuildLog.htm b/build/tools/MasterEditorTWL/MasterEditorTWL/Debug/BuildLog.htm index 4616e8db..e0cb2d97 100644 Binary files a/build/tools/MasterEditorTWL/MasterEditorTWL/Debug/BuildLog.htm and b/build/tools/MasterEditorTWL/MasterEditorTWL/Debug/BuildLog.htm differ diff --git a/build/tools/MasterEditorTWL/MasterEditorTWL/Form1.h b/build/tools/MasterEditorTWL/MasterEditorTWL/Form1.h index b1d77808..ffefd509 100644 --- a/build/tools/MasterEditorTWL/MasterEditorTWL/Form1.h +++ b/build/tools/MasterEditorTWL/MasterEditorTWL/Form1.h @@ -3,6 +3,7 @@ #include "srl.h" #include "deliverable.h" #include "crc_whole.h" +#include "utility.h" namespace MasterEditorTWL { @@ -452,6 +453,7 @@ private: System::Windows::Forms::GroupBox^ gboxProd; + private: System::Windows::Forms::TextBox^ tboxPlatform; @@ -3343,6 +3345,16 @@ private: System::Windows::Forms::GroupBox^ gboxProd; // 特殊な設定をテキストボックスに反映 this->setSrlFormsCaptionEx(); + // SDKバージョンとライブラリ + if( this->hSrl->hSDKList != nullptr ) + { + this->tboxSDK->Clear(); + for each( System::String ^str in this->hSrl->hSDKList ) + { + this->tboxSDK->Text += str + "\r\n"; + } + } + // ペアレンタルコントロール関連 this->setParentalForms(); } @@ -4031,8 +4043,8 @@ private: System::Windows::Forms::GroupBox^ gboxProd; MessageBox::Show( str, "Error", MessageBoxButtons::OK, MessageBoxIcon::Error ); } - // 言語切り替え private: + // 日本語版への切り替え void changeJapanese(void) { System::Int32 index; @@ -4200,6 +4212,7 @@ private: System::Windows::Forms::GroupBox^ gboxProd; } private: + // 英語版への切り替え void changeEnglish(void) { System::Int32 index; diff --git a/build/tools/MasterEditorTWL/MasterEditorTWL/srl.cpp b/build/tools/MasterEditorTWL/MasterEditorTWL/srl.cpp index 50992a4f..692f8827 100644 --- a/build/tools/MasterEditorTWL/MasterEditorTWL/srl.cpp +++ b/build/tools/MasterEditorTWL/MasterEditorTWL/srl.cpp @@ -54,13 +54,14 @@ ECSrlResult RCSrl::readFromFile( System::String ^filename ) } // ファイルを閉じる前にROMヘッダ以外の領域から設定を取り出す { - //ECSrlResult r; + ECSrlResult r; (void)this->hasDSDLPlaySign( fp ); - //if( r != ECSrlResult::NOERROR ) - //{ - // (void)fclose(fp); - // return r; - //} + r = this->searchSDKVersion( fp ); + if( r != ECSrlResult::NOERROR ) + { + (void)fclose(fp); + return r; + } } (void)fclose( fp ); @@ -474,3 +475,65 @@ ECSrlResult RCSrl::hasDSDLPlaySign( FILE *fp ) } return (ECSrlResult::NOERROR); } + +// +// SDKバージョンを取得する +// +ECSrlResult RCSrl::searchSDKVersion( FILE *fp ) +{ + const u8 pattern[8] = {0x21, 0x06, 0xc0, 0xde, 0xde, 0xc0, 0x06, 0x21}; + System::Collections::Generic::List ^list; + this->hSDKList = gcnew System::Collections::Generic::List; + this->hSDKList->Clear(); + + list = MasterEditorTWL::patternMatch( fp, pattern , 8 ); + if( list == nullptr ) + { + System::Diagnostics::Debug::WriteLine( "no list" ); + return ECSrlResult::ERROR_SDK; + } + for each( u32 item in list ) + { + // マジックコードのオフセットの手前4バイトがSDKバージョン + if( item >= 4 ) + { + u32 offset; + u32 sdkcode; + + offset = item - 4; + fseek( fp, offset, SEEK_SET ); + if( 4 != fread( (void*)&sdkcode, 1, 4, fp ) ) + { + return ECSrlResult::ERROR_SDK; + } + + // 解読 + System::Byte major = (System::Byte)(0xff & (sdkcode >> 24)); + System::Byte minor = (System::Byte)(0xff & (sdkcode >> 16)); + System::UInt16 relstep = (System::UInt16)(0xffff & sdkcode); + System::String ^str = nullptr; + str += (major.ToString() + "." + minor.ToString() + " "); + + // RELSTEPの解釈 + // PR1=10100 PR2=10200 ... + // RC1=20100 RC2=20200 ... + // RELEASE=30000 + System::UInt16 patch = relstep; + while( patch > 10000 ) + { + patch -= 10000; + } + patch = patch / 100; + switch( relstep / 10000 ) + { + case 1: str += ("PR " + patch.ToString()); break; + case 2: str += ("RC " + patch.ToString()); break; + case 3: str += ("RELEASE " + patch.ToString()); break; + default: break; + } + this->hSDKList->Add( str ); + //System::Diagnostics::Debug::WriteLine( "SDK " + str ); + } + } + return ECSrlResult::NOERROR; +} diff --git a/build/tools/MasterEditorTWL/MasterEditorTWL/srl.h b/build/tools/MasterEditorTWL/MasterEditorTWL/srl.h index 853385ee..46cab881 100644 --- a/build/tools/MasterEditorTWL/MasterEditorTWL/srl.h +++ b/build/tools/MasterEditorTWL/MasterEditorTWL/srl.h @@ -29,6 +29,8 @@ namespace MasterEditorTWL ERROR_SIGN_DECRYPT, // CRC算出でのエラー ERROR_SIGN_CRC, + // SDKバージョン取得でのエラー + ERROR_SDK, }; // ------------------------------------------------------------------- @@ -123,6 +125,9 @@ namespace MasterEditorTWL //property System::Boolean ^hRegionChina; //property System::Boolean ^hRegionKorea; + // SDKバージョンリスト + property System::Collections::Generic::List ^hSDKList; + // constructor and destructor public: RCSrl(); @@ -152,7 +157,10 @@ namespace MasterEditorTWL // SRLバイナリから特殊な設定を調べる ECSrlResult hasDSDLPlaySign( FILE *fp ); // DSダウンロード署名がSRLに格納されているか調べる - // @arg [in] 入力ファイルのFP (->SRL読み込み時に実行されるべき) + // @arg [in] 入力ファイルのFP (->SRL読み込み時に実行されるべき)] + + // SRLバイナリ中のSDKバージョンを取得する + ECSrlResult searchSDKVersion( FILE *fp ); }; // end of ref class RCSrl diff --git a/build/tools/MasterEditorTWL/MasterEditorTWL/utility.cpp b/build/tools/MasterEditorTWL/MasterEditorTWL/utility.cpp index 84b1d5c6..58ad6f92 100644 --- a/build/tools/MasterEditorTWL/MasterEditorTWL/utility.cpp +++ b/build/tools/MasterEditorTWL/MasterEditorTWL/utility.cpp @@ -279,4 +279,152 @@ System::String^ MasterEditorTWL::transRatingToString( System::Byte ogn, System:: } return str; +} // MasterEditorTWL::transRatingToString + +// +// バイト列に特定のパターンが含まれるかどうかマッチングする +// +// @arg [in] テキスト +// [in] テキストの長さ +// [in] パターン +// [in] パターンの長さ +// [in] テキストの終端まで調べた時点でテキストが途中までマッチしていた場合を成功とみなすか +// +// @ret マッチしたテキストのオフセットをリストで返す。 +// +System::Collections::Generic::List^ MasterEditorTWL::patternMatch( + const u8 *text, const u32 textLen, const u8 *pattern, const u32 patternLen, const System::Boolean enableLast ) +{ + // ひとまずシンプルな方法で実装する + u32 first; + u32 len; + System::Collections::Generic::List ^list = gcnew System::Collections::Generic::List(); + list->Clear(); + + // パターンを1文字ずつずらしながらマッチング + for( first=0; first < textLen; first++ ) + { + len = (patternLen < (textLen-first))?patternLen:(textLen-first); // 最後のほうは途中までしかマッチングしない + if( memcmp( text+first, pattern, len ) == 0 ) + { + if( (enableLast == true) ) + { + list->Add( first ); + } + else if( len == patternLen ) // 完全一致しないとダメ + { + list->Add( first ); + } + } + } + return list; +} // MasterEditorTWL::patternMatch + +// +// ファイルにバイト列のパターンが含まれるかどうかマッチングする +// +// @arg [in] マッチ対象となるファイルポインタ +// @arg [in] パターン +// @arg [in] パターンの長さ(PATTERN_MATCH_LEN_MAX以下でなければならない) +// +// @ret マッチしたテキストのオフセットをリストで返す。 +// 最後までマッチした場合のみ成功したとみなす。 +// +#define PATTERN_MATCH_LEN_MAX (10*1024) +System::Collections::Generic::List^ MasterEditorTWL::patternMatch( FILE *fp, const u8 *pattern, const u32 patternLen ) +{ + u8 text[ 2 * PATTERN_MATCH_LEN_MAX ]; // バッファの切れ目を探索するため多めに読み込むので最大でパターンの2倍だけバッファが必要になる + u32 cur; + u32 filesize; + u32 len; + u32 extra; + System::Collections::Generic::List ^tmplist; + System::Collections::Generic::List ^list = gcnew System::Collections::Generic::List; + list->Clear(); + + if( patternLen > PATTERN_MATCH_LEN_MAX ) + return nullptr; + + fseek( fp, 0, SEEK_END ); + filesize = ftell( fp ); + + cur = 0; + while( cur < filesize ) + { + // バッファの切れ目を調べたいため実際には(パターンの長さ-1)だけ多めにリードする + len = ((filesize - cur) < PATTERN_MATCH_LEN_MAX)?(filesize - cur):PATTERN_MATCH_LEN_MAX; + extra = (len < PATTERN_MATCH_LEN_MAX)?0:(patternLen-1); + fseek( fp, cur, SEEK_SET ); + if( (len + extra) != fread( text, 1, len + extra, fp ) ) + { + return nullptr; + } + + // テキスト終端に途中までマッチングしたときは失敗とみなす + tmplist = MasterEditorTWL::patternMatch( text, len+extra, pattern, patternLen, false ); + if( tmplist != nullptr ) + { + for each( u32 tmpval in tmplist ) + { + list->Add( tmpval + cur ); // 実際のオフセットはファイルオフセットを加えた値 + } + } + + // 次のSEEK位置:多めにリードしたはずらす + cur += len; + } + return list; } + +void MasterEditorTWL::debugPatternMatch( System::String ^filename ) +{ + FILE *fp = NULL; + u32 i; + const u8 pattern[8] = {0x21, 0x06, 0xc0, 0xde, 0xde, 0xc0, 0x06, 0x21}; + System::Collections::Generic::List ^list; + const char *pchFilename = + (const char*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi( filename ).ToPointer(); + + // ファイルを開いてROMヘッダのみ読み出す + if( fopen_s( &fp, pchFilename, "rb" ) != NULL ) + { + System::Diagnostics::Debug::WriteLine( "f_open failed" ); + return; + } + + list = MasterEditorTWL::patternMatch( fp, pattern , 8 ); + fclose( fp ); + + i=0; + if( list == nullptr ) + { + System::Diagnostics::Debug::WriteLine( "no list" ); + return; + } + for each( u32 item in list ) + { + System::Diagnostics::Debug::WriteLine( "item " + i.ToString() + " = 0x" + item.ToString("X") ); + i++; + } + + //u8 buf[ 512 ]; + //u32 i; + //u8 pattern[8] = {0xfe, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; + //System::Collections::Generic::List ^list; + + //for( i=0; i < 512; i++ ) + //{ + // buf[i] = i % 256; + //} + + //list = MasterEditorTWL::patternMatch( buf, 512, pattern, 8, true ); + + //i = 0; + //System::Diagnostics::Debug::WriteLine( "pattern match" ); + //for each( u32 item in list ) + //{ + // System::Diagnostics::Debug::WriteLine( "item " + i + " = " + item ); + // i++; + //} +} + \ No newline at end of file diff --git a/build/tools/MasterEditorTWL/MasterEditorTWL/utility.h b/build/tools/MasterEditorTWL/MasterEditorTWL/utility.h index 626b39f2..3e952b06 100644 --- a/build/tools/MasterEditorTWL/MasterEditorTWL/utility.h +++ b/build/tools/MasterEditorTWL/MasterEditorTWL/utility.h @@ -3,6 +3,8 @@ // 共用ライブラリ・クラスの宣言 #include +#include +#include namespace MasterEditorTWL { @@ -42,4 +44,32 @@ namespace MasterEditorTWL // System::String^ transRatingToString( System::Byte ogn, System::Boolean enable, System::Byte rating, System::Boolean english ); + // + // バイト列に特定のパターンが含まれるかどうかマッチングする + // + // @arg [in] テキスト + // [in] テキストの長さ + // [in] パターン + // [in] パターンの長さ + // [in] テキストの終端まで調べた時点でテキストが途中までマッチしていた場合を成功とみなすか + // + // @ret マッチしたテキストのインデックスをリストで返す。 + // + System::Collections::Generic::List^ patternMatch( + const u8 *text, const u32 textLen, const u8 *pattern, const u32 patternLen, const System::Boolean enableLast ); + + // + // ファイルにバイト列のパターンが含まれるかどうかマッチングする + // + // @arg [in] マッチ対象となるファイルポインタ + // @arg [in] パターン + // @arg [in] パターンの長さ + // + // @ret マッチしたテキストのインデックスをリストで返す。 + // 最後までマッチした場合のみ成功したとみなす。 + // + System::Collections::Generic::List^ patternMatch( FILE *fp, const u8 *pattern, const u32 patternLen ); + + void debugPatternMatch( System::String ^filename ); + } // end of namespace MasterEditorTWL