srlの改竄検出コマンドラインツールを追加

git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlToolsRED@557 7061adef-622a-194b-ae81-725974e89856
This commit is contained in:
n1481 2011-05-13 05:09:53 +00:00
parent 3788fbc745
commit 18fa074d21
12 changed files with 1630 additions and 0 deletions

View File

@ -0,0 +1,15 @@
例)
./tamperdetector.exe --g ./srl/GENUINE_AAAA.srl --m ./srl/MAGICON_AAAA.srl
効果)
ヘッダ改竄状況、ファイル改竄状況の順に表示されます。
オフセットやサイズが改竄されている場合
双方のsrlファイル上でチェック対象のファイルが存在しているアドレスが
 異なるケース)にも対応しています。
サイズが改竄されている場合は小さいほうのサイズでチェックされます。
最後に srlファイル中の BMPファイルを全て PC上のカレントパスにエクスポートします。

View File

@ -0,0 +1,110 @@
/*---------------------------------------------------------------------------*
Project: TwlSDK - tools - makebanner
File: banner.h
Copyright 2003-2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
*---------------------------------------------------------------------------*/
#ifndef TWL_OS_COMMON_BANNER_H_
#define TWL_OS_COMMON_BANNER_H_
// define data---------------------------------------------
#define BANNER_IMAGE_SIZE (32 * 32 / (8/4))
#define BANNER_PLTT_SIZE (16 * 2)
#define BANNER_LANG_LENGTH 128
#define BANNER_LANG_SIZE (BANNER_LANG_LENGTH * 2)
#define BANNER_VER_NTR_MIN 1 // NTRバナーver.MIN.
#define BANNER_VER_NTR_MAX 3 // NTRバナーver.MAX.(smaller than UCHAR_MAX)
#define BANNER_VER_TWL_MIN 3 // TWLバナーver.MIN.
#define BANNER_VER_TWL_MAX 3 // TWLバナーver.MAX.(smaller than UCHAR_MAX)
#define BANNER_CHINESE_SUPPORT_VER 2 // 中国語サポートver.
#define BANNER_KOREAN_SUPPORT_VER 3 // 韓国語サポートver.
#define BANNER_LANG_NUM_RSV 8 // 言語予約領域数
#define BANNER_ANIME_PATTERN_NUM 8 // バナーアニメパターン数
#define BANNER_ANIME_CONTROL_INFO_NUM 64 // バナーアニメコントロール情報数
typedef enum {
BANNER_PRIO_JAPANESE = 0,
BANNER_PRIO_ENGLISH,
BANNER_PRIO_FRENCH,
BANNER_PRIO_GERMAN,
BANNER_PRIO_ITALIAN,
BANNER_PRIO_SPANISH,
BANNER_PRIO_CHINESE,
BANNER_PRIO_KOREAN,
BANNER_LANG_NUM,
BANNER_LANG_NUM_V1 = BANNER_PRIO_CHINESE,
BANNER_LANG_NUM_V2 = BANNER_PRIO_KOREAN - BANNER_PRIO_CHINESE,
BANNER_LANG_NUM_V3 = BANNER_LANG_NUM - BANNER_PRIO_KOREAN
}BannerLanguagePriorityIdx;
// プラットフォームコード
typedef enum {
BANNER_PLATFORM_NTR = 0,
BANNER_PLATFORM_TWL = 1,
BANNER_PLATFORM_MAX = 2
}BannerPlatformCode;
// バナーヘッダ
typedef struct {
u8 version;
u8 platform; // 上記BannerPlatformCodeで指定
u16 crc16_v1;
u16 crc16_v2;
u16 crc16_v3;
u16 crc16_anime;
u8 reserved_B[ 22 ];
}BannerHeader;
// バナーver.1 ボディ
typedef struct {
u8 image[ BANNER_IMAGE_SIZE ];
u8 pltt[ BANNER_PLTT_SIZE ];
u16 gameName[ BANNER_LANG_NUM_V1 ][ BANNER_LANG_LENGTH ];
}BannerFileV1;
// バナーver.2 ボディ追加分
typedef struct {
u16 gameName[ BANNER_LANG_NUM_V2 ][ BANNER_LANG_LENGTH ];
}BannerFileV2;
// バナーver.3 ボディ追加分
typedef struct {
u16 gameName[ BANNER_LANG_NUM_V3 ][ BANNER_LANG_LENGTH ];
}BannerFileV3;
// バナーgameName 言語拡張予約領域
typedef struct {
u16 gameName[ BANNER_LANG_NUM_RSV ][ BANNER_LANG_LENGTH ];
}BannerFileRsv;
// NTRバナーファイル構造体
typedef struct {
BannerHeader h;
BannerFileV1 v1;
BannerFileV2 v2;
BannerFileV3 v3;
}NTRBannerFile;
#endif //TWL_OS_COMMON_BANNER_H_

View File

