From a5cbc2ae3b608b54f1b1ee0df3c85efc58090e3f Mon Sep 17 00:00:00 2001 From: nishikawa_takeshi Date: Fri, 17 Apr 2009 07:41:32 +0000 Subject: [PATCH] =?UTF-8?q?=E3=83=95=E3=82=A3=E3=83=B3=E3=82=AC=E3=83=BC?= =?UTF-8?q?=E3=83=97=E3=83=AA=E3=83=B3=E3=82=BF:CUI=E7=89=88=E3=82=82?= =?UTF-8?q?=E5=AE=9F=E8=A3=85=E3=80=82=E8=BF=BD=E5=8A=A0=E3=81=97=E5=BF=98?= =?UTF-8?q?=E3=82=8C=E3=81=A6=E3=81=84=E3=81=9F=E3=83=95=E3=82=A1=E3=82=A4?= =?UTF-8?q?=E3=83=AB=E3=82=92=E8=BF=BD=E5=8A=A0=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlToolsRED@261 7061adef-622a-194b-ae81-725974e89856 --- .../FingerPrinterTWL/FingerPrinterTWL.ncb | Bin 10546176 -> 10750976 bytes .../FingerPrinterTWL/FingerPrinterTWL.suo | Bin 33280 -> 32256 bytes .../FingerPrinterTWL/FingerPrinterTWL.cpp | 37 +++- .../FingerPrinterTWL/FingerPrinterTWL.vcproj | 4 + ...interTWL.vcproj.RED.nishikawa_takeshi.user | 4 +- .../FingerPrinterTWL/Form1.cpp | 39 ++-- .../FingerPrinterTWL/FingerPrinterTWL/Form1.h | 7 +- .../FingerPrinterTWL/FormAbout.cpp | 3 + .../FingerPrinterTWL/FormAbout.h | 156 ++++++++++++++ .../FingerPrinterTWL/FormAbout.resx | 120 +++++++++++ .../FingerPrinterTWL/FormCheck.cpp | 3 + .../FingerPrinterTWL/FormCheck.h | 197 ++++++++++++++++++ .../FingerPrinterTWL/FormCheck.resx | 120 +++++++++++ .../FingerPrinterTWL/fingerprint_console.cpp | 195 +++++++++++++++++ .../FingerPrinterTWL/fingerprint_util.h | 16 ++ .../FingerPrinterTWL/fingerprinter_util.cpp | 123 +++++++++-- 16 files changed, 983 insertions(+), 41 deletions(-) create mode 100644 build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormAbout.cpp create mode 100644 build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormAbout.h create mode 100644 build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormAbout.resx create mode 100644 build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormCheck.cpp create mode 100644 build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormCheck.h create mode 100644 build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormCheck.resx create mode 100644 build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/fingerprint_console.cpp diff --git a/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL.ncb b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL.ncb index 3345b57bcf579c613770c2c4d2cd71c5884e1d72..d071236f0c9e9da42e1affb1894cd3ef1beb820d 100644 GIT binary patch delta 35578 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 delta 37814 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 a?5j=KY_jq5%7s6hAs276{EycxjQI<6>wW+L delta 4567 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 swGo;uX~`S$L>p|susXw%zqa<;7drBy ^args ); + using namespace FingerPrinterTWL; [STAThreadAttribute] int main(array ^args) { - // コントロールが作成される前に、Windows XP ビジュアル効果を有効にします - Application::EnableVisualStyles(); - Application::SetCompatibleTextRenderingDefault(false); + // GUIモードかチェック + bool guimode = false; + for each( System::String ^arg in args ) + { + if( arg->StartsWith("-") && (arg->IndexOf('g') >= 0) ) + { + guimode = true; + } + } - // メイン ウィンドウを作成して、実行します - Application::Run(gcnew Form1()); + if( (args->Length == 0) || guimode ) + { + // コントロールが作成される前に、Windows XP ビジュアル効果を有効にします + Application::EnableVisualStyles(); + Application::SetCompatibleTextRenderingDefault(false); + + // メイン ウィンドウを作成して、実行します + Application::Run(gcnew Form1()); + } + else + { + try + { + fingerprintConsole( args ); + } + catch( System::Exception ^ex ) + { + System::Console::WriteLine(ex->Message); + return -1; + } + } return 0; } diff --git a/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FingerPrinterTWL.vcproj b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FingerPrinterTWL.vcproj index fce5c15..eb30221 100644 --- a/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FingerPrinterTWL.vcproj +++ b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FingerPrinterTWL.vcproj @@ -203,6 +203,10 @@ RelativePath=".\AssemblyInfo.cpp" > + + diff --git a/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FingerPrinterTWL.vcproj.RED.nishikawa_takeshi.user b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FingerPrinterTWL.vcproj.RED.nishikawa_takeshi.user index 7963a7f..58b35ae 100644 --- a/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FingerPrinterTWL.vcproj.RED.nishikawa_takeshi.user +++ b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FingerPrinterTWL.vcproj.RED.nishikawa_takeshi.user @@ -11,7 +11,7 @@ SRL."); + throw gcnew Exception("Failed to transform TAD => SRL."); } this->srlbin = ReadBin(tmp); System::IO::File::Delete(tmp); // 中間ファイルを削除する @@ -132,7 +132,7 @@ void Form1::commonSaveRom( System::String ^dstpath ) if( this->rTad->Checked && !(this->rh->s.titleID_Hi && TITLE_ID_MEDIA_MASK) ) { - throw gcnew Exception("Cannot make TAD file for software intended for Game Card."); + throw gcnew Exception("Cannot make TAD file from the software intended for Game Card."); } this->fingerprintRomHeader(); @@ -144,6 +144,7 @@ void Form1::commonSaveRom( System::String ^dstpath ) System::String ^tmp = ".\\tmp" + System::DateTime::Now.ToString("yyyyMMddHHmmss") + ".srl"; WriteBin( tmp, this->srlbin ); makeTad( maketad_path, tmp, dstpath ); + System::IO::File::Delete(tmp); } else { @@ -155,19 +156,11 @@ void Form1::commonSaveRom( System::String ^dstpath ) // ボタンが押されたときの処理 (catch文必須) // ------------------------------------------------------------------ -void Form1::procOpenRomButton( System::String ^path ) +void Form1::procOpenRomButton() { try { - System::String ^rompath = nullptr; - if( !path ) - { - rompath = OpenFileUsingDialog( this->prevDir, "rom format (*.srl;*.tad)|*.srl;*.tad|All files (*.*)|*.*" ); - } - else - { - rompath = System::String::Copy(path); - } + System::String ^rompath = OpenFileUsingDialog( this->prevDir, "rom format (*.srl;*.tad)|*.srl;*.tad|All files (*.*)|*.*" ); if( !rompath ) { return; @@ -177,10 +170,7 @@ void Form1::procOpenRomButton( System::String ^path ) this->tboxFile->SelectionStart = rompath->Length; // 入りきらないときに右端を表示する this->rSrl->Checked = true; this->rTad->Checked = false; - if( !path ) - { - this->prevDir = System::IO::Path::GetDirectoryName( rompath ); // あらかじめパスが指定されたときには更新しない - } + this->prevDir = System::IO::Path::GetDirectoryName( rompath ); // あらかじめパスが指定されたときには更新しない } catch( System::Exception ^ex ) { @@ -221,6 +211,23 @@ void Form1::procSaveRomButton() } } +void Form1::procDragDrop( System::String ^rompath ) +{ + try + { + this->commonOpenRom( rompath ); + this->tboxFile->Text = rompath; + this->tboxFile->SelectionStart = rompath->Length; // 入りきらないときに右端を表示する + this->rSrl->Checked = true; + this->rTad->Checked = false; + } + catch( System::Exception ^ex ) + { + this->tboxFile->Text = ""; // クリア + this->errMsg( ex->Message ); + } +} + void Form1::procAboutButton() { try diff --git a/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/Form1.h b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/Form1.h index 93e4503..4137ff8 100644 --- a/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/Form1.h +++ b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/Form1.h @@ -338,8 +338,9 @@ namespace FingerPrinterTWL { // ボタンが押されたときの処理(例外catchを入れること) private: - void procOpenRomButton( System::String ^path ); + void procOpenRomButton(); void procSaveRomButton(); + void procDragDrop( System::String ^rompath ); void procAboutButton(); // ダイアログ @@ -355,7 +356,7 @@ namespace FingerPrinterTWL { private: System::Void butFile_Click(System::Object^ sender, System::EventArgs^ e) { - this->procOpenRomButton(nullptr); + this->procOpenRomButton(); } private: System::Void butFP_Click(System::Object^ sender, System::EventArgs^ e) @@ -376,7 +377,7 @@ namespace FingerPrinterTWL { { array ^files = dynamic_cast< array ^>(e->Data->GetData( DataFormats::FileDrop ) ); String ^path = files[0]; - this->procOpenRomButton( path ); // ボタンが押されたときと同じ挙動 + this->procDragDrop( path ); } // 再びボタン private: diff --git a/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormAbout.cpp b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormAbout.cpp new file mode 100644 index 0000000..a202a0c --- /dev/null +++ b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormAbout.cpp @@ -0,0 +1,3 @@ +#include "StdAfx.h" +#include "FormAbout.h" + diff --git a/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormAbout.h b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormAbout.h new file mode 100644 index 0000000..d53f6ff --- /dev/null +++ b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormAbout.h @@ -0,0 +1,156 @@ +#pragma once + +using namespace System; +using namespace System::ComponentModel; +using namespace System::Collections; +using namespace System::Windows::Forms; +using namespace System::Data; +using namespace System::Drawing; + + +namespace FingerPrinterTWL { + + /// + /// FormAbout の概要 + /// + /// 警告: このクラスの名前を変更する場合、このクラスが依存するすべての .resx ファイルに関連付けられた + /// マネージ リソース コンパイラ ツールに対して 'Resource File Name' プロパティを + /// 変更する必要があります。この変更を行わないと、 + /// デザイナと、このフォームに関連付けられたローカライズ済みリソースとが、 + /// 正しく相互に利用できなくなります。 + /// + public ref class FormAbout : public System::Windows::Forms::Form + { + public: + FormAbout(void) + { + InitializeComponent(); + // + //TODO: ここにコンストラクタ コードを追加します + // + this->construct(); + } + + protected: + /// + /// 使用中のリソースをすべてクリーンアップします。 + /// + ~FormAbout() + { + if (components) + { + delete components; + } + } + private: System::Windows::Forms::Label^ lab; + protected: + private: System::Windows::Forms::Label^ labVersion; + private: System::Windows::Forms::Label^ label1; + private: System::Windows::Forms::TextBox^ tboxRemarks; + private: System::Windows::Forms::Button^ butOK; + + protected: + + private: + /// + /// 必要なデザイナ変数です。 + /// + System::ComponentModel::Container ^components; + +#pragma region Windows Form Designer generated code + /// + /// デザイナ サポートに必要なメソッドです。このメソッドの内容を + /// コード エディタで変更しないでください。 + /// + void InitializeComponent(void) + { + this->lab = (gcnew System::Windows::Forms::Label()); + this->labVersion = (gcnew System::Windows::Forms::Label()); + this->label1 = (gcnew System::Windows::Forms::Label()); + this->tboxRemarks = (gcnew System::Windows::Forms::TextBox()); + this->butOK = (gcnew System::Windows::Forms::Button()); + this->SuspendLayout(); + // + // lab + // + this->lab->AutoSize = true; + this->lab->Location = System::Drawing::Point(29, 25); + this->lab->Name = L"lab"; + this->lab->Size = System::Drawing::Size(96, 12); + this->lab->TabIndex = 0; + this->lab->Text = L"TWL Fingerprinter"; + // + // labVersion + // + this->labVersion->AutoSize = true; + this->labVersion->Location = System::Drawing::Point(29, 46); + this->labVersion->Name = L"labVersion"; + this->labVersion->Size = System::Drawing::Size(44, 12); + this->labVersion->TabIndex = 1; + this->labVersion->Text = L"Version"; + // + // label1 + // + this->label1->AutoSize = true; + this->label1->Location = System::Drawing::Point(29, 67); + this->label1->Name = L"label1"; + this->label1->Size = System::Drawing::Size(138, 12); + this->label1->TabIndex = 2; + this->label1->Text = L"(C)2009 Nintendo Co., Ltd."; + // + // tboxRemarks + // + this->tboxRemarks->BackColor = System::Drawing::SystemColors::MenuBar; + this->tboxRemarks->Location = System::Drawing::Point(23, 101); + this->tboxRemarks->Multiline = true; + this->tboxRemarks->Name = L"tboxRemarks"; + this->tboxRemarks->Size = System::Drawing::Size(238, 70); + this->tboxRemarks->TabIndex = 3; + // + // butOK + // + this->butOK->Location = System::Drawing::Point(103, 190); + this->butOK->Name = L"butOK"; + this->butOK->Size = System::Drawing::Size(75, 23); + this->butOK->TabIndex = 4; + this->butOK->Text = L"OK"; + this->butOK->UseVisualStyleBackColor = true; + this->butOK->Click += gcnew System::EventHandler(this, &FormAbout::butOK_Click); + // + // FormAbout + // + this->AutoScaleDimensions = System::Drawing::SizeF(6, 12); + this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; + this->ClientSize = System::Drawing::Size(292, 230); + this->Controls->Add(this->butOK); + this->Controls->Add(this->tboxRemarks); + this->Controls->Add(this->label1); + this->Controls->Add(this->labVersion); + this->Controls->Add(this->lab); + this->Name = L"FormAbout"; + this->Text = L"FormAbout"; + this->ResumeLayout(false); + this->PerformLayout(); + + } +#pragma endregion + + private: + void construct() + { + // バージョン情報 + System::Reflection::Assembly ^ass = System::Reflection::Assembly::GetEntryAssembly(); + System::Version ^ver = ass->GetName()->Version; + this->labVersion->Text = "Version " + ver->Major.ToString() + "." + ver->Minor.ToString(); + // OpenSSL ライセンス注意書き + this->tboxRemarks->Text = "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/)"; + this->tboxRemarks->SelectionStart = 0; + } + + private: + System::Void butOK_Click(System::Object^ sender, System::EventArgs^ e) + { + this->Close(); + } +}; +} diff --git a/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormAbout.resx b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormAbout.resx new file mode 100644 index 0000000..ff31a6d --- /dev/null +++ b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormAbout.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormCheck.cpp b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormCheck.cpp new file mode 100644 index 0000000..bd8e694 --- /dev/null +++ b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormCheck.cpp @@ -0,0 +1,3 @@ +#include "StdAfx.h" +#include "FormCheck.h" + diff --git a/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormCheck.h b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormCheck.h new file mode 100644 index 0000000..f9622e8 --- /dev/null +++ b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormCheck.h @@ -0,0 +1,197 @@ +#pragma once + +#include "fingerprint_util.h" + +using namespace System; +using namespace System::ComponentModel; +using namespace System::Collections; +using namespace System::Windows::Forms; +using namespace System::Data; +using namespace System::Drawing; + + +namespace FingerPrinterTWL { + + /// + /// FormCheck の概要 + /// + /// 警告: このクラスの名前を変更する場合、このクラスが依存するすべての .resx ファイルに関連付けられた + /// マネージ リソース コンパイラ ツールに対して 'Resource File Name' プロパティを + /// 変更する必要があります。この変更を行わないと、 + /// デザイナと、このフォームに関連付けられたローカライズ済みリソースとが、 + /// 正しく相互に利用できなくなります。 + /// + public ref class FormCheck : public System::Windows::Forms::Form + { + public: + FormCheck(void) + { + InitializeComponent(); + // + //TODO: ここにコンストラクタ コードを追加します + // + } + + protected: + /// + /// 使用中のリソースをすべてクリーンアップします。 + /// + ~FormCheck() + { + if (components) + { + delete components; + } + } + private: System::Windows::Forms::Label^ labMsg; + private: System::Windows::Forms::Label^ labWarning; + private: System::Windows::Forms::Label^ labAscii; + private: System::Windows::Forms::Label^ labHex; + private: System::Windows::Forms::TextBox^ tboxAscii; + private: System::Windows::Forms::TextBox^ tboxHex; + private: System::Windows::Forms::Button^ butOK; + + + + protected: + + + private: + /// + /// 必要なデザイナ変数です。 + /// + System::ComponentModel::Container ^components; + +#pragma region Windows Form Designer generated code + /// + /// デザイナ サポートに必要なメソッドです。このメソッドの内容を + /// コード エディタで変更しないでください。 + /// + void InitializeComponent(void) + { + this->labMsg = (gcnew System::Windows::Forms::Label()); + this->labWarning = (gcnew System::Windows::Forms::Label()); + this->labAscii = (gcnew System::Windows::Forms::Label()); + this->labHex = (gcnew System::Windows::Forms::Label()); + this->tboxAscii = (gcnew System::Windows::Forms::TextBox()); + this->tboxHex = (gcnew System::Windows::Forms::TextBox()); + this->butOK = (gcnew System::Windows::Forms::Button()); + this->SuspendLayout(); + // + // labMsg + // + this->labMsg->AutoSize = true; + this->labMsg->Location = System::Drawing::Point(21, 27); + this->labMsg->Name = L"labMsg"; + this->labMsg->Size = System::Drawing::Size(290, 12); + this->labMsg->TabIndex = 0; + this->labMsg->Text = L"The fingerprint has been registered in the ROM already."; + // + // labWarning + // + this->labWarning->AutoSize = true; + this->labWarning->Location = System::Drawing::Point(21, 47); + this->labWarning->Name = L"labWarning"; + this->labWarning->Size = System::Drawing::Size(261, 12); + this->labWarning->TabIndex = 1; + this->labWarning->Text = L"You can replace it with new one by re-registering."; + // + // labAscii + // + this->labAscii->AutoSize = true; + this->labAscii->Location = System::Drawing::Point(21, 96); + this->labAscii->Name = L"labAscii"; + this->labAscii->Size = System::Drawing::Size(94, 12); + this->labAscii->TabIndex = 2; + this->labAscii->Text = L"ASCII Characters"; + // + // labHex + // + this->labHex->AutoSize = true; + this->labHex->Location = System::Drawing::Point(21, 167); + this->labHex->Name = L"labHex"; + this->labHex->Size = System::Drawing::Size(119, 12); + this->labHex->TabIndex = 3; + this->labHex->Text = L"Hexadecimal Numbers"; + // + // tboxAscii + // + this->tboxAscii->Location = System::Drawing::Point(23, 111); + this->tboxAscii->Multiline = true; + this->tboxAscii->Name = L"tboxAscii"; + this->tboxAscii->ReadOnly = true; + this->tboxAscii->Size = System::Drawing::Size(288, 37); + this->tboxAscii->TabIndex = 4; + // + // tboxHex + // + this->tboxHex->Location = System::Drawing::Point(23, 182); + this->tboxHex->Multiline = true; + this->tboxHex->Name = L"tboxHex"; + this->tboxHex->ReadOnly = true; + this->tboxHex->Size = System::Drawing::Size(288, 37); + this->tboxHex->TabIndex = 5; + // + // butOK + // + this->butOK->Location = System::Drawing::Point(172, 257); + this->butOK->Name = L"butOK"; + this->butOK->Size = System::Drawing::Size(75, 23); + this->butOK->TabIndex = 6; + this->butOK->Text = L"OK"; + this->butOK->UseVisualStyleBackColor = true; + this->butOK->Click += gcnew System::EventHandler(this, &FormCheck::butOK_Click); + // + // FormCheck + // + this->AutoScaleDimensions = System::Drawing::SizeF(6, 12); + this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; + this->ClientSize = System::Drawing::Size(418, 296); + this->Controls->Add(this->butOK); + this->Controls->Add(this->tboxHex); + this->Controls->Add(this->tboxAscii); + this->Controls->Add(this->labHex); + this->Controls->Add(this->labAscii); + this->Controls->Add(this->labWarning); + this->Controls->Add(this->labMsg); + this->Name = L"FormCheck"; + this->Text = L"Fingerprint Checker"; + this->ResumeLayout(false); + this->PerformLayout(); + + } +#pragma endregion + + // ================================================================================ + // フィンガープリントの表示 + // ================================================================================ + public: + void displayFingerprint( unsigned char fingerprint[32] ) + { + cli::array ^bytes = gcnew cli::array(32); + int i; + for( i=0; i < 32; i++ ) + { + bytes[i] = fingerprint[i]; + } + this->displayFingerprint( bytes ); + } + void displayFingerprint( cli::array ^fingerprint ) + { + this->tboxAscii->Text = TransBytesToString( fingerprint ); + this->tboxHex->Text = TransBytesToHexString( fingerprint ); + + this->tboxAscii->SelectionStart = 0; + this->tboxHex->SelectionStart = 0; + } + + // ================================================================================ + // GUI処理 + // ================================================================================ + private: + System::Void butOK_Click(System::Object^ sender, System::EventArgs^ e) + { + this->Close(); + } +}; +} diff --git a/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormCheck.resx b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormCheck.resx new file mode 100644 index 0000000..ff31a6d --- /dev/null +++ b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/FormCheck.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/fingerprint_console.cpp b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/fingerprint_console.cpp new file mode 100644 index 0000000..09384f5 --- /dev/null +++ b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/fingerprint_console.cpp @@ -0,0 +1,195 @@ +#include "stdafx.h" +#include "fingerprint_util.h" +#include "MasterEditorTWL/split_tad.h" + +using namespace System; + +// +// usage +// +void usage() +{ + System::String ^msg = + "Usage:\n" + + "FingerprintTWL.exe input_rom output_rom [options]\n\n" + + "options:\n" + + "-a ASCII_CHARACTORS: register ASCII charactors as fingerprint.\n" + + "-b HEX_NUMBERS: regsiter hexadicimal charactors as fingerprint.\n" + + "-s : output the ROM as SRL format.\n" + + "-t : output the ROM as TAD format.\n" + + "-f : Force to overwrite the fingerprint to the already fingerprinted ROM.\n" + "-g : GUI mode. Other options are ignored.\n" + + "-h : display this usage.\n"; + System::Console::WriteLine( "{0}", msg ); +} + +// +// コンソール処理 +// +void fingerprintConsole( cli::array ^args ) +{ + System::String ^optarg; + char opt; + bool isAscii = false; + bool isTad = false; + bool isForce = false; + System::String ^fingerprint; + + while( (opt = getopt(args, "a:b:stfgh", optarg)) >= 0 ) + { + switch( opt ) + { + case 'a': + isAscii = true; + fingerprint = System::String::Copy(optarg); + break; + + case 'b': + isAscii = false; + fingerprint = System::String::Copy(optarg); + break; + + case 't': + isTad = true; + break; + + case 's': + isTad = false; + break; + + case 'f': + isForce = false; + break; + + case 'g': + return; + break; + + case 'h': + usage(); + return; + break; + + default: + throw gcnew System::Exception( "Arguments error." ); + break; + } + } + + if( args->Length < 2 ) + { + throw gcnew System::Exception( "Arguments error." ); + } + + // 入出力ファイルのパス + System::String ^srcpath = args[0]; + System::String ^dstpath = args[1]; + System::Console::WriteLine( "Input file: {0}", srcpath ); + System::Console::WriteLine( "Output file: {0}", dstpath ); + System::Console::WriteLine(); + + // SRLの読み込み + cli::array ^srlbin; + if( System::IO::Path::GetExtension(srcpath)->ToUpper()->Equals(".TAD") ) + { + // TADの場合 split_tad + System::Console::WriteLine( "*** Transform TAD => SRL ***" ); + System::String ^tmp = ".\\tmp" + System::DateTime::Now.ToString("yyyyMMddHHmmss") + ".srl"; + if( splitTad(srcpath, tmp) < 0 ) + { + throw gcnew System::Exception("Failed to transform TAD => SRL."); + } + srlbin = ReadBin(tmp); + System::IO::File::Delete(tmp); // 中間ファイルを削除する + } + else + { + srlbin = ReadBin(srcpath); + } + ROM_Header rh; + ExtractRomHeader( srlbin, &rh ); + + // fingerprint が埋め込まれていたら表示して上書き確認をする + bool isFingerprint = false; + int i; + for( i=0; i < 32; i++ ) + { + if( rh.s.reserved_C[i] != 0 ) + { + isFingerprint = true; + break; + } + } + if( isFingerprint ) + { + cli::array ^bytes = gcnew cli::array(32); + int i; + for( i=0; i < 32; i++ ) + { + bytes[i] = rh.s.reserved_C[i]; + } + + System::Console::WriteLine( "*** Check the fingerprint ***" ); + System::Console::WriteLine( "ASCII Charactors:" ); + System::Console::WriteLine( "{0}", TransBytesToString(bytes) ); + System::Console::WriteLine( "Hexadecimal Numbers:" ); + System::Console::WriteLine( "{0}", TransBytesToHexString(bytes) ); + System::Console::WriteLine(); + System::Console::WriteLine( "The fingerprint has already been registered in the ROM." ); + System::Console::WriteLine(); + + if( !isForce ) + { + System::Console::WriteLine( "Overwrite it? (y/n) > " ); + System::ConsoleKeyInfo ^key = System::Console::ReadKey(); + if( (key->KeyChar == 'y') || (key->KeyChar == 'Y') ) + { + System::Console::WriteLine( "Overwrite the fingerprint." ); + } + else + { + throw gcnew System::Exception( "Canceled." ); + } + } + } + + // fingerprint の埋め込み + System::Console::WriteLine( "*** Register the fingerprint ***" ); + cli::array ^bytes; + if( isAscii ) + { + System::Console::WriteLine( "ASCII Charactors:" ); + System::Console::WriteLine( "{0}", fingerprint ); + bytes = TransStringToBytes( fingerprint, 32 ); + } + else + { + bytes = TransHexStringToBytes( fingerprint, 32 ); + } + pin_ptr buf = &bytes[0]; // 解放の必要なし + memcpy( rh.s.reserved_C, buf, 32 ); + SignRomHeader( &rh ); // 署名 + System::Console::WriteLine( "Hexadecimal Numbers:" ); + System::Console::WriteLine( "{0}", TransBytesToHexString(bytes) ); + + // maketad + if( isTad ) + { + System::String ^bindir = System::IO::Path::GetDirectoryName( System::Reflection::Assembly::GetEntryAssembly()->Location ); + if( !bindir->EndsWith("\\") ) + { + bindir = bindir + "\\"; + } + System::String ^maketad_path = bindir + "maketad.exe"; + + System::Console::WriteLine( "*** Transform SRL => TAD ***" ); + System::String ^tmp = ".\\tmp" + System::DateTime::Now.ToString("yyyyMMddHHmmss") + ".srl"; + WriteBin( tmp, srlbin ); + makeTad( maketad_path, tmp, dstpath ); + System::IO::File::Delete(tmp); + } + else + { + WriteBin( dstpath, srlbin ); + } +} \ No newline at end of file diff --git a/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/fingerprint_util.h b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/fingerprint_util.h index 8ff7d48..e8dfbf5 100644 --- a/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/fingerprint_util.h +++ b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/fingerprint_util.h @@ -77,3 +77,19 @@ System::String^ SaveFileUsingDialog( System::String ^defdir, System::String ^fil // @arg [in] 入力SRLのパス // @arg [in] 出力SRLのパス void makeTad( System::String ^maketad_path, System::String ^srlpath, System::String ^tadpath ); + +// ---------------------------------------------------------------------- +// コンソール +// ---------------------------------------------------------------------- + +// getopt : 引数を解析してオプションが見つかったら1つ返す +// @arg [in/out] 引数 (オプションが見つかった場合削除されていく) +// @arg [in] オプション許可リスト +// @arg [out] オプション引数の格納場所 (ない場合 nullptrが入る) +// @ret 最初に見つかったオプション +char getopt( cli::array ^%args, System::String ^condition, System::String ^% optarg ); + +// args から特定の要素を削除 +// @arg [in] 引数 +// @arg [in] 削除する要素のインデックス +void shrinkArgs( cli::array ^%args, const int index ); diff --git a/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/fingerprinter_util.cpp b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/fingerprinter_util.cpp index 40ac61f..7e99868 100644 --- a/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/fingerprinter_util.cpp +++ b/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/fingerprinter_util.cpp @@ -7,6 +7,7 @@ #include #include #include +#include "fingerprint_util.h" using namespace MasterEditorTWL; @@ -27,7 +28,7 @@ cli::array^ ReadBin( System::String ^path ) { if( fopen_s( &fp, pch, "rb" ) != NULL ) { - ex = gcnew System::Exception( "Fail to open file:" + path ); + ex = gcnew System::Exception( "Failed to open file:" + path ); throw ex; } @@ -40,7 +41,7 @@ cli::array^ ReadBin( System::String ^path ) fseek( fp, 0, SEEK_SET ); if( fread( (void*)pbin, 1, size, fp ) != size ) { - ex = gcnew System::Exception( "Fail to read data from " + path ); + ex = gcnew System::Exception( "Failed to read data from " + path ); throw ex; } } @@ -68,7 +69,7 @@ void WriteBin( System::String ^path, cli::array ^bin ) { if( fopen_s( &fp, pch, "w+b" ) != NULL ) // 上書き・バイナリ { - ex = gcnew System::Exception( "Fail to open file:" + path ); + ex = gcnew System::Exception( "Failed to open file:" + path ); throw ex; } @@ -78,7 +79,7 @@ void WriteBin( System::String ^path, cli::array ^bin ) (void)fseek( fp, 0, SEEK_SET ); if( fwrite( (const void*)pbin, 1, size, fp ) != size ) { - ex = gcnew System::Exception( "Fail to write data to " + path ); + ex = gcnew System::Exception( "Failed to write data to " + path ); throw ex; } } @@ -105,13 +106,13 @@ void ReadRomHeader( System::String ^srlpath, ROM_Header *dstrh ) { if( fopen_s( &fp, pchFile, "rb" ) != NULL ) { - ex = gcnew System::Exception( "Fail to open file:" + srlpath ); + ex = gcnew System::Exception( "Failed to open file:" + srlpath ); throw ex; } fseek( fp, 0, SEEK_SET ); if( fread( (void*)dstrh, 1, sizeof(ROM_Header), fp ) != sizeof(ROM_Header) ) { - ex = gcnew System::Exception( "Fail to read data from " + srlpath ); + ex = gcnew System::Exception( "Failed to read data from " + srlpath ); throw ex; } } @@ -138,14 +139,14 @@ void WriteRomHeader( System::String ^srlpath, ROM_Header *srcrh ) { if( fopen_s( &fp, pchFile, "r+b" ) != NULL ) // 上書き・バイナリ { - ex = gcnew System::Exception( "Fail to open file:" + srlpath ); + ex = gcnew System::Exception( "Failed to open file:" + srlpath ); throw ex; } (void)fseek( fp, 0, SEEK_SET ); if( fwrite( (const void*)srcrh, 1, sizeof(ROM_Header), fp ) != sizeof(ROM_Header) ) { - ex = gcnew System::Exception( "Fail to write data to " + srlpath ); + ex = gcnew System::Exception( "Failed to write data to " + srlpath ); throw ex; } } @@ -202,12 +203,12 @@ void CopyFile( System::String ^srcpath, System::String ^dstpath ) { if( fopen_s( &ifp, pchSrcFile, "rb" ) != NULL ) { - ex = gcnew System::Exception( "Fail to open file:" + srcpath ); + ex = gcnew System::Exception( "Failed to open file:" + srcpath ); throw ex; } if( fopen_s( &ofp, pchDstFile, "wb" ) != NULL ) // 同名ファイルを削除して新規にライト・バイナリ { - ex = gcnew System::Exception( "Fail to open file:" + dstpath ); + ex = gcnew System::Exception( "Failed to open file:" + dstpath ); throw ex; } @@ -225,12 +226,12 @@ void CopyFile( System::String ^srcpath, System::String ^dstpath ) if( datasize != fread(buf, 1, datasize, ifp) ) { - ex = gcnew System::Exception( "Fail to read data from " + srcpath ); + ex = gcnew System::Exception( "Failed to read data from " + srcpath ); throw ex; } if( datasize != fwrite(buf, 1, datasize, ofp) ) { - ex = gcnew System::Exception( "Fail to write data to " + dstpath ); + ex = gcnew System::Exception( "Failed to write data to " + dstpath ); throw ex; } size -= datasize; @@ -307,7 +308,7 @@ void SignRomHeader( ROM_Header *rh ) result = ACSign_Encrypto( signDst, privateKey, &signSrc, sizeof(SignatureData) ); if( !result ) { - throw gcnew System::Exception( "Exception: Fail to calc the hash of the ROM header." ); + throw gcnew System::Exception( "Exception: Failed to calc the hash of the ROM header." ); } // 署名を解除してダイジェストと一致するかベリファイする @@ -319,7 +320,7 @@ void SignRomHeader( ROM_Header *rh ) } if( !result || (memcmp( &signSrc, &(decryptBlock[pos+1]), sizeof(SignatureData) ) != 0) ) { - throw gcnew System::Exception( "Exception: Fail to compare the hash of the ROM header." ); + throw gcnew System::Exception( "Exception: Failed to compare the hash of the ROM header." ); } // ROMヘッダに署名を上書き @@ -504,5 +505,97 @@ System::String^ SaveFileUsingDialog( System::String ^defdir, System::String ^fil // @arg [in] 出力SRLのパス void makeTad( System::String ^maketad_path, System::String ^srlpath, System::String ^tadpath ) { - System::Diagnostics::Process::Start( maketad_path, "\"" + srlpath + "\" -o \"" + tadpath + "\"" ); + System::Diagnostics::ProcessStartInfo ^info = gcnew System::Diagnostics::ProcessStartInfo(); + info->FileName = maketad_path; + info->Arguments = "\"" + srlpath + "\" -o \"" + tadpath + "\""; + info->CreateNoWindow = true; + info->UseShellExecute = false; + info->RedirectStandardError = true; + + System::Diagnostics::Process ^p = System::Diagnostics::Process::Start( info ); + //p->WaitForExit(); + System::String ^output = p->StandardError->ReadToEnd(); + output->Replace( (char)'\r\r\n', (char)'\n' ); + System::Console::WriteLine( "{0}", output ); + + if( output != "" ) + { + throw gcnew System::Exception("Failed to transform SRL to TAD."); + } +} + +// ---------------------------------------------------------------------- +// コンソール +// ---------------------------------------------------------------------- + +// getopt : 引数を解析してオプションが見つかったら1つ返す +// @arg [in/out] 引数 (オプションが見つかった場合削除されていく) +// @arg [in] オプション許可リスト +// @arg [out] オプション引数の格納場所 (ない場合 nullptrが入る) +// @ret 最初に見つかったオプション +char getopt( cli::array ^%args, System::String ^condition, System::String ^% optarg ) +{ + char opt=0; + + // 初期化 + optarg = nullptr; + + // オプションを探して条件に合うかどうかを調べる + int ai; + int ci = 0; + for( ai=0; ai < args->Length; ai++ ) + { + System::String ^arg = args[ai]; + if( arg->StartsWith("-") && arg->Length >= 2 ) + { + // 条件に合うオプションかどうかを調べる + ci = condition->IndexOf( arg[1] ); + if( ci >= 0 ) + { + opt = (char)condition[ci]; + } + break; + } + } + // オプションはあったが条件にない不正なオプションだった + if( ci < 0 ) + { + return ((char)0); + } + // オプションが存在しなかった + if( ai == args->Length ) + { + return ((char)-1); + } + + // オプション引数があるかチェック + if( ((ci+1) < condition->Length) && (condition[ci+1] == ':') ) + { + if( ((ai+1) < args->Length) && !args[ai+1]->StartsWith("-") ) + { + optarg = System::String::Copy(args[ai+1]); + shrinkArgs( args, ai+1); + } + else + { + return ((char)0); // オプション引数がない + } + } + + // オプションを削除する + shrinkArgs( args, ai ); + return opt; +} + +// args から特定の要素を削除 +// @arg [in] 引数 +// @arg [in] 削除する要素のインデックス +void shrinkArgs( cli::array ^%args, const int index ) +{ + int i; + for( i=index+1; i < args->Length; i++ ) + { + args[i-1] = args[i]; + } + cli::array::Resize( args, args->Length - 1 ); }