diff --git a/build/tools/MasterEditorTWL/MasterEditorTWL.ncb b/build/tools/MasterEditorTWL/MasterEditorTWL.ncb index aa075b08..3fa85b4f 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 bfb3df58..5f0cbd28 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 6abff88e..7960e606 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/srl.cpp b/build/tools/MasterEditorTWL/MasterEditorTWL/srl.cpp index 2c83b651..6582106d 100644 --- a/build/tools/MasterEditorTWL/MasterEditorTWL/srl.cpp +++ b/build/tools/MasterEditorTWL/MasterEditorTWL/srl.cpp @@ -370,14 +370,11 @@ ECSrlResult RCSrl::setRomHeader(void) // // ヘッダのCRCを算出 // -#define HEADER_CRC16_INIT_VALUE (0xffff) -#define HEADER_CALC_CRC16_SIZE (0x15e) -ECSrlResult RCSrl::calcRomHeaderCRC(void) +static u16 calcCRC( const u16 start, const u8 *data, const int allsize ) { u16 r1; - u16 total = HEADER_CRC16_INIT_VALUE; - int size = HEADER_CALC_CRC16_SIZE; - const u8 *data = (u8*)this->pRomHeader; + u16 total = start; + int size = allsize; // CRCテーブルは固定 const u16 CRC16Table[16] = @@ -403,9 +400,13 @@ ECSrlResult RCSrl::calcRomHeaderCRC(void) data++; } + return total; +} // calcRomHeaderCRCCore() +ECSrlResult RCSrl::calcRomHeaderCRC(void) +{ // ROMヘッダのCRC領域を上書き - this->pRomHeader->s.header_crc16 = total; + this->pRomHeader->s.header_crc16 = calcCRC( CRC16_INIT_VALUE, (u8*)this->pRomHeader, CALC_CRC16_SIZE ); return (ECSrlResult::NOERROR); } // ECSrlResult RCSrl::calcRomHeaderCRC(void) @@ -617,8 +618,246 @@ ECSrlResult RCSrl::mrc( FILE *fp ) this->hErrorList->Clear(); this->hWarnList->Clear(); + ECSrlResult result; + result = this->mrcNTR( fp ); + if( result != ECSrlResult::NOERROR ) + { + return result; + } + result = this->mrcTWL( fp ); + if( result != ECSrlResult::NOERROR ) + { + return result; + } //this->hErrorList->Add( gcnew RCMRCError( "テスト", 0x01, 0xfe, "テスト要因", "test", "reason", false ) ); //this->hWarnList->Add( gcnew RCMRCError( "テスト2", 0x01, 0xfe, "テスト要因2", "test2", "reason2", false ) ); return ECSrlResult::NOERROR; } + +// NTR互換MRC +ECSrlResult RCSrl::mrcNTR( FILE *fp ) +{ + System::Int32 i; + + // ROMヘッダのチェック + + // 文字コードチェック + for( i=0; i < TITLE_NAME_MAX; i++ ) + { + char c = this->pRomHeader->s.title_name[i]; + if( ((c < 0x20) || (0x5f < c)) && (c != 0x00) ) + { + this->hErrorList->Add( gcnew RCMRCError( + "ソフトタイトル", 0x0, 0xb, "使用不可のASCIIコードが使用されています。", + "Game Title", "Unusable ASCII code is used.", false ) ); + } + } + for( i=0; i < GAME_CODE_MAX; i++ ) + { + char c = this->pRomHeader->s.game_code[i]; + if( (c < 0x20) || (0x5f < c) ) + { + this->hErrorList->Add( gcnew RCMRCError( + "イニシャルコード", 0xc, 0xf, "使用不可のASCIIコードが使用されています。", + "Game Code", "Unusable ASCII code is used.", false ) ); + } + } + if( memcmp( this->pRomHeader->s.game_code, "NTRJ", GAME_CODE_MAX ) == 0 ) + { + this->hErrorList->Add( gcnew RCMRCError( + "イニシャルコード", 0xc, 0xf, "SDKデフォルトのコード(NTRJ)が使用されています。", + "Game Code", "SDK default code(NTRJ) is used.", false ) ); + } + for( i=0; i < MAKER_CODE_MAX; i++ ) + { + char c = this->pRomHeader->s.maker_code[i]; + if( (c < 0x20) || (0x5f < c) ) + { + this->hErrorList->Add( gcnew RCMRCError( + "メーカーコード", 0x10, 0x11, "使用不可のASCIIコードが使用されています。", + "Maker Code", "Unusable ASCII code is used.", false ) ); + } + } + + // 値チェック + if( this->pRomHeader->s.rom_type != 0x00 ) + { + this->hErrorList->Add( gcnew RCMRCError( + "デバイスタイプ", 0x13, 0x13, "不正な値です。00hを設定してください。", + "Device Type", "Invalid data. Please set 00h.", false ) ); + } + fseek( fp, 0, SEEK_END ); + u32 filesize = ftell(fp); // 実ファイルサイズ(単位Mbit) + u32 romsize = 1 << (this->pRomHeader->s.rom_size); // ROM容量 + if( (romsize*1024*1024/8) < filesize ) + { + this->hErrorList->Add( gcnew RCMRCError( + "デバイス容量", 0x14, 0x14, "実ファイルサイズよりも小さい値が指定されています。", + "Device Capacity", "Setting data is less than the actual file size.", false ) ); + } + else if( filesize < (romsize*1024*1024/8) ) + { + this->hWarnList->Add( gcnew RCMRCError( // 警告 + "デバイス容量", 0x14, 0x14, "実ファイルサイズに比べて無駄のある値が設定されています。", + "Device Capacity", "Setting data is larger than the actual file size.", false ) ); + } + if( (filesize % 2) != 0 ) + { + this->hErrorList->Add( gcnew RCMRCError( + "実ファイルサイズ", METWL_ERRLIST_NORANGE, METWL_ERRLIST_NORANGE, "中途半端な値です。通常では2のべき乗の値です。", + "Actual File Size", "Invalid size. This size is usually power of 2.", false ) ); + } + u8 romver = this->pRomHeader->s.rom_version; + if( ((romver < 0x00) || (0x09 < romver)) && (romver != 0xE0) ) + { + this->hErrorList->Add( gcnew RCMRCError( + "リマスターバージョン", 0x1e, 0x1e, "不正な値です。正式版では01h-09hのいずれかの値、事前版ではE0hです。", + "Release Ver.", "Invalid data. Please set either one of 01h-09h(Regular ver.), or E0h(Preliminary ver.)", false ) ); + } + if( this->pRomHeader->s.warning_no_spec_rom_speed != 0 ) + { + this->hErrorList->Add( gcnew RCMRCError( + "諸フラグ", 0x1f, 0x1f, "rsfファイルでROMSpeedTypeが設定されていません。", + "Setting Flags", "In a RSF file, the item \"ROMSpeedType\" is not set.", false ) ); + } + if( this->pRomHeader->s.banner_offset == 0 ) + { + this->hErrorList->Add( gcnew RCMRCError( + "バナーオフセット", 0x68, 0x6b, "バナーデータが設定されていません。", + "Banner Offset.", "Banner data is not set.", false ) ); + } + if( this->pRomHeader->s.rom_valid_size == 0 ) + { + this->hErrorList->Add( gcnew RCMRCError( + "ROM実効サイズ", 0x80, 0x83, "値が設定されていません。", + "ROM Valid Size.", "Data is not set.", false ) ); + } + + // CRC + u16 crc; + // セキュア領域 + { + // セキュア領域はROMヘッダ外 + u8 *secures; + s32 secure_size = SECURE_AREA_END - this->pRomHeader->s.main_rom_offset; + if (secure_size > SECURE_AREA_SIZE) + { + secure_size = SECURE_AREA_SIZE; + } + if (secure_size <= 0) + { + this->hErrorList->Add( gcnew RCMRCError( + "セキュア領域CRC", 0x15e, 0x15f, "セキュア領域のアドレス指定が不正です。", + "Secure Area CRC.", "Illegal address of secure area.", false ) ); + } + secures = new u8[secure_size]; // never return if not allocated + fseek( fp, (u32)this->pRomHeader->s.main_rom_offset, SEEK_SET ); + if( secure_size != fread( secures, 1, secure_size, fp ) ) + { + delete []secures; + return ECSrlResult::ERROR_FILE_READ; + } + crc = calcCRC(CRC16_INIT_VALUE, (u8 *)secures, secure_size); + delete []secures; + if( crc != this->pRomHeader->s.secure_area_crc16 ) + { + this->hErrorList->Add( gcnew RCMRCError( + "セキュア領域CRC", 0x07c, 0x07d, "計算結果と一致しません。セキュア領域が改ざんされた可能性があります。", + "Secure Area CRC.", "Calclated CRC is different from Registered one.", false ) ); + } + } + + // ロゴ領域 + crc = 0xcf56; + if( crc != this->pRomHeader->s.nintendo_logo_crc16 ) + { + this->hErrorList->Add( gcnew RCMRCError( + "キャラクターデータCRC", 0x15c, 0x15d, "計算結果と一致しません。キャラクターデータが改ざんされた可能性があります。", + "Charactor Data CRC.", "Calclated CRC is different from Registered one.", false ) ); + } + + // ヘッダCRC + crc = calcCRC( CRC16_INIT_VALUE, (u8*)this->pRomHeader, CALC_CRC16_SIZE ); + if( crc != this->pRomHeader->s.header_crc16 ) + { + this->hErrorList->Add( gcnew RCMRCError( + "ROMヘッダCRC", 0x15e, 0x15f, "計算結果と一致しません。ROMヘッダが改ざんされた可能性があります。", + "ROM Header CRC.", "Calclated CRC is different from Registered one.", false ) ); + } + + // 予約領域 + for( i=0; i < 8; i++ ) + { + if( this->pRomHeader->s.ctrl_reserved_B[i] != 0 ) + { + this->hErrorList->Add( gcnew RCMRCError( + "ROM情報予約領域", 0x078, 0x07f, "不正な値が含まれています。この領域をすべて0で埋めてください。", + "Reserved Area for ROM Info.", "Invalid data is included. Please set 0 into this area.", false ) ); + } + } + for( i=0; i < 32; i++ ) + { + if( this->pRomHeader->s.reserved_C[i] != 0 ) + { + this->hErrorList->Add( gcnew RCMRCError( + "予約領域C", 0x078, 0x07f, "不正な値が含まれています。この領域をすべて0で埋めてください。", + "Reserved Area C", "Invalid data is included. Please set 0 into this area.", false ) ); + } + } + + // ROMヘッダ以外の領域のチェック (ファイルから適宜リードする) + + // システムコールライブラリ + u8 syscall[32]; + u32 offset = this->pRomHeader->s.main_rom_offset; + fseek( fp, offset, SEEK_SET ); + if( 32 != fread( syscall, 1, 32, fp ) ) + { + return ECSrlResult::ERROR_FILE_READ; + } + for( i=0; i < 32; i++ ) + { + if( syscall[i] != 0x00 ) + break; + } + if( i == 32 ) // 全部0 + { + this->hErrorList->Add( gcnew RCMRCError( + "システムコールライブラリ", METWL_ERRLIST_NORANGE, METWL_ERRLIST_NORANGE, "SDKデフォルトです。", + "System-Call Library", "This Library is SDK default one.", false ) ); + } + + return ECSrlResult::NOERROR; +} // mrcNTR() + +ECSrlResult RCSrl::mrcTWL( FILE *fp ) +{ + System::Int32 i; + + // ROMヘッダのチェック + + // 値チェック + u32 romsize = 1 << (this->pRomHeader->s.rom_size); // ROM容量 + if( (romsize < METWL_ROMSIZE_MIN) || (METWL_ROMSIZE_MAX < romsize) ) + { + this->hErrorList->Add( gcnew RCMRCError( + "デバイス容量", 0x14, 0x14, "指定可能な容量ではありません。", + "Device Capacity", "Invalid capacity.", false ) ); + } + + // 予約領域 + for( i=0; i < 7; i++ ) + { + if( this->pRomHeader->s.reserved_A[i] != 0 ) + { + this->hErrorList->Add( gcnew RCMRCError( + "予約領域A", 0x015, 0x01b, "不正な値が含まれています。この領域をすべて0で埋めてください。", + "Reserved Area A", "Invalid data is included. Please set 0 into this area.", false ) ); + } + } + + // ROMヘッダ以外の領域のチェック + + return ECSrlResult::NOERROR; +} \ No newline at end of file diff --git a/build/tools/MasterEditorTWL/MasterEditorTWL/srl.h b/build/tools/MasterEditorTWL/MasterEditorTWL/srl.h index dace2ac1..61a82b32 100644 --- a/build/tools/MasterEditorTWL/MasterEditorTWL/srl.h +++ b/build/tools/MasterEditorTWL/MasterEditorTWL/srl.h @@ -6,6 +6,11 @@ #include #include +// 宣言 +#define METWL_ERRLIST_NORANGE 0 // エラーのアドレス範囲を指定しないことを表す特別な値 +#define METWL_ROMSIZE_MIN 256 // 最小のデバイス容量 256Mbit +#define METWL_ROMSIZE_MAX 4096 // 最大の.. 4Gbit + namespace MasterEditorTWL { // ------------------------------------------------------------------- @@ -305,8 +310,8 @@ namespace MasterEditorTWL // MRC(Master ROM Checker)機能 ECSrlResult mrc( FILE *fp ); - //ECSrlResult mrcNTR( FILE *fp ); - //ECSrlResult mrcTWL( FILE *fp ); + ECSrlResult mrcNTR( FILE *fp ); + ECSrlResult mrcTWL( FILE *fp ); }; // end of ref class RCSrl