@ -0,0 +1,446 @@
#include <string.h>
#include "checker.h"
#include "nitro_romheader.h"
extern Entry gEntry;
extern Entry mEntry;
void Checker::Initialize( FILE* myGfp, FILE* myMfp, void* myGbuf, void* myMbuf, u32 size)
{
gfp = myGfp;
mfp = myMfp;
gBuf = myGbuf;
mBuf = myMbuf;
buffer_size = size;
gEntry.Initialize();
mEntry.Initialize();
}
bool Checker::LoadHeader( void* gHeaderBuf, void* mHeaderBuf)
{
size_t readed;
fseek( gfp, 0, SEEK_SET);
readed = fread( gHeaderBuf, sizeof(RomHeader), 1, gfp);
if( readed == 1)
{
fseek( mfp, 0, SEEK_SET);
readed = fread( mHeaderBuf, sizeof(RomHeader), 1, mfp);
if( readed == sizeof(RomHeader))
{
return true;
}
}
return false;
}
bool Checker::Diff( u32 g_offset, u32 g_size, u32 m_offset, u32 m_size, bool isDataOnly, PrintLevel print_enable)
{
long nowgfp, nowmfp;
int result = 0;
u32 check_size, rest_size;
int i, loop_num;
bool function_result = true;
check_size = (g_size < m_size)? g_size : m_size;
rest_size = check_size;
if( !isDataOnly)
{
/* 指定アドレスとサイズのチェック */
if( g_offset == m_offset)
{
if( (print_enable)&&(print_enable < PRINT_LEVEL_2)) {
printf( " offset:0x%x改竄されていない\n", g_offset);
}
}
else
{
function_result = false;
if( print_enable) {
printf( " offset:0x%x ---> offset:0x%x改竄されている\n", g_offset, m_offset);
}
}
if( g_size == m_size)
{
if( (print_enable)&&(print_enable < PRINT_LEVEL_2)) {
printf( " size:0x%x改竄されていない\n", g_size);
}
}
else
{
function_result = false;
if( print_enable) {
printf( " size:0x%x ---> size:0x%x改竄されている\n", g_size, m_size);
}
}
}
bool filled = true;
int totalResult = 0;
int j;
nowgfp = ftell( gfp);
nowmfp = ftell( mfp);
/* メモリ内容のチェック(サイズが異なる場合は小さいサイズで) */
fseek( gfp, g_offset, SEEK_SET);
fseek( mfp, m_offset, SEEK_SET);
if( rest_size > buffer_size)
{
loop_num = (rest_size / buffer_size);
for( i=0; i<loop_num; i++)
{
fread( gBuf, buffer_size, 1, gfp);
fread( mBuf, buffer_size, 1, mfp);
result = memcmp( gBuf, mBuf, buffer_size);
if( result != 0)
{
totalResult = 1;
}
if( filled) // FILLチェック
{
for( j=0; j<buffer_size; j++)
{
if( *((u8*)mBuf + j) != *((u8*)mBuf))
{
// printf( ".%d, %d, 0x%x, 0x%x\n", i, j, *((u8*)mBuf+j), *((u8*)mBuf));
filled = false;
}
}
}
}
rest_size = (rest_size % buffer_size);
}
if( rest_size)
{
fread( gBuf, rest_size, 1, gfp);
fread( mBuf, rest_size, 1, mfp);
result = memcmp( gBuf, mBuf, rest_size);
if( result != 0)
{
totalResult = 1;
}
if( filled) // FILLチェック
{
for( j=0; j<(int)rest_size; j++)
{
if( *((u8*)mBuf + j) != *((u8*)mBuf))
{
// printf( "..%d, %d, 0x%x, 0x%x\n", i, j, *((u8*)mBuf+j), *((u8*)mBuf));
filled = false;
}
}
}
}
/* メモリ内容チェック結果 */
if( result == 0)
{
if( (print_enable)&&(print_enable < PRINT_LEVEL_2)) {
printf( " data:(改竄されていない)\n");
}
}
else
{
function_result = false;
if( filled)
{
if( print_enable) {
printf( " data:0x%xでフィルされている\n", *((u8*)mBuf));
}
}
else
{
if( print_enable) {
printf( " data:(改竄されている)\n");
}
}
}
// ファイルポインタを戻す
fseek( gfp, nowgfp, SEEK_SET);
fseek( mfp, nowmfp, SEEK_SET);
return function_result;
}
void Checker::AnalyzeBanner( RomHeader* gHeaderBuf, RomHeader* mHeaderBuf)
{
BannerHeader gBannerHeader;
BannerHeader mBannerHeader;
u32 banner_size[3] = {
sizeof( BannerFileV1),
sizeof( BannerFileV1) + sizeof( BannerFileV2),
sizeof( BannerFileV1) + sizeof( BannerFileV2) + sizeof( BannerFileV3),
};
fseek( gfp, (u32)(gHeaderBuf->banner_offset), SEEK_SET);
fseek( mfp, (u32)(mHeaderBuf->banner_offset), SEEK_SET);
fread( &gBannerHeader, sizeof(BannerHeader), 1, gfp);
fread( &mBannerHeader, sizeof(BannerHeader), 1, mfp);
printf( "------- Banner Header -------\n");
Diff( (u32)(gHeaderBuf->banner_offset), sizeof(BannerHeader),
(u32)(mHeaderBuf->banner_offset), sizeof(BannerHeader),
false, PRINT_LEVEL_1);
if( (((gBannerHeader.version) < 1) || ((gBannerHeader.version) > 3)) ||
(((mBannerHeader.version) < 1) || ((mBannerHeader.version) > 3)))
{
printf( " invalid banner version!\n");
return;
}
printf( "------- Banner Body -------\n");
Diff( (u32)(gHeaderBuf->banner_offset) + sizeof(BannerHeader), banner_size[gBannerHeader.version],
(u32)(mHeaderBuf->banner_offset) + sizeof(BannerHeader), banner_size[mBannerHeader.version],
false, PRINT_LEVEL_1);
}
void Checker::AnalyzeFNT( RomHeader* headerBuf, FILE* fp, Entry* entry, PrintLevel print_enable)
{
int i;
ROM_FNTDir currentDir;
MyDirEntry tmpDirEntry;
MyDirEntry* pDirEntry;
// ルートディレクトリの情報を読む
fseek( fp, (u32)(headerBuf->fnt_offset), SEEK_SET);
fread( &currentDir, sizeof(ROM_FNTDir), 1, fp);
// ディレクトリテーブル全体を読む
fseek( fp, (u32)(headerBuf->fnt_offset), SEEK_SET);
fread( &fntBuf, sizeof(ROM_FNTDir) * currentDir.parent_id, 1, fp);
// ルートディレクトリのparent_idは総ディレクトリ数を表す
for( i=0; i<currentDir.parent_id; i++)
{
entry->InitializeEntry( &tmpDirEntry);
if( i == 0)
{
if( print_enable) {
printf( "------- dir_id : 0xf000 (root) -------\n");
}
tmpDirEntry.self_id = 0xF000;
}
else
{
if( print_enable) {
printf( "------- dir_id : 0x%x (child dir of 0x%x) -------\n", (0xF000 + i), fntBuf[i].parent_id);
}
tmpDirEntry.self_id = (0xF000 + i);
tmpDirEntry.parent_id = fntBuf[i].parent_id;
}
if( !entry->FindDirEntry( tmpDirEntry.self_id))
{ // 見つからなかったら追加
pDirEntry = (MyDirEntry*)malloc( sizeof(MyDirEntry));
entry->CopyEntry( pDirEntry, &tmpDirEntry);
entry->addDirEntry( pDirEntry);
}
FindEntry( fntBuf[i].entry_start,
fntBuf[i].entry_file_id,
headerBuf, fp, entry, tmpDirEntry.self_id,
print_enable);
}
}
void Checker::FindEntry( u32 fnt_offset, u16 entry_id, RomHeader* headerBuf, FILE* fp, Entry* entry, u16 parent_id, PrintLevel print_enable)
{
EntryInfo entryInfo;
char entryNames[FILE_NAME_LENGTH];
u16 dir_id;
MyDirEntry* dirEntry;
MyFileEntry* fileEntry;
fseek( fp, (u32)(headerBuf->fnt_offset) + fnt_offset, SEEK_SET);
while( 1)
{
fread( &entryInfo, sizeof(char), 1, fp);
if( (entryInfo.entry_type == 0) && (entryInfo.entry_name_length == 0)) // 終端チェック
{
break;
}
fread( entryNames, entryInfo.entry_name_length, 1, fp);
entryNames[entryInfo.entry_name_length] = '\0';
if( entryInfo.entry_type == 0) // ファイル
{
if( print_enable) {
printf( "- %s(file_id:0x%d)\n", entryNames, entry_id);
}
/* パス解析用 */
fileEntry = (MyFileEntry*)malloc( sizeof(MyFileEntry));
entry->InitializeEntry( fileEntry);
fileEntry->self_id = entry_id;
fileEntry->parent_id = parent_id;
entry->SetName( fileEntry, entryNames, entryInfo.entry_name_length);
entry->addFileEntry( fileEntry);
FindAllocation( entry_id, headerBuf, fp, entry, print_enable);
entry_id++;
}
else // ディレクトリ
{
fread( &dir_id, sizeof(u16), 1, fp);
if( print_enable) {
printf( "- [%s](dir_id:0x%x)\n", entryNames, dir_id);
}
/* パス解析用 */
dirEntry = entry->FindDirEntry( dir_id);
if( !dirEntry)
{ // 見つからなかったら追加
dirEntry = (MyDirEntry*)malloc( sizeof(MyDirEntry));
entry->InitializeEntry( dirEntry);
dirEntry->self_id = dir_id;
dirEntry->parent_id = parent_id;
entry->addDirEntry( dirEntry);
}
entry->SetName( dirEntry, entryNames, entryInfo.entry_name_length);
}
}
}
void Checker::FindAllocation( u16 entry_id, RomHeader* headerBuf, FILE* fp, Entry* entry, PrintLevel print_enable)
{
ROM_FAT currentRomFat;
long nowfp;
nowfp = ftell( fp);
fseek( fp,
(u32)(headerBuf->fat_offset) + (sizeof(ROM_FAT) * entry_id),
SEEK_SET);
fread( &currentRomFat, sizeof(ROM_FAT), 1, fp);
if( print_enable) {
printf( " fat top:0x%x, bottom:0x%x, len:0x%x\n",
(u32)(currentRomFat.top), (u32)(currentRomFat.bottom),
(u32)(currentRomFat.bottom) - (u32)(currentRomFat.top));
}
Diff( (u32)(currentRomFat.top), (u32)(currentRomFat.bottom) - (u32)(currentRomFat.top),
(u32)(currentRomFat.top), (u32)(currentRomFat.bottom) - (u32)(currentRomFat.top),
true, print_enable);
/* パス解析用 */
MyFileEntry* fileEntry = entry->FindFileEntry( entry_id);
fileEntry->top = (u32)(currentRomFat.top);
fileEntry->bottom = (u32)(currentRomFat.bottom);
// ファイルポインタを戻す
fseek( fp, nowfp, SEEK_SET);
}
/* ROM内のBMPファイルを全て切り出して出力する */
#define BMP_BUFFER_SIZE (512*1024)
u32 tmpBuf[BMP_BUFFER_SIZE / 4];
void Checker::ExportGenuineBmpFiles( Entry* gEntry, PrintLevel print_enable)
{
int i;
MyFileEntry *currentEntry = gEntry->fileEntry;
MyFileEntry *hisEntry;
// u32* tmpBuf = (u32*)malloc( BMP_BUFFER_SIZE);
u32 file_size, rest_size;
int loop_num;
FILE* fp;
while( currentEntry)
{
if( currentEntry->name_length > 4)
{
if( memcmp( &currentEntry->name[currentEntry->name_length - 4], ".bmp", 4) == 0)
{
file_size = (currentEntry->bottom - currentEntry->top);
rest_size = file_size;
loop_num = file_size / BMP_BUFFER_SIZE;
fp = fopen( currentEntry->name, "w");
fseek( gfp, currentEntry->top, SEEK_SET);
if( rest_size > BMP_BUFFER_SIZE)
{
for( i=0; i<loop_num; i++)
{
fread( tmpBuf, BMP_BUFFER_SIZE, 1, gfp);
fwrite( tmpBuf, BMP_BUFFER_SIZE, 1, fp);
}
rest_size = (rest_size % BMP_BUFFER_SIZE);
}
if( rest_size)
{
fread( tmpBuf, rest_size, 1, gfp);
fwrite( tmpBuf, rest_size, 1, fp);
}
fclose( fp);
}
}
if( print_enable) {
printf( "- %s exported.\n", currentEntry->full_path_name);
}
currentEntry = (MyFileEntry*)(currentEntry->next);
};
// free( tmpBuf);
}
/* ディレクトリとファイルをチェックする */
void Checker::CheckAllEntries( Entry* gEntry, Entry* mEntry)
{
{
MyDirEntry *currentEntry = gEntry->dirEntry;
MyDirEntry *hisEntry;
printf( "------- directory check -------\n");
while( currentEntry)
{
printf( "- %s", currentEntry->full_path_name);
hisEntry = mEntry->FindDirEntry( currentEntry->full_path_name);
if( hisEntry)
{
printf( "\n");
}
else
{
printf( " --->(存在していない)\n");
}
currentEntry = (MyDirEntry*)(currentEntry->next);
}
}
MyFileEntry *currentEntry = gEntry->fileEntry;
MyFileEntry *hisEntry;
printf( "------- file check -------\n");
while( currentEntry)
{
printf( "- %s", currentEntry->full_path_name);
hisEntry = mEntry->FindFileEntry( currentEntry->full_path_name);
if( hisEntry)
{
printf( "\n");
if( Diff( currentEntry->top, (currentEntry->bottom - currentEntry->top),
hisEntry->top, (hisEntry->bottom - hisEntry->top),
false, PRINT_LEVEL_1) == false)
{
printf( "\n");
}
}
else
{
printf( " --->(存在していない)\n");
}
currentEntry = (MyFileEntry*)(currentEntry->next);
}
}
void Checker::Finalize( void)
{
}

