From 04f52448ee78f5046d477005961e318412a4a029 Mon Sep 17 00:00:00 2001 From: nishikawa_takeshi Date: Thu, 4 Dec 2008 10:04:46 +0000 Subject: [PATCH] =?UTF-8?q?=E3=83=9E=E3=82=B9=E3=82=BF=E3=82=A8=E3=83=87?= =?UTF-8?q?=E3=82=A3=E3=82=BF:tad=E8=AA=AD=E3=81=BF=E8=BE=BC=E3=81=BF?= =?UTF-8?q?=E5=AE=9F=E8=A3=85=E4=B8=AD=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@58 7061adef-622a-194b-ae81-725974e89856 --- .../MasterEditorTWL/MasterEditorTWL.ncb | Bin 11283456 -> 11283456 bytes .../MasterEditorTWL/MasterEditorTWL.suo | Bin 55296 -> 60928 bytes .../MasterEditorTWL/Debug/BuildLog.htm | Bin 19548 -> 12432 bytes .../MasterEditorTWL/MasterEditorTWL/Form1.h | 460 +++++++----------- .../MasterEditorTWL/Form_deliv.cpp | 32 +- .../MasterEditorTWL/Form_file.cpp | 41 +- .../MasterEditorTWL/Form_srl.cpp | 8 +- .../MasterEditorTWL/Form_tmp.cpp | 3 +- .../MasterEditorTWL/Form_util.cpp | 133 ++++- .../MasterEditorTWL/MasterEditorTWL.vcproj | 16 + .../MasterEditorTWL/split_tad.cpp | 275 +++++++++++ .../MasterEditorTWL/split_tad.h | 80 +++ .../MasterEditorTWL/split_tad_util.cpp | 186 +++++++ .../MasterEditorTWL/split_tad_util.h | 73 +++ 14 files changed, 985 insertions(+), 322 deletions(-) create mode 100644 build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/split_tad.cpp create mode 100644 build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/split_tad.h create mode 100644 build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/split_tad_util.cpp create mode 100644 build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/split_tad_util.h diff --git a/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL.ncb b/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL.ncb index 882211e0b4567bd0df2bc9660d8761a20d85d7a1..2e8fb5a57b2d09384f58c232414bc2b365dea79f 100644 GIT binary patch delta 115855 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 L0cBRVtGfIb`Z*r# delta 85385 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 SvEpF;Hgs>$gZ0~E=lvfQ*WiBu diff --git a/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL.suo b/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL.suo index 407fc4b848d850d81930357c40008815a70fdeb2..ca7e3bef721d26c23246de4f011c52998c49a986 100644 GIT binary patch delta 6485 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 & 0x0F; // 下位1桁 + System::Byte subver = System::Decimal::ToByte(this->numSubmitVersion->Value) & 0x0F; + + System::String ^prefix = "T" + this->hSrl->hGameCode + romver.ToString("X") + subver.ToString("X"); + if( this->isPreliminary() == true ) + { + prefix += "E"; + } + return prefix; + } + private: // ---------------------------------------------- // 一時ファイルの取り扱い @@ -2924,6 +2941,12 @@ private: System::Windows::Forms::DataGridViewTextBoxColumn^ colWarnCause; // フォームの入力をチェックする System::Boolean checkSrlForms(void); + // 事前版かどうか確認する + bool isPreliminary() + { + return this->cboxRemasterVerE->Checked; + } + private: // --------------------------------------------------------------------- // リージョン設定は複雑なので別に切り出す @@ -2997,7 +3020,7 @@ private: System::Windows::Forms::DataGridViewTextBoxColumn^ colWarnCause; void sucMsg( System::String ^msgJ, System::String ^msgE ) { - if( this->stripItemJapanese->Checked ) + if( this->isJapanese() ) MessageBox::Show( msgJ, "Information", MessageBoxButtons::OK, MessageBoxIcon::None ); else MessageBox::Show( msgE, "Information", MessageBoxButtons::OK, MessageBoxIcon::None ); @@ -3006,7 +3029,7 @@ private: System::Windows::Forms::DataGridViewTextBoxColumn^ colWarnCause; // エラーメッセージを出力 void errMsg( System::String ^msgJ, System::String ^msgE ) { - if( this->stripItemJapanese->Checked ) + if( this->isJapanese() ) MessageBox::Show( msgJ, "Error", MessageBoxButtons::OK, MessageBoxIcon::Error ); else MessageBox::Show( msgE, "Error", MessageBoxButtons::OK, MessageBoxIcon::Error ); @@ -3029,6 +3052,16 @@ private: System::Windows::Forms::DataGridViewTextBoxColumn^ colWarnCause; // 言語リソース切り替え void changeLanguage( System::String ^langname ); + // 日本語版かどうか確認する + bool isJapanese() + { + return (this->stripItemJapanese->Checked); + } + bool isEnglish() + { + return (!this->isJapanese()); + } + // -------------------------------------------------------- // エラー情報の登録 // -------------------------------------------------------- @@ -3061,6 +3094,32 @@ private: System::Windows::Forms::DataGridViewTextBoxColumn^ colWarnCause; // SRLのバイナリに影響する項目の中で修正可能なエラーだけをチェック System::Boolean isValidAffectRomModified(void); + private: + // ---------------------------------------------- + // ファイル操作ユーティリティ + // ---------------------------------------------- + + // 直前にアクセスしたディレクトリを記憶して次回のデフォルトにする + System::String ^prevDir; // 初期値はnullptr + + // ファイルをダイアログで取得 + // @arg [in] 拡張子フィルタ + // @ret 取得したファイル名 エラーのとき nullptr + System::String^ openFileDlg( System::String ^filter ); + + // セーブするファイルをダイアログで取得 + // @arg [in] 拡張子フィルタ + // @arg [in] ファイルの拡張子が不正なときに追加するときの正しい拡張子 + // @ret 取得したファイル名 エラーのとき nullptr + System::String^ saveFileDlg( System::String ^filter, System::String ^extension ); + + // セーブするディレクトリをダイアログで取得 + // @ret 取得したディレクトリ名(\\で終わるように調整される) エラーのときnullptr + System::String^ saveDirDlg( System::String ^msgJ, System::String ^msgE ); + + // ファイルが存在するかを調べて上書き確認をする + bool isOverwriteFile( System::String ^path ); + ///////////////////////////////////////////// // タイトルバー操作メソッド ///////////////////////////////////////////// @@ -3089,22 +3148,24 @@ private: System::Windows::Forms::DataGridViewTextBoxColumn^ colWarnCause; System::String^ filename; // ドラッグアンドドロップ以外ではダイアログから入力する + filename = this->openFileDlg( "rom format (*.srl;*.tad)|*.srl;*.tad|All files (*.*)|*.*" ); + if( filename == nullptr ) { - System::Windows::Forms::OpenFileDialog ^dlg = gcnew (OpenFileDialog); - - dlg->InitialDirectory = System::Environment::GetFolderPath( System::Environment::SpecialFolder::Desktop );//"c:\\"; - dlg->Filter = "srl format (*.srl)|*.srl|All files (*.*)|*.*"; - dlg->FilterIndex = 1; - dlg->RestoreDirectory = true; - - if( dlg->ShowDialog() != System::Windows::Forms::DialogResult::OK ) - { - //this->errMsg( "ROMデータファイルのオープンがキャンセルされました。", "Opening the ROM data file is canceled by user." ); - return; - } - filename = dlg->FileName; + //this->errMsg( "ROMデータファイルのオープンがキャンセルされました。", "Opening the ROM data file is canceled by user." ); + return; } - this->loadSrl( filename ); + + // 拡張子で tad 読み込みにするかを判定 + if( System::IO::Path::GetExtension( filename )->ToLower()->Equals( ".tad" ) ) + { + this->loadTad( filename ); + } + else + { + this->loadSrl( filename ); + } + this->tboxFile->Text = filename; + this->clearOtherForms(); //this->sucMsg( "ROMデータファイルのオープンに成功しました。", "The ROM data file is opened successfully." ); } //stripItemOpenRom_Click() @@ -3112,8 +3173,6 @@ private: System::Windows::Forms::DataGridViewTextBoxColumn^ colWarnCause; private: System::Void stripItemMasterRom_Click(System::Object^ sender, System::EventArgs^ e) { - System::String^ filename; - // SRLが読み込まれていないときにはリードさせない if( System::String::IsNullOrEmpty( this->tboxFile->Text ) ) { @@ -3132,76 +3191,47 @@ private: System::Windows::Forms::DataGridViewTextBoxColumn^ colWarnCause; return; } - // SRL名を提出手順書に従わせる - { - filename = gcnew System::String(""); + // 出力ファイル名をゲームコードなどから強制的に決める + System::String ^prefix = this->getSubmitFilePrefix(); + System::String ^srlfile = prefix + ".SRL"; - if( this->cboxRemasterVerE->Checked == true ) - { - filename = "T" + this->hSrl->hGameCode + "E" - + System::Decimal::ToByte(this->numSubmitVersion->Value).ToString("X") + ".SRL"; - } - else - { - filename = "T" + this->hSrl->hGameCode + this->hSrl->hRomVersion->ToString("X") - + System::Decimal::ToByte(this->numSubmitVersion->Value).ToString("X") + ".SRL"; - } - } + // 注意書き + this->sucMsg( + "以下のファイルが作成されます。\n\n" + + srlfile + " (マスターROM)\n", + + "Following file for submission will be made. \n\n" + + srlfile + " (Master ROM)\n" + ); - // 注意書き - { - this->sucMsg( - "提出手順書にしたがい、ROMデータファイル名は \"" + filename + "\"となります。\n" + "\nROMデータファイルを保存するフォルダを選択してください。", - "ROM data file name is \"" + filename + "\".\n" + "\nPlease select a folder in which the ROM data is saved." - ); - } // ダイアログからSRLを保存するディレクトリを取得する + System::String ^dir = this->saveDirDlg( "保存先フォルダを選択してください。", "Please select a folder for saving the file" ); + if( !dir ) { - System::Windows::Forms::FolderBrowserDialog ^dlg = gcnew (System::Windows::Forms::FolderBrowserDialog); - - if( dlg->ShowDialog() != System::Windows::Forms::DialogResult::OK ) - { - this->errMsg( "フォルダの選択がキャンセルされましたのでマスターROMは作成されません。", - "A submission sheet can not be made, since selecting folder is canceled." ); - return; - } - else - { - if( !dlg->SelectedPath->EndsWith("\\") ) - { - filename = dlg->SelectedPath + "\\" + filename; - } - else - { - filename = dlg->SelectedPath + filename; - } - } - if( System::IO::File::Exists( filename ) ) - { - System::String ^msg; - if( this->stripItemJapanese->Checked ) - msg = gcnew System::String( filename + "はすでに存在します。上書きしますか?" ); - else - msg = gcnew System::String( filename + "already exists. Overwrite it?" ); - if( MessageBox::Show( msg, "Information", MessageBoxButtons::YesNo, MessageBoxIcon::None ) - == System::Windows::Forms::DialogResult::No ) - { - this->errMsg( "マスターROMの作成をキャンセルしました。", - "Making a master ROM is canceled." ); - return; - } - } + this->errMsg( "フォルダの選択がキャンセルされましたのでマスターROMは作成されません。", + "A master ROM isn't made, since selecting folder is canceled." ); + return; } + srlfile = dir + srlfile; + + // ファイルが存在するかを調べて上書き確認をする + if( !this->isOverwriteFile(srlfile) ) + { + this->errMsg( "ファイルの上書きがキャンセルされましたのでマスターROMは作成されません。", + "Since overwriting a file is canceled, a master ROM isn't made." ); + return; + } + try { - if( !this->saveSrl( filename ) ) + if( !this->saveSrl( srlfile ) ) { this->errMsg( "マスターROMの作成に失敗しました。", "Making a master ROM failed." ); return; } - this->sucMsg( "マスターROMの作成が成功しました。", "Making the ROM data file succeeded." ); - this->tboxFile->Text = filename; + this->sucMsg( "マスターROMの作成が成功しました。", "A master ROM is made successfully." ); + this->tboxFile->Text = srlfile; } catch( System::Exception ^ex ) { @@ -3240,132 +3270,52 @@ private: System::Windows::Forms::DataGridViewTextBoxColumn^ colWarnCause; return; } - // SRL名を提出手順書に従わせる - System::String ^srlfile; - { - srlfile = gcnew System::String(""); + // 出力ファイル名をゲームコードなどから強制的に決める + System::String ^prefix = this->getSubmitFilePrefix(); + System::String ^srlfile = prefix + ".SRL"; + System::String ^delivfile = prefix + "_SHEET.XML"; + System::String ^middlefile = prefix + "_MIDDLEWARE.XML"; + System::String ^middlefilePrint = prefix + "_MIDDLEWARE.HTML"; - if( this->cboxRemasterVerE->Checked == true ) - { - srlfile = "T" + this->hSrl->hGameCode + "E" - + System::Decimal::ToByte(this->numSubmitVersion->Value).ToString("X") + ".SRL"; - } - else - { - srlfile = "T" + this->hSrl->hGameCode + this->hSrl->hRomVersion->ToString("X") - + System::Decimal::ToByte(this->numSubmitVersion->Value).ToString("X") + ".SRL"; - } - } + // 注意書き + this->sucMsg( + "以下の提出ファイルが一度に作成されます。\n\n" + + srlfile + " (マスターROM)\n" + + delivfile + " (マスターROM提出確認書)\n" + + middlefile + " (ミドルウェア一覧)\n" + + middlefilePrint + " (ミドルウェア一覧 印刷用)\n" + + "\n", - // 注意書き - { - this->sucMsg( - "Step1/3: ROMデータファイルと提出確認書の情報を一致させるため、まず、入力情報を反映させたマスターROMデータファイルを作成します。\n(キャンセルされたとき、提出データ一式は作成されません。)\n" - + "\n マスターROMデータファイル名は \"" + srlfile + "\"となります。\n" + "\nマスターROMデータファイルを保存するフォルダを選択してください。", - "Step1/3: Firstly, We make a master ROM file because all information in a submission sheet are match those in the ROM data file.\n(When it is canceled, both A set of submission data is not made.)\n" - + "\n The name of the master ROM data file is \"" + srlfile + "\".\n" + "\nPlease select a folder in which the ROM data is saved." - ); - } + "Following files for submission will be made. \n\n" + + srlfile + " (Master ROM)\n" + + delivfile + " (Submission Sheet)\n" + + middlefile + " (Middleware List)\n" + + middlefilePrint + " (Middleware List For Print)\n" + + "\n" + ); // ダイアログからSRLを保存するディレクトリを取得する - System::String ^delivfile; + System::String ^dir = this->saveDirDlg( "保存先フォルダを選択してください。", "Please select a folder for saving files" ); + if( !dir ) { - System::Windows::Forms::FolderBrowserDialog ^dlg = gcnew (System::Windows::Forms::FolderBrowserDialog); - - if( dlg->ShowDialog() != System::Windows::Forms::DialogResult::OK ) - { - this->errMsg( "フォルダの選択がキャンセルされましたので提出データ一式は作成されません。", - "A set of submission data can not be made, since selecting folder is canceled." ); - return; - } - else - { - if( !dlg->SelectedPath->EndsWith("\\") ) - { - srlfile = dlg->SelectedPath + "\\" + srlfile; - } - else - { - srlfile = dlg->SelectedPath + srlfile; - } - } - if( System::IO::File::Exists( srlfile ) ) - { - System::String ^msg; - if( this->stripItemJapanese->Checked ) - msg = gcnew System::String( srlfile + "はすでに存在します。上書きしますか?" ); - else - msg = gcnew System::String( srlfile + "already exists. Overwrite it?" ); - if( MessageBox::Show( msg, "Information", MessageBoxButtons::YesNo, MessageBoxIcon::None ) - == System::Windows::Forms::DialogResult::No ) - { - this->errMsg( "ファイルの上書きがキャンセルされましたので提出データ一式は作成されません。", - "Since overwriting a file is canceled, a set of submission data can not be made." ); - return; - } - } - + this->errMsg( "フォルダの選択がキャンセルされましたので提出データ一式は作成されません。", + "A set of submission data can not be made, since selecting folder is canceled." ); + return; } + srlfile = dir + srlfile; + delivfile = dir + delivfile; + middlefile = dir + middlefile; + middlefilePrint = dir + middlefilePrint; - // 注意書き + // ファイルが存在するかを調べて上書き確認をする + if( !this->isOverwriteFile(srlfile) || !this->isOverwriteFile(delivfile) || + !this->isOverwriteFile(middlefile) || !this->isOverwriteFile(middlefilePrint) ) { - this->sucMsg( - "Step2/3: 続いて、使用されているミドルウェアのリストを作成します。\nここでキャンセルされたとき、提出データ一式は作成されませんのでご注意ください。", - "Step2/3: Secondly, We should make a list of middlewares used by the ROM. \n(CAUTION: When it is canceled, A set of submission data is not made.)" - ); + this->errMsg( "ファイルの上書きがキャンセルされましたので提出データ一式は作成されません。", + "Since overwriting a file is canceled, a set of submission data can not be made." ); + return; } - // ダイアログでファイルパスを決定 - System::String ^middlefile; - { - System::Windows::Forms::SaveFileDialog ^dlg = gcnew (SaveFileDialog); - - dlg->InitialDirectory = System::Environment::GetFolderPath( System::Environment::SpecialFolder::Desktop );//"c:\\"; - dlg->Filter = "xml format (*.xml)|*.xml"; - dlg->FilterIndex = 1; - dlg->RestoreDirectory = true; - - if( dlg->ShowDialog() != System::Windows::Forms::DialogResult::OK ) - { - this->errMsg( "ミドルウェアリストの作成がキャンセルされました。提出データ一式は作成されません。", - "Making a list of middlewares is canceled. A set of submission data is not made." ); - return; - } - middlefile = dlg->FileName; - if( !(dlg->FileName->EndsWith( ".xml" )) ) - { - middlefile += ".xml"; - } - } - - // 注意書き - { - this->sucMsg( - "Step3/3: 続いて、提出確認書を作成します。\nここでキャンセルされたとき、提出データ一式は作成されませんのでご注意ください。", - "Step3/3: Finally, We should make a submission sheet. \n(CAUTION: When it is canceled, A set of submission data is not made, but also the master ROM data and a list of middleware are not made.)" - ); - } - // ダイアログでファイルパスを決定 - { - System::Windows::Forms::SaveFileDialog ^dlg = gcnew (SaveFileDialog); - - dlg->InitialDirectory = System::Environment::GetFolderPath( System::Environment::SpecialFolder::Desktop );//"c:\\"; - dlg->Filter = "xml format (*.xml)|*.xml"; - dlg->FilterIndex = 1; - dlg->RestoreDirectory = true; - - if( dlg->ShowDialog() != System::Windows::Forms::DialogResult::OK ) - { - this->errMsg( "提出確認書の作成がキャンセルされました。提出データ一式は作成されません。", - "Making a submission sheet is canceled. A set of submission data is not made." ); - return; - } - delivfile = dlg->FileName; - if( !(dlg->FileName->EndsWith( ".xml" )) ) - { - delivfile += ".xml"; - } - } - + // マスタ提出確認書に必要な情報をフォームから取得して更新 this->setSrlProperties(); // 先にSrlを更新しておく this->setDeliverableProperties(); @@ -3375,8 +3325,8 @@ private: System::Windows::Forms::DataGridViewTextBoxColumn^ colWarnCause; { if( !this->saveSrl( srlfile ) ) { - this->errMsg( "マスターROMの作成に失敗しました。提出確認書およびミドルウェアリストは作成されません。", - "Making a master ROM failed. And a submission sheet and a list of middlewares are not made." ); + this->errMsg( "マスターROMの作成に失敗しました。作成を中止するため一部のファイルは作成されません。", + "Making a master ROM failed. Therefore, a part of files can't be made." ); return; } this->tboxFile->Text = srlfile; @@ -3384,15 +3334,15 @@ private: System::Windows::Forms::DataGridViewTextBoxColumn^ colWarnCause; catch( System::Exception ^ex ) { (void)ex; - this->errMsg( "マスターROMの作成に失敗しました。提出確認書およびミドルウェアリストは作成されません。", - "Making a master ROM failed. And a submission sheet and a list of middlewares are not made." ); + this->errMsg( "マスターROMの作成に失敗しました。作成を中止するため一部のファイルは作成されません。", + "Making a master ROM failed. Therefore, a part of files can't be made." ); return; } u16 crc; // SRL全体のCRCを計算する(書類に記述するため) if( !getWholeCRCInFile( srlfile, &crc ) ) { - this->errMsg( "CRCの計算に失敗しました。提出確認書およびミドルウェアリストは作成されません。", - "Calc CRC is failed. Therefore, And a submission sheet and a list of middlewares are not made." ); + this->errMsg( "CRCの計算に失敗しました。作成を中止するため一部のファイルは作成されません。", + "Calculating CRC is failed. Therefore, a part of files can't be made." ); return; } System::UInt16 ^hcrc = gcnew System::UInt16( crc ); @@ -3401,18 +3351,17 @@ private: System::Windows::Forms::DataGridViewTextBoxColumn^ colWarnCause; this->tboxWholeCRC->AppendText( hcrc->ToString("X") ); // ミドルウェアのリストを作成 - if( !this->saveMiddlewareListXmlEmbeddedXsl( middlefile ) ) + if( !this->saveMiddlewareListXmlEmbeddedXsl( middlefile ) || !this->saveMiddlewareListHtml( middlefilePrint ) ) { - this->errMsg( "ミドルウェアのリストが作成できませんでした。提出確認書は作成されません。", - "Making a list of middleware failed. And a submission sheet is not made."); + this->errMsg( "ミドルウェアのリストが作成できませんでした。作成を中止するため一部のファイルは作成されません。", + "Making a list of middleware failed. Therefore, a part of files can't be made."); return; } // 書類作成 - cli::array ^paths = srlfile->Split(L'\\'); // 余分なパスを削除 - srlfile = paths[ paths->Length - 1 ]; - //result = this->hDeliv->write( delivfile, this->hSrl, hcrc, srlfile, !(this->stripItemJapanese->Checked) ); - result = this->hDeliv->writeSpreadsheet( delivfile, this->hSrl, hcrc, srlfile, !(this->stripItemJapanese->Checked) ); + srlfile = System::IO::Path::GetFileName( srlfile ); + //result = this->hDeliv->write( delivfile, this->hSrl, hcrc, srlfile, !this->isJapanese() ); + result = this->hDeliv->writeSpreadsheet( delivfile, this->hSrl, hcrc, srlfile, !this->isJapanese() ); if( result != ECDeliverableResult::NOERROR ) { switch( result ) @@ -3433,33 +3382,18 @@ private: System::Windows::Forms::DataGridViewTextBoxColumn^ colWarnCause; } return; } - this->sucMsg( "提出データ一式の作成に成功しました。", "The submission sheet is made successfully." ); + this->sucMsg( "提出データ一式の作成に成功しました。", "A set of submission data is made successfully." ); } //stripItemSheet_Click() private: System::Void stripItemSaveTemp_Click(System::Object^ sender, System::EventArgs^ e) { - System::String ^filename = gcnew System::String(""); + System::String ^filename = this->saveFileDlg( "xml format (*.xml)|*.xml", ".xml" ); - // ダイアログでファイルパスを決定 + if( !filename ) { - System::Windows::Forms::SaveFileDialog ^dlg = gcnew (SaveFileDialog); - - dlg->InitialDirectory = System::Environment::GetFolderPath( System::Environment::SpecialFolder::Desktop );//"c:\\"; - dlg->Filter = "xml format (*.xml)|*.xml"; - dlg->FilterIndex = 1; - dlg->RestoreDirectory = true; - - if( dlg->ShowDialog() != System::Windows::Forms::DialogResult::OK ) - { - return; - } - filename = dlg->FileName; - if( !(dlg->FileName->EndsWith( ".xml" )) ) - { - filename += ".xml"; - } + return; } this->saveTmp( filename ); } //stripItemSaveTemp_Click() @@ -3467,26 +3401,11 @@ private: System::Windows::Forms::DataGridViewTextBoxColumn^ colWarnCause; private: System::Void stripItemLoadTemp_Click(System::Object^ sender, System::EventArgs^ e) { - System::String ^filename = gcnew System::String(""); + System::String ^filename = this->openFileDlg( "xml format (*.xml)|*.xml" ); - // ダイアログでファイルパスを決定 + if( filename == nullptr ) { - System::Windows::Forms::OpenFileDialog ^dlg = gcnew (OpenFileDialog); - - dlg->InitialDirectory = System::Environment::GetFolderPath( System::Environment::SpecialFolder::Desktop );//"c:\\"; - dlg->Filter = "xml format (*.xml)|*.xml"; - dlg->FilterIndex = 1; - dlg->RestoreDirectory = true; - - if( dlg->ShowDialog() != System::Windows::Forms::DialogResult::OK ) - { - return; - } - filename = dlg->FileName; - if( !(dlg->FileName->EndsWith( ".xml" )) ) - { - filename += ".xml"; - } + return; } this->loadTmp( filename ); } //stripItemLoadTemp_Click() @@ -3494,34 +3413,15 @@ private: System::Windows::Forms::DataGridViewTextBoxColumn^ colWarnCause; private: System::Void stripItemMiddlewareXml_Click(System::Object^ sender, System::EventArgs^ e) { - System::String ^filename = gcnew System::String(""); - if( System::String::IsNullOrEmpty(this->tboxFile->Text) ) { this->errMsg( "ROMデータファイルが読み込まれていません。", "ROM file has not opened yet." ); return; } - // ダイアログでファイルパスを決定 - { - System::Windows::Forms::SaveFileDialog ^dlg = gcnew (SaveFileDialog); + System::String ^filename = this->saveFileDlg( "xml format (*.xml)|*.xml", ".xml" ); - dlg->InitialDirectory = System::Environment::GetFolderPath( System::Environment::SpecialFolder::Desktop );//"c:\\"; - dlg->Filter = "xml format (*.xml)|*.xml"; - dlg->FilterIndex = 1; - dlg->RestoreDirectory = true; - - if( dlg->ShowDialog() != System::Windows::Forms::DialogResult::OK ) - { - return; - } - filename = dlg->FileName; - if( !(dlg->FileName->EndsWith( ".xml" )) ) - { - filename += ".xml"; - } - } - if( !this->saveMiddlewareListXmlEmbeddedXsl(filename) ) + if( !filename || !this->saveMiddlewareListXmlEmbeddedXsl(filename) ) { this->errMsg( "ミドルウェアリストの作成に失敗しました。","Making a middleware list failed." ); } @@ -3530,34 +3430,15 @@ private: System::Windows::Forms::DataGridViewTextBoxColumn^ colWarnCause; private: System::Void stripItemMiddlewareHtml_Click(System::Object^ sender, System::EventArgs^ e) { - System::String ^filename = gcnew System::String(""); - if( System::String::IsNullOrEmpty(this->tboxFile->Text) ) { this->errMsg( "ROMデータファイルがオープンされていません。", "ROM file has not opened yet." ); return; } - // ダイアログでファイルパスを決定 - { - System::Windows::Forms::SaveFileDialog ^dlg = gcnew (SaveFileDialog); + System::String ^filename = this->saveFileDlg( "html format (*.html)|*.html", ".html" ); - dlg->InitialDirectory = System::Environment::GetFolderPath( System::Environment::SpecialFolder::Desktop );//"c:\\"; - dlg->Filter = "html format (*.html)|*.html"; - dlg->FilterIndex = 1; - dlg->RestoreDirectory = true; - - if( dlg->ShowDialog() != System::Windows::Forms::DialogResult::OK ) - { - return; - } - filename = dlg->FileName; - if( !(dlg->FileName->EndsWith( ".html" )) ) - { - filename += ".html"; - } - } - if( !this->saveMiddlewareListHtml(filename) ) + if( !filename || !this->saveMiddlewareListXmlEmbeddedXsl(filename) ) { this->errMsg( "ミドルウェアリストの作成に失敗しました。","Making a middleware list failed." ); } @@ -3591,6 +3472,7 @@ private: System::Windows::Forms::DataGridViewTextBoxColumn^ colWarnCause; return; } this->loadSrl( filename ); // ドラッグアンドドロップの時点でボタンを押さなくてもファイルを開く + this->tboxFile->Text = filename; this->clearOtherForms(); //this->sucMsg( "ROMデータファイルのオープンに成功しました。", "The ROM data file is opened successfully." ); } @@ -3635,8 +3517,8 @@ private: System::Windows::Forms::DataGridViewTextBoxColumn^ colWarnCause; private: System::Void cboxRemasterVerE_CheckedChanged(System::Object^ sender, System::EventArgs^ e) { - //this->numRemasterVer->Enabled = !(this->cboxRemasterVerE->Checked); - //if( this->cboxRemasterVerE->Checked == false ) + //this->numRemasterVer->Enabled = !(this->isEngilsh()); + //if( this->isEngilsh() == false ) //{ // this->numRemasterVer->Value = 0; //} @@ -3726,10 +3608,6 @@ private: System::Windows::Forms::DataGridViewTextBoxColumn^ colWarnCause; this->loadOtherForms(); // SRLに登録されていないROM仕様のフォームも戻す } - - - - }; // enf of ref class Form1 } // end of namespace MasterEditorTWL diff --git a/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/Form_deliv.cpp b/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/Form_deliv.cpp index c8ce7dc..1755313 100644 --- a/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/Form_deliv.cpp +++ b/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/Form_deliv.cpp @@ -104,7 +104,7 @@ void Form1::setDeliverableProperties(void) // 会社情報 this->hDeliv->hCompany1 = this->tboxCompany1->Text + " " + this->tboxDepart1->Text; this->hDeliv->hPerson1 = this->tboxPerson1->Text; - if( this->stripItemJapanese->Checked == true ) + if( this->isJapanese() == true ) { this->hDeliv->hFurigana1 = this->tboxFurigana1->Text; } @@ -115,7 +115,7 @@ void Form1::setDeliverableProperties(void) this->hDeliv->hTel1 = this->tboxTel1->Text; this->hDeliv->hFax1 = this->tboxFax1->Text; this->hDeliv->hMail1 = this->tboxMail1->Text; - if( this->stripItemJapanese->Checked == true ) + if( this->isJapanese() == true ) { this->hDeliv->hNTSC1 = this->tboxNTSC1->Text; } @@ -127,7 +127,7 @@ void Form1::setDeliverableProperties(void) { this->hDeliv->hCompany2 = this->tboxCompany2->Text + " " + this->tboxDepart2->Text; this->hDeliv->hPerson2 = this->tboxPerson2->Text; - if( this->stripItemJapanese->Checked == true ) + if( this->isJapanese() == true ) { this->hDeliv->hFurigana2 = this->tboxFurigana2->Text; } @@ -138,7 +138,7 @@ void Form1::setDeliverableProperties(void) this->hDeliv->hTel2 = this->tboxTel2->Text; this->hDeliv->hFax2 = this->tboxFax2->Text; this->hDeliv->hMail2 = this->tboxMail2->Text; - if( this->stripItemJapanese->Checked == true ) + if( this->isJapanese() == true ) { this->hDeliv->hNTSC2 = this->tboxNTSC2->Text; } @@ -202,7 +202,7 @@ void Form1::setDeliverableProperties(void) // SRL情報を文字列で登録 if( this->combRegion->SelectedIndex < 0 ) { - if( this->stripItemJapanese->Checked == true ) + if( this->isJapanese() == true ) this->hDeliv->hRegion = gcnew System::String("不明"); else this->hDeliv->hRegion = gcnew System::String("Undefined"); @@ -213,7 +213,7 @@ void Form1::setDeliverableProperties(void) } if( this->combCERO->SelectedIndex < 0 ) { - if( this->stripItemJapanese->Checked == true ) + if( this->isJapanese() == true ) this->hDeliv->hCERO = gcnew System::String("不可"); else this->hDeliv->hCERO = gcnew System::String("Undefined"); @@ -224,7 +224,7 @@ void Form1::setDeliverableProperties(void) } if( this->combESRB->SelectedIndex < 0 ) { - if( this->stripItemJapanese->Checked == true ) + if( this->isJapanese() == true ) this->hDeliv->hESRB = gcnew System::String("不可"); else this->hDeliv->hESRB = gcnew System::String("Undefined"); @@ -235,7 +235,7 @@ void Form1::setDeliverableProperties(void) } if( this->combUSK->SelectedIndex < 0 ) { - if( this->stripItemJapanese->Checked == true ) + if( this->isJapanese() == true ) this->hDeliv->hUSK = gcnew System::String("不可"); else this->hDeliv->hUSK = gcnew System::String("Undefined"); @@ -246,7 +246,7 @@ void Form1::setDeliverableProperties(void) } if( this->combPEGI->SelectedIndex < 0 ) { - if( this->stripItemJapanese->Checked == true ) + if( this->isJapanese() == true ) this->hDeliv->hPEGI = gcnew System::String("不可"); else this->hDeliv->hPEGI = gcnew System::String("Undefined"); @@ -257,7 +257,7 @@ void Form1::setDeliverableProperties(void) } if( this->combPEGI_PRT->SelectedIndex < 0 ) { - if( this->stripItemJapanese->Checked == true ) + if( this->isJapanese() == true ) this->hDeliv->hPEGI_PRT = gcnew System::String("不可"); else this->hDeliv->hPEGI_PRT = gcnew System::String("Undefined"); @@ -268,7 +268,7 @@ void Form1::setDeliverableProperties(void) } if( this->combPEGI_BBFC->SelectedIndex < 0 ) { - if( this->stripItemJapanese->Checked == true ) + if( this->isJapanese() == true ) this->hDeliv->hPEGI_BBFC = gcnew System::String("不可"); else this->hDeliv->hPEGI_BBFC = gcnew System::String("Undefined"); @@ -279,7 +279,7 @@ void Form1::setDeliverableProperties(void) } if( this->combOFLC->SelectedIndex < 0 ) { - if( this->stripItemJapanese->Checked == true ) + if( this->isJapanese() == true ) this->hDeliv->hOFLC = gcnew System::String("不可"); else this->hDeliv->hOFLC = gcnew System::String("Undefined"); @@ -321,14 +321,14 @@ System::Boolean Form1::checkDeliverableForms(void) this->checkTextForm( this->tboxPerson1->Text, LANG_PERSON_J, LANG_PERSON_E, false ); this->checkTextForm( this->tboxCompany1->Text, LANG_COMPANY_J, LANG_COMPANY_E, false ); this->checkTextForm( this->tboxDepart1->Text, LANG_DEPART_J, LANG_DEPART_E, false ); - if( this->stripItemJapanese->Checked == true ) + if( this->isJapanese() == true ) { this->checkTextForm( this->tboxFurigana1->Text, LANG_FURIGANA_J, LANG_FURIGANA_J, false ); } this->checkTextForm( this->tboxTel1->Text, LANG_TEL_J, LANG_TEL_E, false ); //this->checkTextForm( this->tboxFax1->Text, LANG_FAX_J, LANG_FAX_E, false ); this->checkTextForm( this->tboxMail1->Text, LANG_MAIL_J, LANG_MAIL_E, false ); - //if( this->stripItemJapanese->Checked == true ) + //if( this->isJapanese() == true ) //{ // this->checkTextForm( this->tboxNTSC1->Text, LANG_NTSC_1_J + " " + LANG_NTSC_2_J, LANG_NTSC_1_J + " " + LANG_NTSC_2_J, false ); //} @@ -338,14 +338,14 @@ System::Boolean Form1::checkDeliverableForms(void) this->checkTextForm( this->tboxPerson2->Text, LANG_PERSON_J, LANG_PERSON_E, false ); this->checkTextForm( this->tboxCompany2->Text, LANG_COMPANY_J, LANG_COMPANY_E, false ); this->checkTextForm( this->tboxDepart2->Text, LANG_DEPART_J, LANG_DEPART_E, false ); - if( this->stripItemJapanese->Checked == true ) + if( this->isJapanese() == true ) { this->checkTextForm( this->tboxFurigana2->Text, LANG_FURIGANA_J, LANG_FURIGANA_J, false ); } this->checkTextForm( this->tboxTel2->Text, LANG_TEL_J, LANG_TEL_E, false ); //this->checkTextForm( this->tboxFax2->Text, LANG_FAX_J, LANG_FAX_E, false ); this->checkTextForm( this->tboxMail2->Text, LANG_MAIL_J, LANG_MAIL_E, false ); - //if( this->stripItemJapanese->Checked == true ) + //if( this->isJapanese() == true ) //{ // this->checkTextForm( this->tboxNTSC2->Text, LANG_NTSC_1_J + " " + LANG_NTSC_2_J, LANG_NTSC_1_J + " " + LANG_NTSC_2_J, false ); //} diff --git a/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/Form_file.cpp b/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/Form_file.cpp index 340020e..160b9e9 100644 --- a/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/Form_file.cpp +++ b/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/Form_file.cpp @@ -10,6 +10,7 @@ #include "crc_whole.h" #include "utility.h" #include "lang.h" +#include "split_tad.h" #include "FormError.h" #include "Form1.h" @@ -21,7 +22,10 @@ using namespace System::Data; using namespace System::Drawing; using namespace MasterEditorTWL; +// ---------------------------------------------- // 設定ファイルの読み込み +// ---------------------------------------------- + void Form1::loadInit(void) { System::Xml::XmlDocument ^doc = gcnew System::Xml::XmlDocument(); @@ -137,7 +141,10 @@ void Form1::loadInit(void) } } // loadInit() +// ---------------------------------------------- // SRLのオープン +// ---------------------------------------------- + System::Void Form1::loadSrl( System::String ^filename ) { ECSrlResult result = this->hSrl->readFromFile( filename ); @@ -163,7 +170,6 @@ System::Void Form1::loadSrl( System::String ^filename ) } return; } - this->tboxFile->Text = filename; // GUIにROM情報を格納 this->setSrlForms(); @@ -203,7 +209,10 @@ System::Void Form1::loadSrl( System::String ^filename ) return; } // loadSrl() +// ---------------------------------------------- // SRLの保存 +// ---------------------------------------------- + System::Boolean Form1::saveSrl( System::String ^filename ) { // コピーしたファイルにROMヘッダを上書き @@ -214,10 +223,10 @@ System::Boolean Form1::saveSrl( System::String ^filename ) // 再リード this->loadSrl( filename ); + this->tboxFile->Text = filename; return true; } // saveSrl() -// SRLの保存 System::Boolean Form1::saveSrlCore( System::String ^filename ) { // ROM情報をフォームから取得してSRLバイナリに反映させる @@ -237,7 +246,21 @@ System::Boolean Form1::saveSrlCore( System::String ^filename ) return true; } +// ---------------------------------------------- +// tadのオープン +// ---------------------------------------------- + +System::Void Form1::loadTad( System::String ^tadfile ) +{ + System::String ^srlfile = System::IO::Path::GetDirectoryName( System::Reflection::Assembly::GetEntryAssembly()->Location ) + + "\\tmp.srl"; + splitTad( tadfile, srlfile ); +} + +// ---------------------------------------------- // ミドルウェアリストの作成 +// ---------------------------------------------- + System::Void Form1::makeMiddlewareListXml(System::Xml::XmlDocument^ doc) { System::Xml::XmlElement ^root = doc->CreateElement( "twl-master-editor" ); @@ -276,7 +299,10 @@ System::Void Form1::makeMiddlewareListXml(System::Xml::XmlDocument^ doc) } } -// ミドルウェアリストの保存 +// ---------------------------------------------- +// ミドルウェアリストの保存(XML) +// ---------------------------------------------- + System::Boolean Form1::saveMiddlewareListXml( System::String ^filename ) { System::Xml::XmlDocument ^doc = gcnew System::Xml::XmlDocument(); @@ -296,7 +322,10 @@ System::Boolean Form1::saveMiddlewareListXml( System::String ^filename ) return true; } -// ミドルウェアリストの保存 +// ---------------------------------------------- +// ミドルウェアリストの保存(XSL埋め込みXML) +// ---------------------------------------------- + System::Boolean Form1::saveMiddlewareListXmlEmbeddedXsl( System::String ^filename ) { System::Xml::XmlDocument ^doc = gcnew System::Xml::XmlDocument(); @@ -336,7 +365,10 @@ System::Boolean Form1::saveMiddlewareListXmlEmbeddedXsl( System::String ^filenam return true; } +// ---------------------------------------------- // ミドルウェアリストの保存(XML->HTML変換) +// ---------------------------------------------- + System::Boolean Form1::saveMiddlewareListHtml( System::String ^filename ) { System::Xml::Xsl::XslCompiledTransform ^xslt = gcnew System::Xml::Xsl::XslCompiledTransform; @@ -361,3 +393,4 @@ System::Boolean Form1::saveMiddlewareListHtml( System::String ^filename ) System::IO::File::Delete( tmpxml ); return true; } + diff --git a/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/Form_srl.cpp b/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/Form_srl.cpp index 44f12e0..1e06546 100644 --- a/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/Form_srl.cpp +++ b/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/Form_srl.cpp @@ -232,14 +232,14 @@ void Form1::setSrlFormsCaptionEx() System::String ^appother = gcnew System::String(""); if( *(this->hSrl->hIsLaunch) == false ) { - if( this->stripItemJapanese->Checked == true ) + if( this->isJapanese() == true ) appother += "ランチャー非表示.\r\n"; else appother += "Not Display On the Launcher.\r\n"; } if( *(this->hSrl->hIsDataOnly) == true ) { - if( this->stripItemJapanese->Checked == true ) + if( this->isJapanese() == true ) appother += "データ専用.\r\n"; else appother += "Data Only.\r\n"; @@ -249,14 +249,14 @@ void Form1::setSrlFormsCaptionEx() this->tboxCaptionEx->Clear(); if( (this->hSrl->hHasDSDLPlaySign != nullptr) && (*(this->hSrl->hHasDSDLPlaySign) == true) ) { - if( this->stripItemJapanese->Checked == true ) + if( this->isJapanese() == true ) this->tboxCaptionEx->Text += gcnew System::String( "DSクローンブート対応.\r\n" ); else this->tboxCaptionEx->Text += gcnew System::String( "DS Clone Boot.\r\n" ); } if( (this->hSrl->hIsSCFGAccess != nullptr) && (*(this->hSrl->hIsSCFGAccess) == true) ) { - if( this->stripItemJapanese->Checked == true ) + if( this->isJapanese() == true ) this->tboxCaptionEx->Text += gcnew System::String( "SCFGレジスタアクセス可能.\r\n" ); else this->tboxCaptionEx->Text += gcnew System::String( "SDFC Register Accessible.\r\n" ); diff --git a/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/Form_tmp.cpp b/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/Form_tmp.cpp index 0d3261f..6a6d830 100644 --- a/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/Form_tmp.cpp +++ b/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/Form_tmp.cpp @@ -34,7 +34,7 @@ System::Void Form1::saveTmp( System::String ^filename ) MasterEditorTWL::appendXmlTag( doc, root, "Srl", this->tboxFile->Text ); // 言語 - MasterEditorTWL::appendXmlTag( doc, root, "Lang", (this->stripItemJapanese->Checked)?"J":"E" ); + MasterEditorTWL::appendXmlTag( doc, root, "Lang", (this->isJapanese())?"J":"E" ); // フォーム System::Xml::XmlElement ^form = doc->CreateElement( "Form" ); @@ -136,6 +136,7 @@ void Form1::loadTmp( System::String ^filename ) if( !System::String::IsNullOrEmpty(text) ) // SRLファイル名がないときはスルー { this->loadSrl(text); + this->tboxFile->Text = filename; } // 言語 diff --git a/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/Form_util.cpp b/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/Form_util.cpp index 6c67019..39381c2 100644 --- a/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/Form_util.cpp +++ b/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/Form_util.cpp @@ -90,7 +90,7 @@ void Form1::setGridError( void ) { for each( RCMrcError ^err in this->hSrl->hErrorList ) { - this->gridError->Rows->Add( err->getAll( this->stripItemJapanese->Checked ) ); + this->gridError->Rows->Add( err->getAll(this->isJapanese()) ); this->colorGridError( err ); } } @@ -103,7 +103,7 @@ void Form1::setGridWarn( void ) { for each( RCMrcError ^err in this->hSrl->hWarnList ) { - this->gridWarn->Rows->Add( err->getAll( this->stripItemJapanese->Checked ) ); + this->gridWarn->Rows->Add( err->getAll(this->isJapanese()) ); this->colorGridWarn( err ); } } @@ -119,7 +119,7 @@ void Form1::overloadGridError( void ) { if( !err->EnableModify ) // 修正可能な情報は表示しない { - this->gridError->Rows->Add( err->getAll( this->stripItemJapanese->Checked ) ); + this->gridError->Rows->Add( err->getAll(this->isJapanese()) ); this->colorGridError( err ); } } @@ -128,7 +128,7 @@ void Form1::overloadGridError( void ) { for each( RCMrcError ^err in this->hErrorList ) { - this->gridError->Rows->Add( err->getAll( this->stripItemJapanese->Checked ) ); + this->gridError->Rows->Add( err->getAll(this->isJapanese()) ); this->colorGridError( err ); } } @@ -142,7 +142,7 @@ void Form1::overloadGridWarn( void ) { if( !err->EnableModify ) { - this->gridWarn->Rows->Add( err->getAll( this->stripItemJapanese->Checked ) ); + this->gridWarn->Rows->Add( err->getAll(this->isJapanese()) ); this->colorGridWarn( err ); } } @@ -151,7 +151,7 @@ void Form1::overloadGridWarn( void ) { for each( RCMrcError ^err in this->hWarnList ) { - this->gridWarn->Rows->Add( err->getAll( this->stripItemJapanese->Checked ) ); + this->gridWarn->Rows->Add( err->getAll(this->isJapanese()) ); this->colorGridWarn( err ); } } @@ -262,4 +262,125 @@ System::Boolean Form1::isValidAffectRomModified(void) return (count == 0); } +// ---------------------------------------------- +// ファイル操作ユーティリティ +// ---------------------------------------------- + +// ファイルをダイアログで取得 +// @arg [in] 拡張子フィルタ +// @ret 取得したファイル名 エラーのとき nullptr +System::String^ Form1::openFileDlg( System::String ^filter ) +{ + System::Windows::Forms::OpenFileDialog ^dlg = gcnew (OpenFileDialog); + if( System::String::IsNullOrEmpty( this->prevDir ) || !System::IO::Directory::Exists( this->prevDir ) ) + { + dlg->InitialDirectory = System::Environment::GetFolderPath( System::Environment::SpecialFolder::Desktop ); + } + else + { + dlg->InitialDirectory = this->prevDir; // 前に選んだディレクトリをデフォルトにする + } + dlg->Filter = filter; + dlg->FilterIndex = 1; + dlg->RestoreDirectory = true; + + if( dlg->ShowDialog() != System::Windows::Forms::DialogResult::OK ) + { + return nullptr; + } + this->prevDir = System::IO::Path::GetDirectoryName( dlg->FileName ); // デフォルトディレクトリの更新 + return System::String::Copy(dlg->FileName); +} + +// セーブするファイルをダイアログで取得 +// @arg [in] 拡張子フィルタ +// @arg [in] ファイルの拡張子が不正なときに追加するときの正しい拡張子 +// @ret 取得したファイル名 エラーのとき nullptr +System::String^ Form1::saveFileDlg( System::String ^filter, System::String ^extension ) +{ + System::String ^retfile; + System::Windows::Forms::SaveFileDialog ^dlg = gcnew (SaveFileDialog); + + if( System::String::IsNullOrEmpty( this->prevDir ) || !System::IO::Directory::Exists( this->prevDir ) ) + { + dlg->InitialDirectory = System::Environment::GetFolderPath( System::Environment::SpecialFolder::Desktop ); + } + else + { + dlg->InitialDirectory = this->prevDir; + } + dlg->Filter = filter; + dlg->FilterIndex = 1; + dlg->RestoreDirectory = true; + + if( dlg->ShowDialog() != System::Windows::Forms::DialogResult::OK ) + { + return nullptr; + } + this->prevDir = System::IO::Path::GetDirectoryName( dlg->FileName ); + retfile = dlg->FileName; + if( !System::String::IsNullOrEmpty(extension) && !(dlg->FileName->EndsWith( extension )) ) + { + retfile += extension; + } + return retfile; +} + +// セーブするディレクトリをダイアログで取得 +// @ret 取得したディレクトリ名(\\で終わるように調整される) エラーのときnullptr +System::String^ Form1::saveDirDlg( System::String ^msgJ, System::String ^msgE ) +{ + System::String ^dir; + System::Windows::Forms::FolderBrowserDialog ^dlg = gcnew (System::Windows::Forms::FolderBrowserDialog); + + if( this->isEnglish() && msgE ) + { + dlg->Description = msgE; + } + else if( msgJ ) + { + dlg->Description = msgJ; + } + + if( dlg->ShowDialog() != System::Windows::Forms::DialogResult::OK ) + { + return nullptr; + } + + if( !dlg->SelectedPath->EndsWith("\\") ) + { + dir = dlg->SelectedPath + "\\"; + } + else + { + dir = System::String::Copy(dlg->SelectedPath); + } + return dir; +} + +// ファイルが存在するかを調べて上書き確認をする +bool Form1::isOverwriteFile( System::String ^path ) +{ + if( System::IO::File::Exists( path ) ) + { + System::String ^msg; + if( this->isJapanese() ) + { + msg = gcnew System::String( path + "はすでに存在します。上書きしますか?" ); + } + else + { + msg = gcnew System::String( path + "already exists. Overwrite it?" ); + } + + if( MessageBox::Show( msg, "Information", MessageBoxButtons::YesNo, MessageBoxIcon::None ) + == System::Windows::Forms::DialogResult::No ) + { + return false; + } + } + return true; // ファイルが存在しない場合 || 上書きOKの場合 ファイルを作成してもよい +} + + // end of file \ No newline at end of file diff --git a/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/MasterEditorTWL.vcproj b/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/MasterEditorTWL.vcproj index 948c5d4..7431d98 100644 --- a/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/MasterEditorTWL.vcproj +++ b/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/MasterEditorTWL.vcproj @@ -247,6 +247,14 @@ RelativePath=".\MasterEditorTWL.cpp" > + + + + @@ -334,6 +342,14 @@ RelativePath=".\resource.h" > + + + + diff --git a/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/split_tad.cpp b/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/split_tad.cpp new file mode 100644 index 0000000..9f00e7a --- /dev/null +++ b/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/split_tad.cpp @@ -0,0 +1,275 @@ +#include "stdafx.h" +#include "twl/types.h" +#include +#include +#include "split_tad.h" +#include "split_tad_util.h" + + +// ------------------------------------------------------ +// 宣言と定数 +// ------------------------------------------------------ + +// internal functions +cli::array^ readTitleKey( cli::array ^ticket ); +cli::array^ decCBC( cli::array ^ Key, cli::array ^ IV, cli::array ^cipherText ); +cli::array ^readContentsInfo( cli::array ^tmd ); + +// tad外し用の鍵 +const u8 commonKey[] = +{ + 0xA1,0x60,0x4A,0x6A,0x71,0x23,0xB5,0x29,0xAE,0x8B,0xEC,0x32,0xC8,0x16,0xFC,0xAA +}; + + +// ------------------------------------------------------ +// tad外し処理本体 +// ------------------------------------------------------ + +// +// tad ファイルから srl(0番目のコンテンツ)を抜き出す +// (split_tad_dev.pl の移植) +// +// @arg [in] 入力 tad ファイル名 +// @arg [out] 出力 srl ファイル名 +// +// @ret 成功したとき0 失敗したら負の値 +// +int splitTad( System::String ^tadpath, System::String ^srlpath ) +{ + FILE *fp = NULL; + const char *pchFilename = + (const char*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi( tadpath ).ToPointer(); + + if( fopen_s( &fp, pchFilename, "rb" ) != NULL ) + { + return -1; + } + + cli::array ^mbuf = subStr( fp, 0, 32 ); + + u32 hdrSize = reverseEndian( unpack32(mbuf, 0) ); // 基本的にビッグエンディアン + u16 tadType = reverseEndian( unpack16(mbuf, 4) ); + u16 tadVersion = reverseEndian( unpack16(mbuf, 6) ); + u32 certSize = reverseEndian( unpack32(mbuf, 8) ); + u32 crlSize = reverseEndian( unpack32(mbuf, 12) ); + u32 ticketSize = reverseEndian( unpack32(mbuf, 16) ); + u32 tmdSize = reverseEndian( unpack32(mbuf, 20) ); + u32 contentSize = reverseEndian( unpack32(mbuf, 24) ); + u32 metaSize = reverseEndian( unpack32(mbuf, 28) ); + + printf( "hdrSize %d\n", hdrSize ); + printf( "tadType %c%c\n", tadType>>8, tadType&0xFF ); + printf( "tadVersion %d\n", tadVersion ); + printf( "certSize %d\n", certSize ); + printf( "crlSize %d\n", crlSize ); + printf( "ticketSize %d\n", ticketSize ); + printf( "tmdSize %d\n", tmdSize ); + printf( "contentSize %d\n", contentSize ); + printf( "metaSize %d\n", metaSize ); + + u32 certOffset = roundUp( hdrSize, 64); + u32 crlOffset = roundUp( certOffset + certSize, 64); + u32 ticketOffset = roundUp( crlOffset + crlSize, 64); + u32 tmdOffset = roundUp( ticketOffset + ticketSize, 64); + u32 contentOffset = roundUp( tmdOffset + tmdSize, 64); + u32 metaOffset = roundUp( contentOffset + contentSize, 64); + u32 fileSize = roundUp( metaOffset + metaSize, 64); + + fseek( fp, 0, SEEK_END ); + u32 orgFileSize = ftell( fp ); + if( fileSize != orgFileSize ) + { + printf( "file size is not expected size(=%d)", fileSize ); + fclose( fp ); + return -1; + } + cli::array ^ticket = subStr( fp, ticketOffset, ticketSize ); + cli::array ^tmd = subStr( fp, tmdOffset, tmdSize ); + cli::array ^content = subStr( fp, contentOffset, contentSize ); + + //saveFile( "cert.bin", subStr( fp, certOffset, certSize ) ); + //saveFile( "crl.bin", subStr( fp, crlOffset, crlSize ) ); + //saveFile( "ticket.bin", ticket ); + //saveFile( "tmd.bin", tmd ); + //saveFile( "meta.bin", subStr( fp, metaOffset, metaSize ) ); + + cli::array ^title_key = readTitleKey( ticket ); + cli::array ^rci = readContentsInfo( tmd ); + dumpBytes( title_key ); + + // 通常は tad は srl (コンテンツ No.0) しか含まないが + // マルチコンテンツ を含む場合のために No.1 以降も別ファイルとして保存する + // srl 名が out.srl のとき out_1.bin out_2.bin ... として出力する + System::String ^srl_dir = System::IO::Path::GetDirectoryName( srlpath ); // 格納ディレクトリ名 + System::String ^srl_prefix = System::IO::Path::GetFileNameWithoutExtension( srlpath ); // 拡張子よりも前のファイル名 + System::String ^srl_ext = System::IO::Path::GetExtension( srlpath ); // 拡張子 + + int result = 0; + u32 offset = 0; + for each( rcContentsInfo ^ci in rci ) + { + u32 size = roundUp( (u32)ci->size, 16 ); + cli::array ^enc_content_x = subStr( content, offset, size ); + cli::array ^content_x_iv = resizeBytes( pack16( reverseEndian(ci->idx) ), 14 ); // ビッグエンディアンにしておく + cli::array ^dec_content_x = decCBC( title_key, content_x_iv, enc_content_x ); + cli::array ^dec_content = subStr( dec_content_x, 0, ci->size ); + System::Security::Cryptography::SHA1 ^sha1 = gcnew System::Security::Cryptography::SHA1Managed(); + cli::array ^hash = sha1->ComputeHash( dec_content ); + + dumpBytes( hash ); + pin_ptr calc = &hash[0]; // 計算で求めたハッシュ + pin_ptr extr = &ci->hash[0]; // 抽出したハッシュ + if( memcmp( calc, extr, 20 ) == 0 ) + { + printf( "hash OK\n" ); + } + else + { + printf( "hash mismatch\n" ); + result = -1; // エラーとする 中断はせず最後まで作成 + } + + //saveFile( "content_" + ci->idx.ToString() + ".encrypted.bin", enc_content_x ); + //saveFile( "content_" + ci->idx.ToString() + ".bin", dec_content ); + if( ci->idx == 0 ) + { + saveFile( srlpath, dec_content ); // コンテンツ No.0 が srl にあたる + } + else + { + System::String ^tmppath = srl_dir + "\\" + srl_prefix + "_" + ci->idx.ToString() + ".bin"; + saveFile( tmppath, dec_content ); + } + offset += roundUp( size, 64 ); + } + fclose( fp ); + return result; +} + +// ------------------------------------------------------ +// internal functions +// ------------------------------------------------------ + +// +// title_key の復号 +// +// @ret title_key のバイト列 +// +cli::array^ readTitleKey( cli::array ^ticket ) +{ + cli::array ^encTitleKey = subStr( ticket, 0x1BF, 16 ); + cli::array ^IV = resizeBytes( subStr( ticket, 0x1DC, 8 ), 8 ); // 16バイトに拡張してケツの8バイトを0で埋める + + cli::array ^comKey = gcnew cli::array(16); + pin_ptr pComKey = &comKey[0]; + memcpy( pComKey, commonKey, 16 ); + + cli::array ^plain; + try + { + plain = decCBC( comKey, IV, encTitleKey ); + } + catch (System::Exception ^ e) + { + System::Console::WriteLine("Exception in readTitleKey(): {0}", e->Message); + } + return plain; +} + +// +// tmd から各コンテンツファイルの情報を抜き出す +// +// @ret 各コンテンツファイルの情報をまとめた Array +// +cli::array ^readContentsInfo( cli::array ^tmd ) +{ + u16 nContent = reverseEndian( unpack16(tmd, 0x1DE) ); + cli::array ^ci = gcnew cli::array( nContent ); + + u16 i; + for( i=0; i < nContent; i++ ) + { + u32 offset = 0x1E4 + 36*i; + ci[i] = gcnew rcContentsInfo; + ci[i]->cid = reverseEndian( unpack32(tmd, offset) ); + ci[i]->idx = reverseEndian( unpack16(tmd, offset + 4) ); + ci[i]->type = reverseEndian( unpack16(tmd, offset + 6) ); + ci[i]->size = reverseEndian( unpack32(tmd, offset + 12) ); + ci[i]->hash = subStr( tmd, offset + 16, 20 ); + } + return ci; +} + +// +// AES復号 : System::Security::Cryptography::RijndaelManaged のヘルプのサンプルをコピペ +// +// @ret 復号後のデータ +// +cli::array^ decCBC( cli::array ^ Key, cli::array ^ IV, cli::array ^cipherText ) +{ + // Check arguments. + if (!cipherText || cipherText->Length <= 0) + throw gcnew System::ArgumentNullException("cipherText"); + if (!Key || Key->Length <= 0) + throw gcnew System::ArgumentNullException("Key"); + if (!IV || IV->Length <= 0) + throw gcnew System::ArgumentNullException("Key"); + + // TDeclare the streams used + // to decrypt to an in memory + // array of bytes. + System::IO::MemoryStream ^msDecrypt; + System::Security::Cryptography::CryptoStream ^csDecrypt; + + // Declare the RijndaelManaged object + // used to decrypt the data. + System::Security::Cryptography::RijndaelManaged ^aesAlg; + + // Declare the string used to hold + // the decrypted text. + cli::array ^plain = gcnew cli::array(cipherText->Length); + + try + { + // Create a RijndaelManaged object + // with the specified key and IV. + aesAlg = gcnew System::Security::Cryptography::RijndaelManaged(); + aesAlg->Mode = System::Security::Cryptography::CipherMode::CBC; // CBCモード + aesAlg->Key = Key; + aesAlg->IV = IV; + aesAlg->Padding = System::Security::Cryptography::PaddingMode::Zeros; + + // Create a decrytor to perform the stream transform. + System::Security::Cryptography::ICryptoTransform ^ decryptor + = aesAlg->CreateDecryptor(aesAlg->Key, aesAlg->IV); + + // Create the streams used for decryption. + msDecrypt = gcnew System::IO::MemoryStream(cipherText); + csDecrypt = gcnew System::Security::Cryptography::CryptoStream + (msDecrypt, decryptor, System::Security::Cryptography::CryptoStreamMode::Read); + csDecrypt->Read( plain, 0, cipherText->Length ); + //srDecrypt = gcnew System::IO::StreamReader(csDecrypt); + + //// Read the decrypted bytes from the decrypting stream + //// and place them in a string. + //plaintext = srDecrypt->ReadToEnd(); + } + finally + { + // Clean things up. + + // Close the streams. + if (csDecrypt) + csDecrypt->Close(); + if (msDecrypt) + msDecrypt->Close(); + + // Clear the RijndaelManaged object. + if (aesAlg) + aesAlg->Clear(); + } + return plain; +} + +// end of file diff --git a/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/split_tad.h b/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/split_tad.h new file mode 100644 index 0000000..b08bdb0 --- /dev/null +++ b/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/split_tad.h @@ -0,0 +1,80 @@ +#pragma once + +#include "twl/types.h" +#include +#include + + +// ------------------------------------------------------ +// APIs +// ------------------------------------------------------ + +// +// tad ファイルから srl(0番目のコンテンツ)を抜き出す +// (split_tad_dev.pl の移植) +// +// @arg [in] 入力 tad ファイルのパス +// @arg [out] 出力 srl ファイルのパス +// +// @ret 成功したとき0 失敗したら負の値 +// +int splitTad( System::String ^tadpath, System::String ^srlpath ); + + +// ------------------------------------------------------ +// 内部処理用の構造体(プロトタイプ宣言できないのでヘッダに置く) +// ------------------------------------------------------ + +// コンテンツ情報の構造体 +ref class rcContentsInfo +{ +private: + System::UInt32 ^h_cid; + System::UInt16 ^h_idx; + System::UInt16 ^h_type; + System::UInt32 ^h_size; + cli::array ^h_hash; +public: + rcContentsInfo() + { + this->h_cid = gcnew System::UInt32; // 解放の必要なし + this->h_idx = gcnew System::UInt16; + this->h_type = gcnew System::UInt16; + this->h_size = gcnew System::UInt32; + this->h_hash = gcnew cli::array(20); // 固定長 + } +public: + property System::UInt32 cid + { + void set( System::UInt32 v ){ *this->h_cid = v; }; + System::UInt32 get(void){ return *this->h_cid; } + } + property System::UInt16 idx + { + void set( System::UInt16 v ){ *this->h_idx = v; }; + System::UInt16 get(void){ return *this->h_idx; } + } + property System::UInt16 type + { + void set( System::UInt16 v ){ *this->h_type = v; }; + System::UInt16 get(void){ return *this->h_type; } + } + property System::UInt32 size + { + void set( System::UInt32 v ){ *this->h_size = v; }; + System::UInt32 get(void){ return *this->h_size; } + } + property cli::array ^hash + { + void set( cli::array ^h ) + { + cli::array::Copy( h, this->h_hash, 20 ); + } + cli::array ^get(void) + { + cli::array ^cp = gcnew cli::array(20); // コピーを返す + cli::array::Copy( this->h_hash, cp, 20 ); + return cp; + } + } +}; diff --git a/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/split_tad_util.cpp b/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/split_tad_util.cpp new file mode 100644 index 0000000..7af50c7 --- /dev/null +++ b/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/split_tad_util.cpp @@ -0,0 +1,186 @@ +#include "stdafx.h" +#include "twl/types.h" +#include +#include +#include "split_tad_util.h" + + +// ------------------------------------------------------------------------ +// 部分バイト列を抜き出す +// ------------------------------------------------------------------------ + +// @ret 抜き出したバイト列 +cli::array^ subStr( FILE *fp, const int offset, const int size ) +{ + if( size <= 0 ) + { + return nullptr; + } + cli::array ^mbuf = gcnew cli::array(size); // メモリ解放の必要なし + pin_ptr buf = &mbuf[0]; // fread が unmanaged 配列を引数にするので変換 + + (void)fseek( fp, offset, SEEK_SET ); + if( fread( buf, 1, size, fp ) != size ) + { + return nullptr; + } + return mbuf; // managed のほうを返す +} + +// @ret 抜き出したバイト列 +cli::array^ subStr( cli::array ^bytes, const int offset, const int size ) +{ + cli::array ^sub = gcnew cli::array(size); + + cli::array::Copy( bytes, offset, sub, 0, size ); + return sub; +} + +// ------------------------------------------------------------------------ +// ファイルを作成してバイト列を格納する +// ------------------------------------------------------------------------ + +// @ret 成功したら0 失敗したら負の値 +int saveFp( FILE *fp, cli::array ^bytes ) +{ + if( bytes == nullptr ) + { + return 0; // 空のファイルをつくりたいということなので正常終了とみなす + } + pin_ptr tmp = &bytes[0]; // array型はふつうの配列ではないのでバイト配列に変換 + int size = bytes->Length; + + if( fwrite( tmp, 1, size, fp ) != size ) + { + return -1; + } + return 0; +} + +// @ret 成功したら0 失敗したら負の値 +int saveFile( System::String ^filename, cli::array ^bytes ) +{ + FILE *fp = NULL; + const char *pchFilename = + (const char*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi( filename ).ToPointer(); + + // ファイルにROMヘッダをライト + if( fopen_s( &fp, pchFilename, "wb" ) != NULL ) // 同名ファイルを削除して新規にライト・バイナリ + { + return -1; + } + fseek( fp, 0, SEEK_SET ); + int r = saveFp( fp, bytes ); + fclose( fp ); + + return r; +} + +// ------------------------------------------------------------------------ +// エンディアンを逆転させる(tadはビッグエンディアンなのであったほうが便利) +// ------------------------------------------------------------------------ + +// @ret エンディアン逆転後の値 +u32 reverseEndian( const u32 v ) +{ + u32 ret = (v<<24) | ((v<<8) & 0x00FF0000) | ((v>>8) & 0x0000FF00) | (v>>24); + return ret; +} + +u16 reverseEndian( const u16 v ) +{ + u16 ret = (v<<8) | (v>>8); + return ret; +} + +// ------------------------------------------------------------------------ +// 多バイト値をバイト列に変換(リトルエンディアン) +// *** perlのpackを意識 *** +// ------------------------------------------------------------------------ + +// @ret 変換後のバイト列 +cli::array ^pack32( u32 v ) +{ + cli::array ^bytes = gcnew cli::array(4); + bytes[0] = v & 0xFF; + bytes[1] = (v >> 8) & 0xFF; + bytes[2] = (v >> 16) & 0xFF; + bytes[3] = (v >> 24) & 0xFF; + return bytes; +} + +cli::array ^pack16( u16 v ) +{ + cli::array ^bytes = gcnew cli::array(2); + bytes[0] = v & 0xFF; + bytes[1] = v >>8; + return bytes; +} + +// ------------------------------------------------------------------------ +// バイト列の部分バイト列から多バイト値として解釈(リトルエンディアン) +// *** perlのunpackを意識 *** +// ------------------------------------------------------------------------ + +// @arg [in] バイト列 +// @arg [in] 何バイト目からを多バイト値とみなすか +// @ret 解釈した後の多バイト値 +u32 unpack32( cli::array ^bytes, const int index ) +{ + pin_ptr tmp = &bytes[0]; + u32 v = (u32)*((u32*)(tmp+index)); + return v; +} + +u16 unpack16( cli::array ^bytes, const int index ) +{ + pin_ptr tmp = &bytes[0]; + u16 v = (u16)*((u16*)(tmp+index)); + return v; +} + +// ------------------------------------------------------------------------ +// 丸める +// ------------------------------------------------------------------------ + +u32 roundUp( const u32 v, const u32 align ) +{ + u32 r = ((v + align - 1) / align) * align; + return r; +} + +u16 roundUp( const u16 v, const u16 align ) +{ + u16 r = ((v + align - 1) / align) * align; + return r; +} + +// ------------------------------------------------------------------------ +// バイト列の長さを拡張して末尾を0で埋める +// (0x12345678 => 0x1234567800000000) +// ------------------------------------------------------------------------ + +// @arg [in] 拡張前のバイト列 +// @arg [in] 何バイト拡張するか(拡張分だけを指定 例えば4バイトを5バイトにする場合には1を指定) +// @ret 拡張後のバイト列(新たなバイト列を内部で生成) +cli::array ^resizeBytes( cli::array ^org, const int difSize ) +{ + cli::array ^r = gcnew cli::array( org->Length + difSize ); + cli::array::Copy( org, 0, r, 0, org->Length ); + return r; +} + +// ------------------------------------------------------------------------ +// バイト列を16進で表示 +// ------------------------------------------------------------------------ + +void dumpBytes( cli::array ^bytes ) +{ + for each( System::Byte b in bytes ) + { + printf( "%02x", b ); + } + printf( "\n" ); +} + +// end of file diff --git a/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/split_tad_util.h b/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/split_tad_util.h new file mode 100644 index 0000000..354eeac --- /dev/null +++ b/build/tools/MasterEditor/MasterEditorTWL/MasterEditorTWL/split_tad_util.h @@ -0,0 +1,73 @@ +#pragma once + +#include "twl/types.h" +#include +#include + + +// ------------------------------------------------------------------------ +// 部分バイト列を抜き出す +// ------------------------------------------------------------------------ + +// @ret 抜き出したバイト列 +cli::array^ subStr( FILE *fp, const int offset, const int size ); +cli::array^ subStr( cli::array ^bytes, const int offset, const int size ); + +// ------------------------------------------------------------------------ +// ファイルを作成してバイト列を格納する +// ------------------------------------------------------------------------ + +// @ret 成功したら0 失敗したら負の値 +int saveFp( FILE *fp, cli::array ^bytes ); +int saveFile( System::String ^filename, cli::array ^bytes ); + +// ------------------------------------------------------------------------ +// エンディアンを逆転させる(tadはビッグエンディアンなのであったほうが便利) +// ------------------------------------------------------------------------ + +// @ret エンディアン逆転後の値 +u32 reverseEndian( const u32 v ); +u16 reverseEndian( const u16 v ); + +// ------------------------------------------------------------------------ +// 多バイト値をバイト列に変換(リトルエンディアン) +// *** perlのpackを意識 *** +// ------------------------------------------------------------------------ + +// @ret 変換後のバイト列 +cli::array ^pack32( u32 v ); +cli::array ^pack16( u16 v ); + +// ------------------------------------------------------------------------ +// バイト列の部分バイト列から多バイト値として解釈(リトルエンディアン) +// *** perlのunpackを意識 *** +// ------------------------------------------------------------------------ + +// @arg [in] バイト列 +// @arg [in] 何バイト目からを多バイト値とみなすか +// @ret 解釈した後の多バイト値 +u32 unpack32( cli::array ^bytes, const int index ); +u16 unpack16( cli::array ^bytes, const int index ); + +// ------------------------------------------------------------------------ +// 丸める +// ------------------------------------------------------------------------ + +u32 roundUp( const u32 v, const u32 align ); +u16 roundUp( const u16 v, const u16 align ); + +// ------------------------------------------------------------------------ +// バイト列の長さを拡張して末尾を0で埋める +// (0x12345678 => 0x1234567800000000) +// ------------------------------------------------------------------------ + +// @arg [in] 拡張前のバイト列 +// @arg [in] 何バイト拡張するか(拡張分だけを指定 例えば4バイトを5バイトにする場合には1を指定) +// @ret 拡張後のバイト列(新たなバイト列を内部で生成) +cli::array ^resizeBytes( cli::array ^org, const int difSize ); + +// ------------------------------------------------------------------------ +// バイト列を16進で表示 +// ------------------------------------------------------------------------ +void dumpBytes( cli::array ^bytes ); +