static ImageUtilOAM.animedata ImportObjImageToData(string imagefilename , string basedir , Dictionary <string, ImageUtilOAM.animedata> animeDic , ImageUtilOAM.ImportOAM oam , ref uint image_number , out string errormessage ) { string key = "OBJ" + imagefilename; ImageUtilOAM.animedata magic_animedata; if (animeDic.ContainsKey(key)) { errormessage = ""; magic_animedata = animeDic[key]; return(magic_animedata); } string hash = ImageUtil.HashBitmap(imagefilename, basedir); magic_animedata = ImageUtilOAM.FindHash(hash, animeDic); if (magic_animedata != null) { errormessage = ""; return(magic_animedata); } Bitmap loadbitmap = ImageUtil.OpenBitmap(ImageUtilMagicFEditor.GetFullPath(imagefilename, basedir), null, out errormessage); if (loadbitmap == null) { return(null); } int width = ImageUtilMagicFEditor.SRC_OBJ_SEAT_TILE_WIDTH * 8 - 16; int height = ImageUtilMagicFEditor.SRC_OBJ_SEAT_TILE_HEIGHT * 8; if (loadbitmap.Width < width || loadbitmap.Height < height) { errormessage = R.Error("画像サイズが正しくありません。\r\nWidth:{2} Height:{3} でなければなりません。\r\n\r\n選択された画像のサイズ Width:{0} Height:{1}", loadbitmap.Width, loadbitmap.Height, width, height, imagefilename); loadbitmap.Dispose(); return(null); } magic_animedata = oam.MakeMagicAnime(imagefilename); if (magic_animedata == null) { errormessage = oam.ErrorMessage; loadbitmap.Dispose(); return(null); } magic_animedata.image_number = image_number++; magic_animedata.imageHash = hash; animeDic[key] = magic_animedata; errormessage = ""; loadbitmap.Dispose(); return(magic_animedata); }
public string BattleAnimeImportDirect(uint id, string filename) { if (InputFormRef.IsPleaseWaitDialog(this)) {//2重割り込み禁止 return(R._("現在他の処理中です")); } if (id <= 0) { return(R._("指定されたID({0})は存在しません。", U.To0xHexString(id))); } uint battleanime_baseaddress = N_InputFormRef.IDToAddr(id - 1); if (battleanime_baseaddress == U.NOT_FOUND) { return(R._("指定されたID({0})は存在しません。", U.To0xHexString(id))); } string error = ""; //少し時間がかかるので、しばらくお待ちください表示. using (InputFormRef.AutoPleaseWait pleaseWait = new InputFormRef.AutoPleaseWait(this)) { uint top_battleanime_baseaddress = N_InputFormRef.BaseAddress; uint bottum_battleanime_baseaddress = N_InputFormRef.BaseAddress + (N_InputFormRef.BlockSize * N_InputFormRef.DataCount); string ext = U.GetFilenameExt(filename); if (ext == ".TXT") {//テキスト形式 error = ImageUtilOAM.ImportBattleAnime(filename , battleanime_baseaddress , top_battleanime_baseaddress , bottum_battleanime_baseaddress); } else if (ext == "" || ext == ".BIN") {//拡張子なし FEditorシリアライズ error = ImageUtilOAM.ImportBattleAnimeOnFEditorSerialize(filename , battleanime_baseaddress , top_battleanime_baseaddress , bottum_battleanime_baseaddress); } else { return(R._("未対応の拡張子({0})が指定されました。", ext)); } } if (error != "") { return(error); } //選択しているところを再選択して画面を再描画 U.ReSelectList(N_AddressList); //書き込み通知 InputFormRef.ShowWriteNotifyAnimation(this, battleanime_baseaddress); return(""); }
void UpdateLZ77Info() { string error = ""; string text = "Un-LZ77 "; uint frame = U.toOffset((uint)N_P16.Value); uint oam = U.toOffset((uint)N_P20.Value); if (U.isSafetyOffset(frame)) { uint size = LZ77.getUncompressSize(Program.ROM.Data, frame); text += "Frame: " + size + " "; string r = ImageUtilOAM.checkFrameSizeSimple((int)size); if (r != "") { error += r; } } if (U.isSafetyOffset(oam)) { uint size = LZ77.getUncompressSize(Program.ROM.Data, oam); text += "OAM: " + size + " "; string r = ImageUtilOAM.checkOAMSizeSimple((int)size); if (r != "") { error += r; } } X_LZ77_INFO.Text = text; X_LZ77_INFO.ErrorMessage = error; }
//変更するアニメデータから、他のアニメーションでも使っているものを除外する public static void MakeAllDataLength(RecycleAddress ra, uint Now_baseaddress) { InputFormRef N_InputFormRef = N_Init(null); //戦闘アニメーションはlz77圧縮の中にポインタがある特殊形式です uint addr = N_InputFormRef.BaseAddress; for (int i = 0; i < N_InputFormRef.DataCount; i++, addr += N_InputFormRef.BlockSize) { if (!U.isSafetyOffset(12 + addr + 4)) { break; } uint section = Program.ROM.p32(12 + addr); if (!U.isSafetyOffset(section)) { break; } if (addr == Now_baseaddress) { continue; } List <Address> list = new List <Address>(); ImageUtilOAM.RecycleOldAnime(ref list, addr); ra.SubRecycle(list); } }
//エラーチェック public static void MakeCheckError(List <FELint.ErrorSt> errors) { InputFormRef N_InputFormRef = N_Init(null); bool isFE6 = (Program.ROM.RomInfo.version == 6); if (!isFE6) {//FE6の場合、パラディンなどが手斧モーションを持っていない. //そのため、FE7,FE8だけチェックします. InputFormRef InputFormRef = Init(null); List <U.AddrResult> handAxsItems = ItemForm.MakeItemListByHandAxs(); List <U.AddrResult> classList = ClassForm.MakeClassList(); for (uint cid = 1; cid < classList.Count; cid++) { uint pointer; uint class_addr = classList[(int)cid].addr; uint addr = ClassForm.GetBattleAnimeAddrWhereAddr(class_addr, out pointer); if (addr == 0) { continue; } if (!U.isSafetyOffset(addr)) { errors.Add(new FELint.ErrorSt(FELint.Type.CLASS, class_addr , R._("クラス({0})の{1}のポインタ({2})が危険です。" , classList[(int)cid].name, R._("戦闘アニメ"), U.To0xHexString(addr)), cid)); continue; } InputFormRef.ReInit(addr); MakeCheckErrorAxs(InputFormRef, N_InputFormRef , handAxsItems, classList, cid, errors); } } { if (N_InputFormRef.DataCount < 10) { errors.Add(new FELint.ErrorSt(FELint.Type.BATTLE_ANIME, U.NOT_FOUND , R._("戦闘アニメが極端に少ないです。破損している可能性があります。"))); } List <uint> seatNumberList = new List <uint>(256); uint p = N_InputFormRef.BaseAddress; for (int i = 0; i < N_InputFormRef.DataCount; i++, p += N_InputFormRef.BlockSize) { if (isFE6 && i == 0x6c) { continue; } ImageUtilOAM.MakeCheckError(errors, p, (uint)(i), seatNumberList); } } }
private void X_N_JumpEditor_Click(object sender, EventArgs e) { if (InputFormRef.IsPleaseWaitDialog(this)) {//2重割り込み禁止 return; } uint battleanime_baseaddress = InputFormRef.SelectToAddr(N_AddressList); if (battleanime_baseaddress == U.NOT_FOUND) { return; } uint sectionData = (uint)N_P12.Value; uint frameData = (uint)N_P16.Value; uint rightToLeftOAM = (uint)N_P20.Value; uint leftToRightOAM = (uint)N_P24.Value; uint palettes = (uint)N_P28.Value; uint ID = (uint)N_AddressList.SelectedIndex + 1; string filehint = GetBattleAnimeHint(ID); if (filehint == "") {//不明な場合、 FE7にある個別バトルにも問い合わせる filehint = UnitCustomBattleAnimeForm.GetBattleAnimeHint((uint)N_AddressList.SelectedIndex + 1); } filehint = N_AddressList.Text + " " + filehint; int palette_count = ImageUtilOAM.CalcMaxPaletteCount(sectionData, frameData, rightToLeftOAM, palettes); //少し時間がかかるので、しばらくお待ちください表示. using (InputFormRef.AutoPleaseWait pleaseWait = new InputFormRef.AutoPleaseWait(this)) //テンポラリディレクトリを利用する using (U.MakeTempDirectory tempdir = new U.MakeTempDirectory()) { string filename = Path.Combine(tempdir.Dir, "anime.txt"); ImageUtilOAM.ExportBattleAnime("", false, filename , sectionData, frameData, rightToLeftOAM, palettes, palette_count); if (!File.Exists(filename)) { R.ShowStopError("アニメーションエディタを表示するために、アニメーションをエクスポートしようとしましたが、アニメをファイルにエクスポートできませんでした。\r\n\r\nファイル:{0}", filename); return; } byte[] paletteBIN = LZ77.decompress(Program.ROM.Data, U.toOffset(palettes)); ToolAnimationCreatorForm f = (ToolAnimationCreatorForm)InputFormRef.JumpFormLow <ToolAnimationCreatorForm>(); f.Init(ToolAnimationCreatorUserControl.AnimationTypeEnum.BattleAnime , ID, filehint, filename, paletteBIN); f.Show(); f.Focus(); } }
static uint All_ToolAutoGenLeftToRightAllAnimation(InputFormRef.AutoPleaseWait pleaseWait, Undo.UndoData undodata) { uint totalSize = 0; //テーブル拡張などで同じOAMが複数個所にある場合の対処 Dictionary <uint, uint> convertHistory = new Dictionary <uint, uint>(); InputFormRef N_InputFormRef = N_Init(null); uint addr = N_InputFormRef.BaseAddress; for (uint i = 0; i < N_InputFormRef.DataCount; i++, addr += N_InputFormRef.BlockSize) { uint rightToLeftOAMAddress = Program.ROM.p32(addr + 20); uint leftToRightOAMAddress = Program.ROM.p32(addr + 24); if (rightToLeftOAMAddress == leftToRightOAMAddress) {//処理済み continue; } //実はさっき処理していますか? //D拡張などで同じデータが複数個ある場合への配慮. uint convertAddress; if (convertHistory.TryGetValue(leftToRightOAMAddress, out convertAddress)) { Program.ROM.write_p32(addr + 24, convertAddress, undodata); continue; } byte[] rightToLeftOAMBin = LZ77.decompress(Program.ROM.Data, rightToLeftOAMAddress); byte[] leftToRightOAMBin = LZ77.decompress(Program.ROM.Data, leftToRightOAMAddress); List <byte> rightToLeftOAMArray = new List <byte>(rightToLeftOAMBin); List <byte> leftToRightOAMArray = new List <byte>(leftToRightOAMBin); if (!ImageUtilOAM.IsMatchOAM(rightToLeftOAMArray, leftToRightOAMArray)) {//鏡写しではないので、自動生成できません。 continue; } pleaseWait.DoEvents(R._("{0} 削減サイズ:{1}", U.To0xHexString(i), totalSize)); //データを自動生成できるので、ポインタを共有します Program.ROM.write_p32(addr + 24, rightToLeftOAMAddress, undodata); //不要なデータを消去します uint leftToRightOAMSize = LZ77.getCompressedSize(Program.ROM.Data, leftToRightOAMAddress); Program.ROM.write_fill(leftToRightOAMAddress, leftToRightOAMSize, 0, undodata); convertHistory[leftToRightOAMAddress] = rightToLeftOAMAddress; totalSize += leftToRightOAMSize; } return(totalSize); }
static bool HasMagicMotion(InputFormRef N_ifr , uint battleAnimationID) { uint battleAnimationIDMinus1 = battleAnimationID - 1; if (battleAnimationIDMinus1 >= N_ifr.DataCount) { return(false); } uint p = N_ifr.BaseAddress + (battleAnimationIDMinus1 * N_ifr.BlockSize); return(ImageUtilOAM.HasMagicMotion(p)); }
//全データの取得 public static void MakeAllDataLength(List <Address> list, bool isPointerOnly) { string selfname; InputFormRef InputFormRef = Init(null); uint addr; List <U.AddrResult> classList = ClassForm.MakeClassList(); for (uint cid = 0; cid < classList.Count; cid++) { uint pointer; uint class_addr = classList[(int)cid].addr; addr = ClassForm.GetBattleAnimeAddrWhereAddr(class_addr, out pointer); if (!U.isSafetyOffset(addr)) { continue; } InputFormRef.ReInitPointer(pointer); selfname = "BattleAnimeSeting:" + U.To0xHexString(cid); FEBuilderGBA.Address.AddAddress(list, InputFormRef , selfname, new uint[] { }); } selfname = "BattleAnime"; InputFormRef N_InputFormRef = N_Init(null); FEBuilderGBA.Address.AddAddress(list, N_InputFormRef, selfname, new uint[] { 12, 16, 20, 24, 28 }); //戦闘アニメーションはlz77圧縮の中にポインタがある特殊形式です addr = N_InputFormRef.BaseAddress; List <uint> seatNumberList = new List <uint>(256); for (int i = 0; i < N_InputFormRef.DataCount; i++, addr += N_InputFormRef.BlockSize) { if (!U.isSafetyOffset(12 + addr + 4)) { break; } uint section = Program.ROM.p32(12 + addr); if (!U.isSafetyOffset(section)) { break; } selfname = "BattleAnime:" + U.To0xHexString(i + 1); ImageUtilOAM.MakeAllDataLength(list, isPointerOnly, selfname, addr, seatNumberList); } }
void UpdateLZ77Info(bool errorOver16Anime) { string error = ""; string text = "Un-LZ77 "; uint frame = U.toOffset((uint)N_P16.Value); uint oam = U.toOffset((uint)N_P20.Value); if (U.isSafetyOffset(frame)) { uint size = LZ77.getUncompressSize(Program.ROM.Data, frame); text += "Frame: " + size + " "; string r = ImageUtilOAM.checkFrameSizeSimple((int)size); if (r != "") { error += r; } } if (U.isSafetyOffset(oam)) { uint size = LZ77.getUncompressSize(Program.ROM.Data, oam); text += "OAM: " + size + " "; string r = ImageUtilOAM.checkOAMSizeSimple((int)size); if (r != "") { error += r; } } if (error != "") { error = error + "\r\n" + R._("これは警告であり、エラーではありません。\r\n大きいアニメーションは動かないことがあるので警告を表示しています。\r\n警告が出ていても動作することもあります。"); } if (errorOver16Anime) { text = R._("16色を超える戦闘アニメーションです。") + " " + text; } X_LZ77_INFO.Text = text; X_LZ77_INFO.ErrorMessage = error; }
void DrawSelectedAnime() { uint showSectionData = U.atoh(ShowSectionCombo.Text) - 1; uint showFrameData = (uint)ShowFrameUpDown.Value; int paletteIndex = (int)ShowPaletteComboBox.SelectedIndex; uint sectionData = (uint)N_P12.Value; uint frameData = (uint)N_P16.Value; uint rightToLeftOAM = (uint)N_P20.Value; uint leftToRightOAM = (uint)N_P24.Value; uint palettes = (uint)N_P28.Value; if (ShowDirectionComboBox.SelectedIndex == 1) {//敵軍の位置を表示 rightToLeftOAM = leftToRightOAM; } Bitmap bitmap = ImageUtilOAM.DrawBattleAnime(showSectionData, showFrameData , sectionData, frameData, rightToLeftOAM, palettes); if (paletteIndex > 0) { bitmap = ImageUtil.SwapPalette(bitmap, paletteIndex); } bool errorOver16Anime; int palette_count = ImageUtil.GetPalette16Count(bitmap); if (palette_count >= 2) { errorOver16Anime = true; } else { errorOver16Anime = false; } UpdateLZ77Info(errorOver16Anime); X_B_ANIME_PIC2.Image = bitmap; }
void DrawSelectedAnime() { uint showSectionData = U.atoh(ShowSectionCombo.Text) - 1; uint showFrameData = (uint)ShowFrameUpDown.Value; int paletteIndex = (int)ShowPaletteComboBox.SelectedIndex; uint sectionData = (uint)N_P12.Value; uint frameData = (uint)N_P16.Value; uint rightToLeftOAM = (uint)N_P20.Value; uint leftToRightOAM = (uint)N_P24.Value; uint palettes = (uint)N_P28.Value; if (ShowDirectionComboBox.SelectedIndex == 1) {//敵軍の位置を表示 rightToLeftOAM = leftToRightOAM; } Bitmap bitmap = ImageUtilOAM.DrawBattleAnime(showSectionData, showFrameData , sectionData, frameData, rightToLeftOAM, palettes); if (paletteIndex > 0) { bitmap = ImageUtil.SwapPalette(bitmap, paletteIndex); } int palette_count = ImageUtil.GetPalette16Count(bitmap); if (palette_count >= 2) { ERROR_OVER16_ANIME.Show(); } else { ERROR_OVER16_ANIME.Hide(); } X_B_ANIME_PIC2.Image = bitmap; }
public static string Import( string filename //読み込むファイル名 , uint magic_baseaddress //魔法アニメの書き換えるアドレス ) { string basename = Path.GetFileNameWithoutExtension(filename) + "_"; string basedir = Path.GetDirectoryName(filename); List <byte> frameData = new List <byte>(); List <ImageUtilOAM.image_data> bgImagesData = new List <ImageUtilOAM.image_data>(); //変換したアニメの記録 Dictionary <string, ImageUtilOAM.animedata> animeDic = new Dictionary <string, ImageUtilOAM.animedata>(); int lineCount = 0; string[] lines = File.ReadAllLines(filename); uint image_bg_number = 0; uint image_obj_number = 0; ImageUtilOAM.ImportOAM oam = new ImageUtilOAM.ImportOAM(); oam.SetBaseDir(Path.GetDirectoryName(filename)); oam.SetIsMagicOAM(true); BGScaleMode bgScaleMode = BGScaleMode.NO; while (lineCount < lines.Length) { string line = lines[lineCount]; if (U.IsComment(line) || U.OtherLangLine(line)) { lineCount++; continue; } line = U.ClipComment(line); if (line == "") { lineCount++; continue; } InputFormRef.DoEvents(null, "Line:" + lineCount); if (line[0] == '~') { U.append_u32(frameData, 0x80000100); lineCount++; continue; } if (line[0] == 'C') {//85コマンド uint command = U.atoh(line.Substring(1)); if ((command & 0xFF) == 0x53) {//スクリプト側で自動拡大命令を入れている場合 ツールは何もしてはいけないので記録する. bgScaleMode = BGScaleMode.SCRIPT_SCALE_MODE; } uint a = (command & 0x00FFFFFF) | 0x85000000; U.append_u32(frameData, a); lineCount++; continue; } if (line[0] == 'S') {//音楽再生 uint music = U.atoh(line.Substring(1)); uint a = ((music & 0xFFFF) << 8) | 0x85000048; U.append_u32(frameData, a); lineCount++; continue; } if (line[0] != 'O' && line[0] != 'B') { //不明な命令なので無視する. lineCount++; continue; } //O objblank.png //B bg3.png //1 ImageUtilOAM.animedata objAnimeData = null; ImageUtilOAM.animedata bgAnimeData = null; uint frameSec = U.NOT_FOUND; for (int n = 1; n <= 3;) { line = lines[lineCount]; if (U.IsComment(line) || U.OtherLangLine(line)) { lineCount++; continue; } line = U.ClipComment(line); if (line == "") { lineCount++; continue; } if (U.isnum(line[0])) { if (frameSec != U.NOT_FOUND) { return(R.Error("時間指定が連続しています。\r\nO filename\r\nB filename\r\ntime\r\n\r\nFile:{0} Line:{1}\r\n", filename, lineCount + 1)); } frameSec = U.atoi(line); lineCount++; n++; continue; } string imagefilename = ImageUtilOAM.parsePFilename(line); if (imagefilename.Length <= 0) { return(R.Error("ファイル名が見つかりませんでした。\r\nFile: {0} line:{1}\r\n\r\nエラー内容:\r\n{2}", filename, lineCount, oam.ErrorMessage)); } if (line[0] == 'O') { if (objAnimeData != null) { return(R.Error("OBJ指定が連続しています。\r\nO filename\r\nB filename\r\ntime\r\n\r\nFile:{0} Line:{1}\r\n", filename, lineCount + 1)); } string errormessage; objAnimeData = ImportObjImageToData(imagefilename , basedir , animeDic , oam , ref image_obj_number , out errormessage ); if (objAnimeData == null) { return(R.Error("OBJ画像をロードできません。 \r\n{2}\r\nFile:{0} Line:{1}", filename, lineCount + 1, errormessage)); } lineCount++; n++; continue; } if (line[0] == 'B') { if (bgAnimeData != null) { return(R.Error("BG指定が連続しています。\r\nO filename\r\nB filename\r\ntime\r\n\r\nFile:{0} Line:{1}\r\n", filename, lineCount + 1)); } string errormessage; bgAnimeData = ImportBGImageToData(imagefilename , basedir , animeDic , bgImagesData , out errormessage ); if (bgAnimeData == null) { return(R.Error("BG画像をロードできません。 \r\n{2}\r\nFile:{0} Line:{1}", filename, lineCount + 1, errormessage)); } lineCount++; n++; continue; } } if (objAnimeData == null) { return(R.Error("OBJ画像がありません。 \r\nO filename\r\nB filename\r\ntime\r\n\r\nみたいに、セットで登録する必要があります。\r\nFile:{0} Line:{1}", filename, lineCount + 1)); } if (bgAnimeData == null) { return(R.Error(("IMAGE_POINTER or ZIMAGE_POINTER の指定が必要です。BG画像がありません。 \r\nO filename\r\nB filename\r\n"), filename, lineCount + 1)); } if (frameSec == U.NOT_FOUND) { return(R.Error("時間指定がありません。 \r\nO filename\r\nB filename\r\ntime\r\n\r\nみたいに、セットで登録する必要があります。\r\nFile:{0} Line:{1}", filename, lineCount + 1)); } //BGがFEditorの小さい形式だった場合、自動的に拡大命令を追加する. if (bgAnimeData.height == 64) { if (bgScaleMode == BGScaleMode.NO) {//拡大命令を付与. uint a = (0x00000153) | 0x85000000; U.append_u32(frameData, a); bgScaleMode = BGScaleMode.AUTO_SCALE_MODE; } } //0x86コマンド { uint a = (frameSec & 0xFFFF) | ((image_bg_number & 0xFF) << 16) | 0x86000000; U.append_u32(frameData, a); //+0 U.append_u32(frameData, objAnimeData.image_pointer); //+4 U.append_u32(frameData, objAnimeData.oam_pos); //+8 OBJ OAM U.append_u32(frameData, objAnimeData.oam2_pos); //+12 OBJ BG OAM U.append_u32(frameData, bgAnimeData.image_pointer); //+16 U.append_u32(frameData, objAnimeData.palette_pointer); //+20 U.append_u32(frameData, bgAnimeData.palette_pointer); //+24 U.append_u32(frameData, bgAnimeData.tsa_pointer); //+28 TSA image_bg_number++; } } InputFormRef.DoEvents(null, "Term"); if (bgScaleMode == BGScaleMode.AUTO_SCALE_MODE) {//拡大命令を自動付与していた場合、解除する. 解除しないと経験値バーが表示されない. uint a = (0x00000053) | 0x85000000; U.append_u32(frameData, a); } //終端. U.append_u32(frameData, 0x80000000); //登録完了処理 oam.Term(); Undo.UndoData undodata = Program.Undo.NewUndoData("import ", Path.GetFileName(filename)); //上書きされるアニメデータ領域を使いまわす List <Address> recycle = new List <Address>(); RecycleOldAnime(ref recycle, "", false, magic_baseaddress); RecycleAddress ra = new RecycleAddress(recycle); //書き込みます.(魔法アニメはなぜか無圧縮) ra.WriteAndWritePointer(magic_baseaddress + 4, oam.GetRightToLeftOAM(), undodata); ra.WriteAndWritePointer(magic_baseaddress + 8, oam.GetLeftToRightOAM(), undodata); //BG用にダミーのOAMを作成 //byte[] dummyOAM = ImageUtilMagicFEditor.MakeDummyOAM(image_bg_number); ra.WriteAndWritePointer(magic_baseaddress + 12, oam.GetRightToLeftOAMBG(), undodata); ra.WriteAndWritePointer(magic_baseaddress + 16, oam.GetLeftToRightOAMBG(), undodata); //BG for (int i = 0; i < bgImagesData.Count; i++) { bgImagesData[i].write_addr = ra.Write(bgImagesData[i].data, undodata); } //OBJ List <ImageUtilOAM.image_data> objImages = oam.GetImages(); for (int i = 0; i < objImages.Count; i++) { objImages[i].write_addr = ra.Write(objImages[i].data, undodata); } //画像の書き込みアドレスが決定したら、画像ポインタをかかないといけないFrameDataを更新します。 byte[] frameDataUZ = frameData.ToArray(); string errorFrame = updateFrameDataAddress(frameDataUZ, bgImagesData, objImages); if (errorFrame != "") { return(R.Error("OAMフレーム更新中にエラーが発生しました。\r\nこのエラーが頻繁に出る場合は、アニメデータと一緒にreport7zを送ってください。") + "\r\n" + errorFrame); } ra.WriteAndWritePointer(magic_baseaddress + 0, frameDataUZ, undodata); //端数の再利用的ない古いデータは0x00クリア. ra.BlackOut(undodata); Program.Undo.Push(undodata); return(""); }
static ImageUtilOAM.animedata ImportBGImageToData(string imagefilename , string basedir , Dictionary <string, ImageUtilOAM.animedata> animeDic , List <ImageUtilOAM.image_data> imagesData , out string errormessage ) { string key = "BG" + imagefilename; ImageUtilOAM.animedata magic_animedata; if (animeDic.ContainsKey(key)) { errormessage = ""; magic_animedata = animeDic[key]; return(magic_animedata); } string hash = ImageUtil.HashBitmap(imagefilename, basedir); magic_animedata = ImageUtilOAM.FindHash(hash, animeDic); if (magic_animedata != null) { errormessage = ""; return(magic_animedata); } magic_animedata = new ImageUtilOAM.animedata(); string bgfilename = ImageUtilMagicFEditor.GetFullPath(imagefilename, basedir); Bitmap loadbitmap = ImageUtil.OpenBitmap(bgfilename, null, out errormessage); if (loadbitmap == null) { return(null); } // int width = ImageUtilMagicFEditor.SRC_BG_SEAT_TILE_WIDTH * 8; // int height = ImageUtilMagicFEditor.SRC_BG_SEAT_TILE_HEIGHT * 8; int width = 240; int height = 160; if (loadbitmap.Width < width || loadbitmap.Height < height) { if ((loadbitmap.Width >= 240 && loadbitmap.Width <= 264) && (loadbitmap.Height >= 64 && loadbitmap.Height < 160)) { height = 64; //FEditor Magic Log.Notify("これはFEditorの小さいBG形式です。"); } else if ((loadbitmap.Width >= 240 && loadbitmap.Width <= 264) && loadbitmap.Height == 160) {//CSA Creator } else { errormessage = R.Error("画像サイズが正しくありません。\r\n{4}\r\nWidth:{2} Height:{3} でなければなりません。\r\n\r\n選択された画像のサイズ Width:{0} Height:{1}", loadbitmap.Width, loadbitmap.Height, width, height, imagefilename); loadbitmap.Dispose(); return(null); } } Bitmap savebitmap = ImageUtil.Copy(loadbitmap, 0, 0, width, height); byte[] image; //画像 byte[] tsa; //TSA string error_string = ImageUtil.ImageToBytePackedTSA(savebitmap, savebitmap.Width, savebitmap.Height, 0, out image, out tsa); if (error_string != "") { errormessage = error_string; loadbitmap.Dispose(); return(null); } //画像の高さを記録. BGは、FEditor=64 Scale Creator=160 と、違う. magic_animedata.height = height; //ハッシュ値 magic_animedata.imageHash = hash; //画像 magic_animedata.image_pointer = (uint)imagesData.Count; ImageUtilOAM.image_data image_data = new ImageUtilOAM.image_data(); image_data.data = image; image_data.data = LZ77.compress(image_data.data); imagesData.Add(image_data); //パレット magic_animedata.palette_pointer = (uint)imagesData.Count; ImageUtilOAM.image_data palette_data = new ImageUtilOAM.image_data(); palette_data.data = ImageUtil.ImageToPalette(savebitmap); imagesData.Add(palette_data); //TSA magic_animedata.tsa_pointer = (uint)imagesData.Count; ImageUtilOAM.image_data tsa_data = new ImageUtilOAM.image_data(); tsa_data.data = tsa; tsa_data.data = LZ77.compress(tsa_data.data); imagesData.Add(tsa_data); animeDic[key] = magic_animedata; errormessage = ""; loadbitmap.Dispose(); return(magic_animedata); }
private void BattleAnimeExportButton_Click(object sender, EventArgs e) { uint battleanime_baseaddress = InputFormRef.SelectToAddr(N_AddressList); if (battleanime_baseaddress == U.NOT_FOUND) { return; } string title = R._("保存するファイル名を選択してください"); string filter = R._("FEditorシリアライズ形式|*.bin|バトルアニメ コメントあり|*.txt|バトルアニメ コメントなし|*.txt|アニメGIF|*.gif|Dump All|*.bin|All files|*"); SaveFileDialog save = new SaveFileDialog(); save.Title = title; save.Filter = filter; Program.LastSelectedFilename.Load(this, "", save, N_L_0_SPLITSTRING_7.Text); DialogResult dr = save.ShowDialog(); if (dr != DialogResult.OK) { return; } if (save.FileNames.Length <= 0 || !U.CanWriteFileRetry(save.FileNames[0])) { return; } string filename = save.FileNames[0]; Program.LastSelectedFilename.Save(this, "", save); uint sectionData = (uint)N_P12.Value; uint frameData = (uint)N_P16.Value; uint rightToLeftOAM = (uint)N_P20.Value; uint leftToRightOAM = (uint)N_P24.Value; uint palettes = (uint)N_P28.Value; string filehint = GetBattleAnimeHint((uint)N_AddressList.SelectedIndex + 1); if (filehint == "") {//不明な場合、 FE7にある個別バトルにも問い合わせる filehint = UnitCustomBattleAnimeForm.GetBattleAnimeHint((uint)N_AddressList.SelectedIndex + 1); } filehint = N_AddressList.Text + " " + filehint; int palette_count = ImageUtilOAM.CalcMaxPaletteCount(sectionData, frameData, rightToLeftOAM, palettes); string ext = U.GetFilenameExt(save.FileName); if (save.FilterIndex == 5) { { string name = U.ChangeExtFilename(filename, ".gif"); uint showSectionData = U.atoh(ShowSectionCombo.Text) - 1; ImageUtilOAM.ExportBattleAnimeGIF(name, showSectionData , sectionData, frameData, rightToLeftOAM, palettes, palette_count); } { string name = U.ChangeExtFilename(filename, ".bin"); ImageUtilOAM.ExportBattleAnimeOnFEditorSerialize(name, battleanime_baseaddress , sectionData, frameData, rightToLeftOAM, leftToRightOAM, palettes, palette_count); } { string name = U.ChangeExtFilename(filename, ".txt"); bool enableComment = false; ImageUtilOAM.ExportBattleAnime(filehint, enableComment, name , sectionData, frameData, rightToLeftOAM, palettes, palette_count); } } else if (save.FilterIndex == 4 || ext == ".GIF") { uint showSectionData = U.atoh(ShowSectionCombo.Text) - 1; ImageUtilOAM.ExportBattleAnimeGIF(filename, showSectionData , sectionData, frameData, rightToLeftOAM, palettes, palette_count); } else if (save.FilterIndex == 0 || ext == ".BIN") { ImageUtilOAM.ExportBattleAnimeOnFEditorSerialize(filename, battleanime_baseaddress , sectionData, frameData, rightToLeftOAM, leftToRightOAM, palettes, palette_count); } else { bool enableComment = true; if (save.FilterIndex == 3) { enableComment = false; } ImageUtilOAM.ExportBattleAnime(filehint, enableComment, filename , sectionData, frameData, rightToLeftOAM, palettes, palette_count); } //エクスプローラで選択しよう U.SelectFileByExplorer(filename); }
public static Bitmap DrawBattleAnime(uint id, ScaleTrim trim = ScaleTrim.SCALE_90, uint custompalette = 0, uint showSectionData = 0, uint showFrameData = 0, int showPaletteIndex = 0) { if (id <= 0) { return(ImageUtil.BlankDummy()); } id = id - 1; //anime IDは 1 からスタート. InputFormRef InputFormRef = N_Init(null); uint addr = InputFormRef.IDToAddr(id); if (!U.isSafetyOffset(addr)) { return(ImageUtil.BlankDummy()); } uint sectionData = Program.ROM.u32(addr + 12); uint frameData = Program.ROM.u32(addr + 16); uint rightToLeftOAM = Program.ROM.u32(addr + 20); uint palettes = Program.ROM.u32(addr + 28); if (custompalette > 0) { uint p = ImageUnitPaletteForm.GetPaletteAddr(custompalette); if (U.isSafetyOffset(addr)) { palettes = p; } } Bitmap bitmap = ImageUtilOAM.DrawBattleAnime(showSectionData, showFrameData , sectionData, frameData, rightToLeftOAM, palettes); if (showPaletteIndex > 0) { bitmap = ImageUtil.SwapPalette(bitmap, showPaletteIndex); } if (trim == ScaleTrim.SCALE_48) { Bitmap trimBitmap = ImageUtil.Blank(48, 48, bitmap); ImageUtil.BitBlt(trimBitmap, 0, 0, trimBitmap.Width, trimBitmap.Height, bitmap , 125, 58); bitmap.Dispose(); return(trimBitmap); } else if (trim == ScaleTrim.SCALE_90) { Bitmap trimBitmap = ImageUtil.Blank(90, 90, bitmap); ImageUtil.BitBlt(trimBitmap, 0, 0, trimBitmap.Width, trimBitmap.Height, bitmap , 100, 30); bitmap.Dispose(); return(trimBitmap); } else if (trim == ScaleTrim.NO_BUT_FLIP) { Bitmap flipBitmap = ImageUtil.Copy(bitmap, 0, 0, bitmap.Width - 8, bitmap.Height, true); bitmap.Dispose(); return(flipBitmap); } else { return(bitmap); } }