View File

@ -0,0 +1,64 @@
#ifndef CHECKER_H_
#define CHECKER_H_
#include <stdio.h>
#include <stdlib.h>
#include "types.h"
#include "nitro_romheader.h"
#include "banner.h"
#include "entry.h"
typedef struct
{
u8 entry_name_length:7; // ファイル名の長さ (0-127)
u8 entry_type :1; // ファイルエントリの場合は 0
} EntryInfo;
typedef enum
{
PRINT_LEVEL_0 = 0,
PRINT_LEVEL_1,
PRINT_LEVEL_2
} PrintLevel;
class Checker
{
private:
bool initialized;
FILE* gfp;
FILE* mfp;
void* gBuf;
void* mBuf;
u32 buffer_size;
ROM_FNTDir fntBuf[4096];
void* dirTableBuf;
public:
void Initialize( FILE* myGfp, FILE* myMfp, void* myGbuf, void* myMbuf, u32 size);
/* ヘッダを読むだけ */
bool LoadHeader( void* gHeaderBuf, void* mHeaderBuf);
/* ROMの特定領域に差がないかどうか調べる */
bool Diff( u32 g_offset, u32 g_size, u32 m_offset, u32 m_size, bool isDataOnly, PrintLevel print_enable);
void Finalize( void);
/* ROMのバナー領域に対して Diff をかける */
void AnalyzeBanner( RomHeader* gHeaderBuf, RomHeader* mHeaderBuf);
/* FNT と FAT を解析して、各ファイルに対して Diff をかける */
void AnalyzeFNT( RomHeader* headerBuf, FILE* fp, Entry* entry, PrintLevel print_enable);
void FindEntry( u32 fnt_offset, u16 entry_id, RomHeader* headerBuf, FILE* fp, Entry* entry, u16 parent_id, PrintLevel print_enable);
void FindAllocation( u16 entry_id, RomHeader* headerBuf, FILE* fp, Entry* entry, PrintLevel print_enable);
void CheckAllEntries( Entry* gEntry, Entry* mEntry);
/* ROM内のBMPファイルを全て切り出して出力する */
void ExportGenuineBmpFiles( Entry* gEntry, PrintLevel print_enable);
};
#endif

View File

@ -0,0 +1,305 @@
#include <string.h>
#include "entry.h"
#include "nitro_romheader.h"
//void Entry::Initialize( void)
void Entry::Initialize( void)
{
dirEntry = NULL;
fileEntry = NULL;
}
void Entry::InitializeEntry( MyDirEntry* myDirEntry)
{
myDirEntry->name = NULL;
myDirEntry->full_path_name = NULL;
myDirEntry->name_length = 0;
myDirEntry->full_path_name_length = 0;
myDirEntry->self_id = 0xFFFF;
myDirEntry->parent_id = 0;
myDirEntry->parent = NULL;
myDirEntry->next = NULL;
}
void Entry::InitializeEntry( MyFileEntry* myFileEntry)
{
myFileEntry->name = NULL;
myFileEntry->full_path_name = NULL;
myFileEntry->name_length = 0;
myFileEntry->full_path_name_length = 0;
myFileEntry->top = 0;
myFileEntry->bottom = 0;
myFileEntry->self_id = 0xFFFF;
myFileEntry->parent_id = 0;
myFileEntry->parent = NULL;
myFileEntry->next = NULL;
}
void Entry::CopyEntry( MyDirEntry* dest, MyDirEntry* src)
{
memcpy( dest, src, sizeof(MyFileEntry));
}
void Entry::SetName( MyDirEntry* myDirEntry, char* fname, u16 len)
{
myDirEntry->name = (char*)malloc( sizeof(MyDirEntry));
memset( myDirEntry->name, 0, len+1);
memcpy( myDirEntry->name, fname, len);
myDirEntry->name_length = len;
}
void Entry::SetName( MyFileEntry* myFileEntry, char* fname, u16 len)
{
myFileEntry->name = (char*)malloc( FILE_NAME_LENGTH);
memset( myFileEntry->name, 0, len+1);
memcpy( myFileEntry->name, fname, len);
myFileEntry->name_length = len;
}
void Entry::addDirEntry( MyDirEntry* myDirEntry)
{
MyDirEntry *currentEntry = dirEntry;
if( !currentEntry)
{
dirEntry = myDirEntry;
return;
}
while( currentEntry->next)
{
currentEntry = (MyDirEntry*)(currentEntry->next);
}
currentEntry->next = myDirEntry;
myDirEntry->next = NULL;
}
void Entry::addFileEntry( MyFileEntry* myFileEntry)
{
MyFileEntry *currentEntry = fileEntry;
if( !currentEntry)
{
fileEntry = myFileEntry;
return;
}
while( currentEntry->next)
{
currentEntry = (MyFileEntry*)(currentEntry->next);
}
currentEntry->next = myFileEntry;
myFileEntry->next = NULL;
}
MyDirEntry* Entry::FindDirEntry( u16 id)
{
MyDirEntry *currentEntry = dirEntry;
while( currentEntry)
{
if( currentEntry->self_id == id)
{
return currentEntry;
}
// printf( "%s, 0x%x, 0x%x\n", __FUNCTION__, currentEntry->self_id, id);
currentEntry = (MyDirEntry*)(currentEntry->next);
}
return NULL;
}
MyFileEntry* Entry::FindFileEntry( u16 id)
{
MyFileEntry *currentEntry = fileEntry;
while( currentEntry)
{
if( currentEntry->self_id == id)
{
return currentEntry;
}
// printf( "%s, 0x%x, 0x%x\n", __FUNCTION__, currentEntry->self_id, id);
currentEntry = (MyFileEntry*)(currentEntry->next);
}
return NULL;
}
MyDirEntry* Entry::FindDirEntry( char* my_full_path_name)
{
MyDirEntry *currentEntry = dirEntry;
while( currentEntry)
{
if( strcmp( currentEntry->full_path_name, my_full_path_name) == 0)
{
return currentEntry;
}
currentEntry = (MyDirEntry*)(currentEntry->next);
}
return NULL;
}
MyFileEntry* Entry::FindFileEntry( char* my_full_path_name)
{
MyFileEntry *currentEntry = fileEntry;
while( currentEntry)
{
if( strcmp( currentEntry->full_path_name, my_full_path_name) == 0)
{
return currentEntry;
}
currentEntry = (MyFileEntry*)(currentEntry->next);
}
return NULL;
}
void Entry::AutoSetFullPath( void)
{
MyDirEntry *currentDirEntry = dirEntry;
while( currentDirEntry)
{
SetFullPath( currentDirEntry);
currentDirEntry = (MyDirEntry*)(currentDirEntry->next);
}
MyFileEntry *currentFileEntry = fileEntry;
while( currentFileEntry)
{
SetFullPath( currentFileEntry);
currentFileEntry = (MyFileEntry*)(currentFileEntry->next);
}
}
void Entry::SetFullPath( MyDirEntry *targetDirEntry)
{
char tmp_name[256];
u16 total_length;
MyDirEntry *currentDirEntry = targetDirEntry;
total_length = 0;
tmp_name[255] = '\0';
while( currentDirEntry)
{
total_length += (currentDirEntry->name_length);
memcpy( &(tmp_name[255 - total_length]), currentDirEntry->name, currentDirEntry->name_length);
if( currentDirEntry->self_id != 0xF000) // rootディレクトリでなければ
{
total_length++; // '/'のぶん
tmp_name[255 - total_length] = '/';
}
currentDirEntry = (MyDirEntry*)(currentDirEntry->parent);
}
targetDirEntry->full_path_name = (char*)malloc( total_length + 1);
targetDirEntry->full_path_name_length = total_length;
memset( targetDirEntry->full_path_name, 0, total_length + 1);
memcpy( targetDirEntry->full_path_name, &(tmp_name[255 - total_length]), total_length);
}
void Entry::SetFullPath( MyFileEntry *targetFileEntry)
{
char tmp_name[256];
u16 total_length;
MyFileEntry *currentFileEntry = targetFileEntry;
MyDirEntry *parentDirEntry;
total_length = 0;
tmp_name[255] = '\0';
{
total_length += (currentFileEntry->name_length);
memcpy( &(tmp_name[255 - total_length]), currentFileEntry->name, currentFileEntry->name_length);
total_length++; // '/'のぶん
tmp_name[255 - total_length] = '/';
parentDirEntry = (MyDirEntry*)(currentFileEntry->parent);
if( parentDirEntry)
{
total_length += parentDirEntry->full_path_name_length;
memcpy( &(tmp_name[255 - total_length]), parentDirEntry->full_path_name, parentDirEntry->full_path_name_length);
}
}
targetFileEntry->full_path_name = (char*)malloc( total_length + 1);
memset( targetFileEntry->full_path_name, 0, total_length + 1);
memcpy( targetFileEntry->full_path_name, &(tmp_name[255 - total_length]), total_length);
}
/* parent リンクを繋げる */
void Entry::FollowParent( void)
{
MyDirEntry *currentDirEntry = dirEntry;
while( currentDirEntry)
{
currentDirEntry->parent = FindDirEntry( currentDirEntry->parent_id);
currentDirEntry = (MyDirEntry*)(currentDirEntry->next);
}
MyFileEntry *currentFileEntry = fileEntry;
while( currentFileEntry)
{
currentFileEntry->parent = FindDirEntry( currentFileEntry->parent_id);
// printf( "%s, 0x%x, 0x%x\n", __FUNCTION__, currentFileEntry->parent_id, (u32)currentFileEntry->parent);
currentFileEntry = (MyFileEntry*)(currentFileEntry->next);
}
}
void Entry::PrintAllDirEntry( void)
{
MyDirEntry *currentEntry = dirEntry;
printf( "------- all directories are -------\n");
while( currentEntry)
{
// printf( "directory : %s\n", currentEntry->name);
printf( "fullpath : %s\n", currentEntry->full_path_name);
// printf( "id : 0x%x\n", currentEntry->self_id);
// printf( "parent id : 0x%x\n", currentEntry->parent_id);
currentEntry = (MyDirEntry*)(currentEntry->next);
}
}
void Entry::PrintAllFileEntry( void)
{
MyFileEntry *currentEntry = fileEntry;
printf( "------- all files are -------\n");
while( currentEntry)
{
// printf( "file : %s\n", currentEntry->name);
printf( "fullpath : %s\n", currentEntry->full_path_name);
// printf( "id : 0x%x\n", currentEntry->self_id);
// printf( "parent id : 0x%x\n", currentEntry->parent_id);
currentEntry = (MyFileEntry*)(currentEntry->next);
}
}
/*
void Entry::CheckAllFiles( Checker* checker, MyFileEntry *anotherFileEntry)
{
MyFileEntry *currentEntry = fileEntry;
MyFileEntry *hisEntry;
while( currentEntry)
{
printf( "- %s", currentEntry->full_path_name);
hisEntry = FindFileEntry( currentEntry->full_path_name);
if( hisEntry)
{
printf( " --->(存在している)\n");
checker.Diff( currentEntry->top, (currentEntry->bottom - currentEntry->top),
hisEntry->top, (hisEntry->bottom - hisEntry->top),
false, true);
}
else
{
printf( " --->(存在していない)\n");
}
}
}*/
/* フルパスをセットする事前にFollowParent()を済ませておくことが必要) */
void Entry::Finalize()
{
}

View File

@ -0,0 +1,83 @@
#ifndef ENTRY_H_
#define ENTRY_H_
#include <stdio.h>
#include <stdlib.h>
#include "types.h"
#include "nitro_romheader.h"
#include "banner.h"
//#include "checker.h"
typedef struct
{
char* name;
char* full_path_name;
u8 name_length;
u8 full_path_name_length;
u16 self_id;
u16 parent_id;
void* parent;
void* next;
} MyDirEntry;
typedef struct
{
char* name;
char* full_path_name;
u8 name_length;
u8 full_path_name_length;
u32 top;
u32 bottom;
u16 self_id;
u16 parent_id;
void* parent;
void* next;
} MyFileEntry;
class Entry
{
// private:
public:
MyDirEntry* dirEntry;
MyFileEntry* fileEntry;
public:
void Initialize( void);
void InitializeEntry( MyDirEntry* myDirEntry);
void InitializeEntry( MyFileEntry* myFileEntry);
void CopyEntry( MyDirEntry* dest, MyDirEntry* src);
void SetName( MyDirEntry* myDirEntry, char* fname, u16 len);
void SetName( MyFileEntry* myDirEntry, char* fname, u16 len);
void addDirEntry( MyDirEntry* myDirEntry);
void addFileEntry( MyFileEntry* myFileEntry);
MyDirEntry* FindDirEntry( u16 id);
MyFileEntry* FindFileEntry( u16 id);
MyDirEntry* FindDirEntry( char* my_full_path_name);
MyFileEntry* FindFileEntry( char* my_full_path_name);
/* parent リンクを繋げる */
void FollowParent( void);
/* フルパスをセットする */
void AutoSetFullPath( void);
void SetFullPath( MyDirEntry *targetDirEntry);
void SetFullPath( MyFileEntry *targetFileEntry);
void PrintAllDirEntry( void);
void PrintAllFileEntry( void);
// void CheckAllFiles( Checker* checker, MyFileEntry *anotherFileEntry);
void Finalize();
};
#endif

View File

@ -0,0 +1,168 @@
#include <stdio.h>
#include <stdlib.h>
#include "types.h"
#include "searcharg.h"
#include "nitro_romheader.h"
#include "checker.h"
extern char* output_fname;
extern char* genuine_fname;
extern char* magicon_fname;
#define BUFFER_SIZE (0x4000)
Entry gEntry;
Entry mEntry;
RomHeader gHeaderBuf;
RomHeader mHeaderBuf;
char gBuf[BUFFER_SIZE];
char mBuf[BUFFER_SIZE];
/*--- 型のビット数をチェック ---*/
bool int_bits(void)
{
int count = 0;
unsigned short usi = ~0U;
unsigned long uli = ~0U;
while (uli) {
if (uli & 1U) count++;
uli >>= 1;
}
if( count != 32)
{
printf("ERROR! unsigned long int : %d bits\n", count);
return false;
}
count = 0;
while (usi) {
if (usi & 1U) count++;
usi >>= 1;
}
if( count != 16)
{
printf("ERROR! unsigned short int : %d bits\n", count);
return false;
}
return true;
}
int main (int argc, char *argv[])
{
// 処理系の unsignedビット数が想定外ならエラー終了types.hを変更してビルドし直してください
if( !int_bits())
{
return 1;
}
SA_searchopt(argc, argv);
printf("[output_fname]%s\n", output_fname);
printf("[genuine_fname]%s\n", genuine_fname);
printf("[magicon_fname]%s\n", magicon_fname);
{
FILE* gfp;
FILE* mfp;
Checker checker;
gfp = fopen( genuine_fname, "r");
mfp = fopen( magicon_fname, "r");
checker.Initialize( gfp, mfp, gBuf, mBuf, BUFFER_SIZE);
checker.LoadHeader( &gHeaderBuf, &mHeaderBuf);
printf( "------------------\n");
printf( "Nitro Rom Header\n");
checker.Diff( 0, sizeof(RomHeader), 0, sizeof(RomHeader), false, PRINT_LEVEL_1);
printf( "------------------\n");
printf( "ARM9 Static Module\n");
checker.Diff( (u32)(gHeaderBuf.arm9.romAddr),
(u32)(gHeaderBuf.arm9.romSize),
(u32)(mHeaderBuf.arm9.romAddr),
(u32)(mHeaderBuf.arm9.romSize),
false, PRINT_LEVEL_1);
printf( "------------------\n");
printf( "ARM7 Static Module\n");
checker.Diff( (u32)(gHeaderBuf.arm7.romAddr),
(u32)(gHeaderBuf.arm7.romSize),
(u32)(mHeaderBuf.arm7.romAddr),
(u32)(mHeaderBuf.arm7.romSize),
false, PRINT_LEVEL_1);
printf( "------------------\n");
printf( "File Name Table\n");
checker.Diff( (u32)(gHeaderBuf.fnt_offset),
(u32)(gHeaderBuf.fnt_size),
(u32)(mHeaderBuf.fnt_offset),
(u32)(mHeaderBuf.fnt_size),
false, PRINT_LEVEL_1);
printf( "------------------\n");
printf( "File Allocation Table\n");
checker.Diff( (u32)(gHeaderBuf.fat_offset),
(u32)(gHeaderBuf.fat_size),
(u32)(mHeaderBuf.fat_offset),
(u32)(mHeaderBuf.fat_size),
false, PRINT_LEVEL_1);
printf( "------------------\n");
printf( "ARM9 Overlay Table\n");
checker.Diff( (u32)(gHeaderBuf.main_ovt_offset),
(u32)(gHeaderBuf.main_ovt_size),
(u32)(mHeaderBuf.main_ovt_offset),
(u32)(mHeaderBuf.main_ovt_size),
false, PRINT_LEVEL_1);
printf( "------------------\n");
printf( "ARM7 Overlay Table\n");
checker.Diff( (u32)(gHeaderBuf.sub_ovt_offset),
(u32)(gHeaderBuf.sub_ovt_size),
(u32)(mHeaderBuf.sub_ovt_offset),
(u32)(mHeaderBuf.sub_ovt_size),
false, PRINT_LEVEL_1);
printf( "------------------\n");
printf( "\nBanner\n");
checker.AnalyzeBanner( &gHeaderBuf, &mHeaderBuf);
printf( "\nFNT & FAT\n");
checker.AnalyzeFNT( &gHeaderBuf, gfp, &gEntry, PRINT_LEVEL_0);
gEntry.FollowParent();
gEntry.AutoSetFullPath();
checker.AnalyzeFNT( &mHeaderBuf, mfp, &mEntry, PRINT_LEVEL_0);
mEntry.FollowParent();
mEntry.AutoSetFullPath();
checker.CheckAllEntries( &gEntry, &mEntry);
checker.ExportGenuineBmpFiles( &gEntry, PRINT_LEVEL_0);
/*
gEntry.PrintAllDirEntry();
gEntry.PrintAllFileEntry();
mEntry.PrintAllDirEntry();
mEntry.PrintAllFileEntry();
*/
printf( "------------------\n");
// AnalyzeFNT( mHeaderBuf, mfp);
fclose( gfp);
fclose( mfp);
}
return 0;
}

View File

@ -0,0 +1,316 @@
/*---------------------------------------------------------------------------*
nitroeva3/card/rom_filesystem.h
*---------------------------------------------------------------------------*/
#ifndef NITROEVA3_CARD_ROM_FILESYSTEM_H_
#define NITROEVA3_CARD_ROM_FILESYSTEM_H_
#include "types.h"
/*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*/
#define FILE_NAME_LENGTH 128
// マスクROMのヘッダアドレスを獲得
#define GetRomHeaderAddr() ((RomHeader *)HW_ROM_HEADER_BUF)
// 共有ワーク領域のアドレス獲得
#define GetSharedWorkAddr() ((SharedWork *)HW_RED_RESERVED) // (HW_MAIN_MEM + 0x007ff800) maybe change later
#define ROM_FILE_MAIN_PROCESSOR 0
#define ROM_FILE_SUB_PROCESSOR 1
#define ROM_FILE_CARD 0
#define ROM_FILE_CARTRIDGE 1
/*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*/
// 共有ワーク構造体
typedef struct {
u32 nCardID; // NORMALカードID
u32 sCardID; // SECUREカードID
u16 cardHeaderCrc16; // カードヘッダCRC16
u16 cardSecureCrc16; // カードSECURE領域CRC16
s16 cardHeaderError; // カードヘッダエラー
} SharedWork;
/*---------------------------------------------------------------------------*
IDを取得するためのテーブル
*---------------------------------------------------------------------------*/
typedef struct
{
char entry_name[FILE_NAME_LENGTH]; // ファイル名 (終端 \0 は省く)
} ROM_FNT;
/*---------------------------------------------------------------------------*
IDと呼ばれる番号が割り振られ
IDと区別するためIDは0xF0000xFFFF
IDは0x00000xEFFF409661440
IDが0xF000IDには
ID 0xF000
*---------------------------------------------------------------------------*/
typedef struct
{
u32 entry_start; // エントリ名の検索位置(ファイル名テーブルの先頭位置からのオフセット)
u16 entry_file_id; // 先頭エントリのファイル ID
u16 parent_id; // 親ディレクトリの ID
} ROM_FNTDir;
/*---------------------------------------------------------------------------*
ROM_FNTStrFile, ROM_FNTStrDir
--> ROM_FNTStrFile
--> ROM_FNTStrDir
IDも連続
0
##########################################################################
()
/Nitro.ROM
/BQ.DAT
/image/APPLE.JPG
DIR-ID
--------------------------------------------------------------------------
0xF000 : entry_start = &(Nitro.ROM), entry_file_id = 0, parent_id = 2 ()
0xF001 : entry_start = &(APPLE.JPG), entry_file_id = 2, parent_id = 0xF000
--------------------------------------------------------------------------
FILE-ID
---( / )------------------------------------------------------
0 : entry_type = 0, entry_name_length = 9, entry_name = "Nitro.ROM"
1 : entry_type = 0, entry_name_length = 6, entry_name = "BQ.DAT"
: entry_type = 1, entry_name_length = 5, entry_name = "image" dir_id = 0xF001
x : entry_type = 0, entry_name_length = 0
---( /image/ )------------------------------------------------
2 : entry_type = 0, entry_name_length = 9, entry_name = "APPLE.JPG"
x : entry_type = 0, entry_name_length = 0
##########################################################################
*---------------------------------------------------------------------------*/
typedef struct
{
u8 entry_type :1; // ファイルエントリの場合は 0
u8 entry_name_length:7; // ファイル名の長さ (0-127)
char entry_name[FILE_NAME_LENGTH]; // ファイル名 (終端 \0 は省く)
} ROM_FNTStrFile;
typedef struct
{
u8 entry_type :1; // ディレクトリエントリの場合は 1
u8 entry_name_length:7; // ディレクトリ名の長さ (0-127)
char entry_name[FILE_NAME_LENGTH]; // ディレクトリ名 (終端 \0 は省く)
u8 dir_id_L; // ディレクトリ ID Low 8bit
u8 dir_id_H; // ディレクトリ ID High 8bit
} ROM_FNTStrDir;
/*---------------------------------------------------------------------------*
FAT :
IDと一致
romFatTable ROM_FAT型
romFat[5].top ID=5 ROMアドレス
使IDに対応するデータにはtop = bottom = 0
*---------------------------------------------------------------------------*/
typedef struct
{
void* top; // ファイルの先頭 ROM アドレス
void* bottom; // ファイルの最終 ROM アドレス
} ROM_FAT;
/*---------------------------------------------------------------------------*
nef
ID
IDはリンク処理時には仮の値が設定されているがmakeromにより実際の値となる
*---------------------------------------------------------------------------*/
typedef struct
{
u32 id; // オーバーレイ ID
void* ram_address; // ロード先頭位置
u32 ram_size; // ロードサイズ
u32 bss_size; // bss 領域サイズ
void* sinit_init; // static initializer 先頭アドレス
void* sinit_init_end; // static initializer 最終アドレス
u32 file_id; // オーバーレイファイルID
u32 rom_size; // オーバーレイファイルサイズ
} ROM_OVT;
/*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*/
typedef struct {
u8* rom_address; // 転送元 ROM アドレス
u8* entry_address; // 実行開始(エントリ)アドレス
u8* ram_address; // 転送先 RAM アドレス
s32 rom_size; // 転送 ROM サイズ
} ROM_ResidentModuleParam; // 常駐の ... resident
// ROMヘッダ・ブートパラメータ構造体 (オリジナルの定義)
typedef struct {
u8 *romAddr; // ROMアドレス
u8 *entryAddr; // エントリアドレス
u8 *ramAddr; // RAMアドレス
s32 romSize; // ROMサイズ
} BootUsrParam;
/*---------------------------------------------------------------------------*
ROMヘッダ構造体
*---------------------------------------------------------------------------*/
typedef struct {
//------------------------------------------------------------------------
// 0x000 System Reserved
//
char title_name[12]; // Soft title name
u32 game_code; // Game code
u16 maker_code; // Maker code
u8 machine_code; // Machine code
u8 rom_type; // Rom type
u8 rom_size; // Rom size
u8 reserved_A[9]; // System Reserved A ( Set ALL 0 )
u8 soft_version; // Soft version
u8 comp_arm9_boot_area:1; // Compress arm9 boot area
u8 comp_arm7_boot_area:1; // Compress arm7 boot area
u8 :0;
//------------------------------------------------------------------------
// 0x020 for Static modules (Section:B)
//
// ARM9
BootUsrParam arm9;
// ARM7
BootUsrParam arm7;
//------------------------------------------------------------------------
// 0x040 for File Name Table[FNT] (Section:C)
//
ROM_FNT* fnt_offset; // ROM offset
u32 fnt_size; // Table size
//------------------------------------------------------------------------
// 0x048 for File Allocation Table[FAT] (Section:E)
//
ROM_FAT* fat_offset; // ROM offset
u32 fat_size; // Table size
//------------------------------------------------------------------------
// 0x050 for Overlay Tables[OVT] (Section:D)
//
// ARM9
ROM_OVT* main_ovt_offset; // ROM offset
u32 main_ovt_size; // Table size
// ARM7
ROM_OVT* sub_ovt_offset; // ROM offset
u32 sub_ovt_size; // Table size
//------------------------------------------------------------------------
// 0x060 for ROM control parameter
u32 game_cmd_param; // Game command parameter
u32 secure_cmd_param; // Secure command parameter
u32 banner_offset; // Ctrl Reserved A (Set 0)
u16 secure_area_crc16; // Secure area CRC-16
u16 secure_cmd_latency; // Secure command latency ((param+2)*256 system cycles)
u8 ctrl_reserved_B[16]; // Ctrl Reserved B (Set 0)
//------------------------------------------------------------------------
// 0x080 - 0x0C0 System Reserved
u8 reserved_B[64]; // System Reserved B (Set 0)
//------------------------------------------------------------------------
// 0x0C0 for NINTENDO logo data
u8 nintendo_logo[0x9c]; // NINTENDO logo data
u16 nintendo_logo_crc16; // CRC-16
//------------------------------------------------------------------------
// 0x15E ROM header CRC-16
u16 header_crc16; // ROM header CRC-16
//------------------------------------------------------------------------
// 0x0160 - 0x0180 System Reserved
//
u8 reserved_C[32]; // Debugger Reserved (Set ALL 0)
} RomHeader;
/*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*/
/*
BOOL get_overlay_info(int card_or_cart, int main_or_sub, u32 id, ROM_OVT *ovt);
BOOL my_romfile_load_overlay_segment(int card_or_cart, int main_or_sub, u32 id);
void print_overlay_info(int main_or_sub, u32 id);
*/
#endif // NITROEVA3_CARD_ROM_FILESYSTEM_H_

View File

@ -0,0 +1,85 @@
/*---------------------------------------------------------------------------*
Project: TwlSDK - - makelst
File: searcharg.c
Copyright 2006-2009 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
*---------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include "searcharg.h"
char* output_fname = NULL;
char* genuine_fname = NULL;
char* magicon_fname = NULL;
void SA_Usage( void)
{
fprintf( stderr, "Analyzing Tool\n");
fprintf( stderr, "Usage: makelst [-o output-file] [--g genuine-srl-file] [--m magicon-srl-file]\n\n");
exit( 1);
}
/*ˆø<CB86>ð‰ð<E280B0>Í·é*/
void SA_searchopt( int argc, char* argv[])
{
int n;
struct option optionInfo[] = {
{ "genuine", required_argument, NULL, 'g'},
{ "magicon", required_argument, NULL, 'm'},
{ NULL, 0, NULL, 0}
};
if( argc <= 1) {
SA_Usage();
}
while( (n = getopt_long( argc, argv, "do:h", &optionInfo[0], NULL))
!= -1)
{
switch( n) {
case 'd':
// dbg_print_flag = 1;
break;
case 'o':
if( output_fname != NULL) {
fprintf( stderr, "ERROR! redefined output filename.\n");
SA_Usage();
}
output_fname = optarg;
break;
case 'g': // "--genuine"
if( genuine_fname != NULL) {
fprintf( stderr, "ERROR! redefined genuine filename.\n");
SA_Usage();
}
genuine_fname = optarg;
break;
case 'm': // "--magicon"
if( magicon_fname != NULL) {
fprintf( stderr, "ERROR! redefined magicon filename.\n");
SA_Usage();
}
magicon_fname = optarg;
break;
case 'h':
SA_Usage();
break;
default: // '?'
SA_Usage();
break;
}
}
}

View File

@ -0,0 +1,25 @@
/*---------------------------------------------------------------------------*
Project: TwlSDK - - makelst
File: searcharg.h
Copyright 2006-2008 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
*---------------------------------------------------------------------------*/
#ifndef __SEARCH_ARG__
#define __SEARCH_ARG__
/*ˆø<CB86>ð‰ð<E280B0>Í·é*/
void SA_searchopt( int argc, char* argv[]);
#endif /*__SEARCH_ARG__*/

Binary file not shown.

View File

@ -0,0 +1,13 @@
#ifndef NITRO_TYPES_H_
#define NITRO_TYPES_H_
typedef unsigned char u8;
typedef unsigned short int u16;
typedef unsigned long u32;
typedef signed short int s16;
typedef signed long s32;
#endif /*NITRO_TYPES_H_*/