bool WriteMapConfig(Undo.UndoData undodata) { if (this.MapStyle.SelectedIndex < 0) { return(false); } uint config_plist = this.MapEditConf[this.MapStyle.SelectedIndex].config_plist; uint chipset_address = MapPointerForm.PlistToOffsetAddr(MapPointerForm.PLIST_TYPE.CONFIG, config_plist); byte[] chipsetConfigZ = LZ77.compress(this.ConfigUZ); uint newaddr = InputFormRef.WriteBinaryData(this, (uint)ChipsetConfigAddress.Value, chipsetConfigZ, InputFormRef.get_data_pos_callback_lz77, undodata); if (newaddr == U.NOT_FOUND) { Program.Undo.Rollback(undodata); return(false); } ChipsetConfigAddress.Value = newaddr; //拡張領域に書き込んでいる可能性もあるので plstを更新する. bool r = MapPointerForm.Write_Plsit(MapPointerForm.PLIST_TYPE.CONFIG, config_plist, newaddr, undodata); if (!r) { Program.Undo.Rollback(undodata); return(false); } //書き込んだ通知. InputFormRef.ShowWriteNotifyAnimation(this, newaddr); InputFormRef.WriteButtonToYellow(this.Config_WriteButton, false); //マップエディタが開いていれば更新する MapEditorForm.UpdateMapStyleIfOpen(); return(true); }
//マップ領域のベース領域の強制割り当て public static uint PreciseMapDataArea(uint mapid) { MapPointerNewPLISTPopupForm f = (MapPointerNewPLISTPopupForm)InputFormRef.JumpFormLow <MapPointerNewPLISTPopupForm>(); f.Init(MapPointerForm.PLIST_TYPE.MAP); DialogResult dr = f.ShowDialog(); if (dr != System.Windows.Forms.DialogResult.OK) { return(0); } uint plist = f.GetSelectPLIST(); Undo.UndoData undodata = Program.Undo.NewUndoData("Precise MapDataArea", mapid.ToString("X")); //マップ領域を新規に割り当てる byte[] data = new byte[2 + (15 * 10)]; data[0] = 15; data[1] = 10; data = LZ77.compress(data); MapSettingForm.PLists plists = MapSettingForm.GetMapPListsWhereMapID(mapid); uint map_addr = MapPointerForm.PlistToOffsetAddr(MapPointerForm.PLIST_TYPE.MAP, plists.mappointer_plist); if (U.isSafetyOffset(map_addr)) {//既存マップがあればコピーする. uint length = LZ77.getCompressedSize(Program.ROM.Data, map_addr); data = Program.ROM.getBinaryData(map_addr, length); } uint write_addr = InputFormRef.AppendBinaryData(data, undodata); if (write_addr == U.NOT_FOUND) { Program.Undo.Rollback(undodata); return(0); } bool r = MapPointerForm.Write_Plsit(MapPointerForm.PLIST_TYPE.MAP, plist, write_addr, undodata); if (!r) { Program.Undo.Rollback(undodata); return(0); } Program.Undo.Push(undodata); return(plist); }
//OBJECTの割り当て public static uint PreciseObjectArea(uint mapid) { MapPointerNewPLISTPopupForm f = (MapPointerNewPLISTPopupForm)InputFormRef.JumpFormLow <MapPointerNewPLISTPopupForm>(); f.Init(MapPointerForm.PLIST_TYPE.OBJECT); DialogResult dr = f.ShowDialog(); if (dr != System.Windows.Forms.DialogResult.OK) { return(0); } uint plist = f.GetSelectPLIST(); Undo.UndoData undodata = Program.Undo.NewUndoData("Precise ObjectArea", mapid.ToString("X")); //OBJECT領域を新規に割り当てる. MapSettingForm.PLists plists = MapSettingForm.GetMapPListsWhereMapID(mapid); Bitmap bmp; if (plists.obj_plist >= 0x100) {//2つのplistが必要だからコピーできない bmp = ImageUtil.Blank(32 * 8, 32 * 8); } else { bmp = DrawMapChipOnly(plists.obj_plist, plists.palette_plist, null); } byte[] data = ImageUtil.ImageToByte16Tile(bmp, bmp.Width, bmp.Height); data = LZ77.compress(data); uint write_addr = InputFormRef.AppendBinaryData(data, undodata); if (write_addr == U.NOT_FOUND) { Program.Undo.Rollback(undodata); return(0); } bool r = MapPointerForm.Write_Plsit(MapPointerForm.PLIST_TYPE.OBJECT, plist, write_addr, undodata); if (!r) { Program.Undo.Rollback(undodata); return(0); } Program.Undo.Push(undodata); return(plist); }
private void CompressFireButton_Click(object sender, EventArgs e) { if (CompressSRCFilename.Text == "" || CompressDESTFilename.Text == "") { return; } byte[] src = File.ReadAllBytes(CompressSRCFilename.Text); byte[] data = LZ77.compress(src); U.WriteAllBytes(CompressDESTFilename.Text, data); //エクスプローラで選択しよう U.SelectFileByExplorer(CompressDESTFilename.Text); }
uint RecompressOne(InputFormRef.AutoPleaseWait wait, Address a, Undo.UndoData undodata) { if (!Address.IsLZ77(a.DataType)) {//念のためlz77圧縮の確認 return(0); } if (!U.isPadding4(a.Addr)) {//4バイトパディングされていないデータはありえない return(0); } byte[] unzipData = LZ77.decompress(Program.ROM.Data, a.Addr); if (unzipData.Length <= 0) { return(0); } uint uncompressSize = LZ77.getUncompressSize(Program.ROM.Data, a.Addr); if (unzipData.Length != uncompressSize) { return(0); } byte[] lz77Data = LZ77.compress(unzipData); if (lz77Data.Length >= a.Length) {//無意味なのでやらない return(0); } uint diff = (uint)(a.Length - lz77Data.Length); if (diff <= 3) {//無意味なのでやらない return(0); } //書き込み Program.ROM.write_fill(a.Addr, a.Length, 0, undodata); Program.ROM.write_range(a.Addr, lz77Data, undodata); wait.DoEvents(R._("recompress lz77 {0}", U.To0xHexString(a.Addr))); return(diff); }
void WriteLZ77Bin(byte[] bin, uint addr, uint datasize, string debugInfo) { byte[] newbin = LZ77.compress(bin); //領域の確保 uint writeaddr = 0; if (!isVanilaExtrendsROMArea(addr + datasize) && datasize >= newbin.Length) {//非拡張領域 //そのまま書き換えられる writeaddr = addr; } else {//リポイントが必要 writeaddr = Alloc((uint)newbin.Length, addr); } //データの書き込み U.write_range(this.WriteROMData32MB, writeaddr, newbin); ResolvedPointer(U.toPointer(addr), U.toPointer(writeaddr), debugInfo); }
public static string Import(string filename, uint anime_pointer) { string basename = Path.GetFileNameWithoutExtension(filename) + "_"; string basedir = Path.GetDirectoryName(filename); //同じアニメを何度も入力しないように記録する. List <anime> anime_list = new List <anime>(); List <byte> frames = new List <byte>(); string[] lines = File.ReadAllLines(filename); uint sound_id = 0x3d1; AnimeType animeType = AnimeType.None; for (uint lineCount = 0; lineCount < lines.Length; lineCount++) { string line = lines[lineCount]; if (U.IsComment(line) || U.OtherLangLine(line)) { continue; } line = U.ClipComment(line); if (line.Length <= 0) { continue; } InputFormRef.DoEvents(null, "Line:" + lineCount); line = line.Replace("\t", " "); string[] sp = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); string command = sp[0]; if (command.Length <= 0) { continue; } if (command[0] == 'S') { sound_id = U.atoh(command.Substring(1)); continue; } if (command[0] == 'D') { animeType = AnimeType.D; continue; } if (!(U.isNumString(command) && sp.Length >= 2)) { continue; } if (sp.Length <= 1) { Debug.Assert(false); continue; } uint wait = U.atoi(command); string image = sp[1]; uint id = FindImage(anime_list, image); if (id == U.NOT_FOUND) { id = (uint)anime_list.Count; string fullfilename = Path.Combine(basedir, image); Bitmap bitmap = ImageUtil.OpenBitmap(fullfilename); if (bitmap == null) { return(R.Error("ファイル名が見つかりませんでした。\r\nFile: {0} line:{1}\r\n\r\nエラー内容:\r\n{2}", filename, lineCount, line)); } if (bitmap.Width != SCREEN_WIDTH || bitmap.Height != SCREEN_HEIGHT) { bitmap = ImageUtil.Copy(bitmap, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); } anime a = new anime(); string error = ImageUtil.ImageToBytePackedTSA(bitmap, SCREEN_WIDTH, SCREEN_HEIGHT, 0, out a.image, out a.tsa); if (error != "") { return(R.Error("画像をインポートできません。\r\nFile: {0} line:{1}\r\n\r\nエラー内容:\r\n{2}", filename, lineCount, error)); } a.image = LZ77.compress(a.image); a.tsa = LZ77.compress(a.tsa); a.pal = ImageUtil.ImageToPalette(bitmap, 1); a.filename = image; anime_list.Add(a); } U.append_u16(frames, id); U.append_u16(frames, wait); } //term U.append_u16(frames, 0xFFFF); U.append_u16(frames, 0xFFFF); anime_pointer = U.toOffset(anime_pointer); if (!U.isSafetyOffset(anime_pointer)) { return(R._("アドレスが無効です")); } uint anime_address = Program.ROM.p32(anime_pointer); List <Address> recycle = new List <Address>(); RecycleOldAnime(ref recycle, basename, false, anime_address); RecycleAddress ra = new RecycleAddress(recycle); Undo.UndoData undodata = Program.Undo.NewUndoData("ImageUtilSkillSystemsAnimeCreator.Import"); List <byte> image_list = new List <byte>(); List <byte> tsa_list = new List <byte>(); List <byte> pal_list = new List <byte>(); for (int i = 0; i < anime_list.Count; i++) { uint p; p = ra.Write(anime_list[i].image, undodata); U.append_u32(image_list, U.toPointer(p)); p = ra.Write(anime_list[i].tsa, undodata); U.append_u32(tsa_list, U.toPointer(p)); p = ra.Write(anime_list[i].pal, undodata); U.append_u32(pal_list, U.toPointer(p)); } List <byte> mainData = new List <byte>(); if (Program.ROM.RomInfo.is_multibyte()) {//FE8J //FE8Jには、スキルごとにプログラムは存在しない. } else {//FE8U //信じられないが、スキルアニメ毎にプログラムコードが設定される. if (animeType == AnimeType.D) { string prog = Path.Combine(Program.BaseDirectory, "config", "patch2", "FE8U", "skill", "skillanimtemplate_defender_2017_01_24.dmp"); mainData.AddRange(File.ReadAllBytes(prog)); } else { string prog = Path.Combine(Program.BaseDirectory, "config", "patch2", "FE8U", "skill", "skillanimtemplate_2016_11_04.dmp"); mainData.AddRange(File.ReadAllBytes(prog)); } } //プログラムの下にデータがある. { uint p; p = ra.Write(frames.ToArray(), undodata); U.append_u32(mainData, U.toPointer(p)); p = ra.Write(tsa_list.ToArray(), undodata); U.append_u32(mainData, U.toPointer(p)); p = ra.Write(image_list.ToArray(), undodata); U.append_u32(mainData, U.toPointer(p)); p = ra.Write(pal_list.ToArray(), undodata); U.append_u32(mainData, U.toPointer(p)); U.append_u32(mainData, sound_id); } //アニメポインタの書き換え. ra.WriteAndWritePointer(anime_pointer, mainData.ToArray(), 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); }
bool WriteMapChipImage(byte[] image, Undo.UndoData undodata) { if (this.MapStyle.SelectedIndex < 0) { return(false); } uint obj_plist = this.MapEditConf[this.MapStyle.SelectedIndex].obj_plist; uint obj2_plist = (obj_plist >> 8) & 0xFF; //FE8にはないが FE7は、 plistを2つ設定できることがある. if (obj2_plist > 0) {//FE7とかあるフィールド画像分割 byte[] image1 = U.subrange(image, 0, (uint)(image.Length / 2)); byte[] image2 = U.subrange(image, (uint)(image.Length / 2), (uint)image.Length); byte[] image1Z = LZ77.compress(image1); byte[] image2Z = LZ77.compress(image2); uint newaddr = InputFormRef.WriteBinaryData(this, (uint)ObjAddress.Value, image1Z, InputFormRef.get_data_pos_callback_lz77, undodata); if (newaddr == U.NOT_FOUND) { Program.Undo.Rollback(undodata); return(false); } ObjAddress.Value = newaddr; //拡張領域に書き込んでいる可能性もあるので plstを更新する. MapPointerForm.Write_Plsit(MapPointerForm.PLIST_TYPE.OBJECT, obj_plist, newaddr, undodata); //分割されたデータを書き込み newaddr = InputFormRef.WriteBinaryData(this, (uint)ObjAddress2.Value, image2Z, InputFormRef.get_data_pos_callback_lz77, undodata); if (newaddr == U.NOT_FOUND) { Program.Undo.Rollback(undodata); return(false); } ObjAddress2.Value = newaddr; //拡張領域に書き込んでいる可能性もあるので plstを更新する. bool r = MapPointerForm.Write_Plsit(MapPointerForm.PLIST_TYPE.OBJECT, obj2_plist, newaddr, undodata); if (!r) { Program.Undo.Rollback(undodata); return(false); } //書き込んだ通知. InputFormRef.ShowWriteNotifyAnimation(this, newaddr); } else { byte[] imageZ = LZ77.compress(image); uint newaddr = InputFormRef.WriteBinaryData(this, (uint)ObjAddress.Value, imageZ, InputFormRef.get_data_pos_callback_lz77, undodata); if (newaddr == U.NOT_FOUND) { Program.Undo.Rollback(undodata); return(false); } ObjAddress.Value = newaddr; //拡張領域に書き込んでいる可能性もあるので plstを更新する. bool r = MapPointerForm.Write_Plsit(MapPointerForm.PLIST_TYPE.OBJECT, obj_plist, newaddr, undodata); if (!r) { Program.Undo.Rollback(undodata); return(false); } //書き込んだ通知. InputFormRef.ShowWriteNotifyAnimation(this, newaddr); } return(true); }
string Import( string filename //読込むファイル名 ) { string basename = Path.GetFileNameWithoutExtension(filename) + "_"; string basedir = Path.GetDirectoryName(filename); //同じアニメを何度も入力しないように記録する. List <anime> anime_list = new List <anime>(); int imageWidth = this.ImageWidth * 8; int imageHeight = 8 * 16; List <byte> frames = new List <byte>(); string[] lines = File.ReadAllLines(filename); for (uint lineCount = 0; lineCount < lines.Length; lineCount++) { string line = lines[lineCount++]; if (U.IsComment(line) || U.OtherLangLine(line)) { continue; } line = U.ClipComment(line); if (line.Length <= 0) { continue; } InputFormRef.DoEvents(null, "Line:" + lineCount); line = line.Replace("\t", " "); string[] sp = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); string command = sp[0]; if (command.Length <= 0) { continue; } if (!(U.isNumString(command) && sp.Length >= 2)) { continue; } uint wait = U.atoi(command); string image = sp[1]; uint id = FindImage(anime_list, image); if (id == U.NOT_FOUND) { id = (uint)anime_list.Count; string fullfilename = Path.Combine(basedir, image); Bitmap bitmap = ImageUtil.OpenBitmap(fullfilename); if (bitmap == null) { return(R.Error("ファイル名が見つかりませんでした。\r\nFile: {0} line:{1}\r\n\r\nエラー内容:\r\n{2}", filename, lineCount, line)); } if (bitmap.Width != imageWidth || bitmap.Height != imageHeight) { bitmap = ImageUtil.Copy(bitmap, 0, 0, imageWidth, imageHeight); } anime a = new anime(); string error = ImageUtil.ImageToBytePackedTSA(bitmap, imageWidth, imageHeight, 0, out a.image, out a.tsa); if (error != "") { return(R.Error("画像をインポートできません。\r\nFile: {0} line:{1}\r\n\r\nエラー内容:\r\n{2}", filename, lineCount, error)); } a.image = LZ77.compress(a.image); a.tsa = LZ77.compress(a.tsa); a.pal = ImageUtil.ImageToPalette(bitmap, 1); a.filename = image; anime_list.Add(a); } U.append_u16(frames, id); U.append_u16(frames, wait); } //term U.append_u16(frames, 0xFFFF); U.append_u16(frames, 0x0); if (anime_list.Count <= 0) { return(R._("書き込むアニメーションがありません")); } Undo.UndoData undodata = Program.Undo.NewUndoData(""); List <Address> recycle = new List <FEBuilderGBA.Address>(); MakeRecycleList(ref recycle, "", false); RecycleAddress ra = new RecycleAddress(recycle); uint p; if (!U.isSafetyOffset(this.FramePointer)) {//固定フレームのアニメ if (this.FramePointer != anime_list.Count) { return(R._("このアニメーションは固定アニメーションです。フレームが{0}個必要です。指定されたアニメには{1}のフレームがあり、数が一致していません。", this.FramePointer, anime_list.Count)); } if (this.TSAList.Count == 1 && this.PaletteList.Count >= 2) {//パレットアニメ List <byte> pal_list = new List <byte>(); for (int i = 0; i < anime_list.Count; i++) { p = ra.Write(anime_list[i].pal, undodata); U.append_u32(pal_list, U.toPointer(p)); } ra.WriteAndWritePointer(this.TSAPointer, anime_list[0].tsa, undodata); ra.WriteAndWritePointer(this.ImagePointer, anime_list[0].image, undodata); ra.WriteAndWritePointer(this.PalettePointer, pal_list.ToArray(), undodata); } else { List <byte> image_list = new List <byte>(); List <byte> tsa_list = new List <byte>(); List <byte> pal_list = new List <byte>(); for (int i = 0; i < anime_list.Count; i++) { p = ra.Write(anime_list[i].image, undodata); U.append_u32(image_list, U.toPointer(p)); p = ra.Write(anime_list[i].tsa, undodata); U.append_u32(tsa_list, U.toPointer(p)); p = ra.Write(anime_list[i].pal, undodata); U.append_u32(pal_list, U.toPointer(p)); } ra.WriteAndWritePointer(this.TSAPointer, tsa_list.ToArray(), undodata); ra.WriteAndWritePointer(this.ImagePointer, image_list.ToArray(), undodata); ra.WriteAndWritePointer(this.PalettePointer, pal_list.ToArray(), undodata); } } else { //フレームを利用するアニメ if (this.TSAList.Count >= 2 && this.PaletteList.Count == 1) { //共通パレット List <byte> image_list = new List <byte>(); List <byte> tsa_list = new List <byte>(); for (int i = 0; i < anime_list.Count; i++) { p = ra.Write(anime_list[i].image, undodata); U.append_u32(image_list, U.toPointer(p)); p = ra.Write(anime_list[i].tsa, undodata); U.append_u32(tsa_list, U.toPointer(p)); } ra.WriteAndWritePointer(this.FramePointer, frames.ToArray(), undodata); ra.WriteAndWritePointer(this.TSAPointer, tsa_list.ToArray(), undodata); ra.WriteAndWritePointer(this.ImagePointer, image_list.ToArray(), undodata); ra.WriteAndWritePointer(this.PalettePointer, anime_list[0].pal, undodata); } else {//複数パレット List <byte> image_list = new List <byte>(); List <byte> tsa_list = new List <byte>(); List <byte> pal_list = new List <byte>(); for (int i = 0; i < anime_list.Count; i++) { p = ra.Write(anime_list[i].image, undodata); U.append_u32(image_list, U.toPointer(p)); p = ra.Write(anime_list[i].tsa, undodata); U.append_u32(tsa_list, U.toPointer(p)); p = ra.Write(anime_list[i].pal, undodata); U.append_u32(pal_list, U.toPointer(p)); } ra.WriteAndWritePointer(this.FramePointer, frames.ToArray(), undodata); ra.WriteAndWritePointer(this.TSAPointer, tsa_list.ToArray(), undodata); ra.WriteAndWritePointer(this.ImagePointer, image_list.ToArray(), undodata); ra.WriteAndWritePointer(this.PalettePointer, pal_list.ToArray(), undodata); } } ra.BlackOut(undodata); Program.Undo.Push(undodata); return(""); }
public uint MakePaletteUIToROM(uint palette_address, bool isCompress, int palette_index) { uint addr = U.toOffset(palette_address); if (!U.CheckZeroAddressWriteHigh(addr)) { return(U.NOT_FOUND); } string undo_name = "PALETTE " + U.To0xHexString(palette_address); byte[] palttebyte = MakePaletteUIToByte(); if (isCompress) {//戦闘アニメのパレットは圧縮されている //現パレットの解凍 byte[] currentdata = LZ77.decompress(Program.ROM.Data, addr); if (currentdata.Length <= 0) {//解凍できない アドレスを強引に書き換えたりしたのだろうか. if (palette_index != 0 && palette_index != OVERRAIDE_ALL_PALETTE) { Log.Error("パレットを解凍できません.", U.To0xHexString(addr)); return(U.NOT_FOUND); } //解凍できないけど、最初のパレットに書き込むなら、サイズは16*2で固定だから関係ない. currentdata = palttebyte; } else if (palette_index == OVERRAIDE_ALL_PALETTE) {//複数あるパレットですべて同じパレットに設定する int paletteCount = currentdata.Length / 0x20; for (int i = 0; i < paletteCount; i++) { uint write_addr = (uint)(i * 0x20); U.write_range(currentdata, write_addr, palttebyte); } } else {//複数あるパレットの一部を書き換える. uint write_addr = (uint)(palette_index * 0x20); if (currentdata.Length < write_addr + palttebyte.Length) {//サイズが足りない場合増設する. Array.Resize(ref currentdata, (int)(write_addr + palttebyte.Length)); } U.write_range(currentdata, write_addr, palttebyte); } byte[] palettebyteZ = LZ77.compress(currentdata); //圧縮されているということは、サイズが可変なわけで、元の場所に書き込めるか、拡張領域かを検討しないといけない。 Undo.UndoData undodata = Program.Undo.NewUndoData(undo_name); uint newaddr = InputFormRef.WriteBinaryData(this.SelfForm, addr, palettebyteZ, InputFormRef.get_data_pos_callback_lz77, undodata); if (newaddr == U.NOT_FOUND) { return(U.NOT_FOUND); } Program.Undo.Push(undodata); return(newaddr); } else { //無圧縮パレット if (palette_index == OVERRAIDE_ALL_PALETTE) { //無圧縮パレットでは、パレットのサイズがわからないので、すべて同じ色にすることは不可能 R.Error("無圧縮パレットなので、すべて同じパレットにすることはできません。"); Debug.Assert(false); return(U.NOT_FOUND); } addr = addr + (uint)(palette_index * 0x20); Program.Undo.Push(undo_name, addr, (uint)palttebyte.Length); Program.ROM.write_range(addr, palttebyte); return(addr); } }
public static string Import(string filename, uint anime_pointer) { string basename = Path.GetFileNameWithoutExtension(filename) + "_"; string basedir = Path.GetDirectoryName(filename); //他のアニメーションとはデータ構造が違うので注意 List <anime> poolList = new List <anime>(); List <byte> frames = new List <byte>(); string[] lines = File.ReadAllLines(filename); for (uint lineCount = 0; lineCount < lines.Length; lineCount++) { string line = lines[lineCount]; if (U.IsComment(line) || U.OtherLangLine(line)) { continue; } line = U.ClipComment(line); if (line.Length <= 0) { continue; } InputFormRef.DoEvents(null, "Line:" + lineCount); string[] sp = line.Split(new string[] { "\t" }, StringSplitOptions.RemoveEmptyEntries); if (sp.Length <= 1) { sp = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); } if (sp.Length <= 1) { continue; } string command = sp[0]; uint wait = U.atoi0x(command); string image = sp[1]; uint song = 0; if (sp.Length >= 2 + 1) { song = U.atoi0x(sp[2]); } string fullfilename = Path.Combine(basedir, image); Bitmap bitmap = ImageUtil.OpenBitmap(fullfilename); if (bitmap == null) { return(R.Error("ファイル名が見つかりませんでした。\r\nFile: {0} line:{1}\r\n\r\nエラー内容:\r\n{2}", filename, lineCount, line)); } if (bitmap.Width != SCREEN_WIDTH || bitmap.Height != SCREEN_HEIGHT) { bitmap = ImageUtil.Copy(bitmap, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); } anime a = new anime(); a.image = ImageUtil.ImageToByte16Tile(bitmap, SCREEN_WIDTH, SCREEN_HEIGHT); a.image = LZ77.compress(a.image); a.pal = ImageUtil.ImageToPalette(bitmap, 1); poolList.Add(a); U.append_u16(frames, wait); U.append_u16(frames, song); U.append_u32(frames, 0x0); U.append_u32(frames, 0x0); } //term U.append_u32(frames, 0x0); U.append_u32(frames, 0x0); U.append_u32(frames, 0x0); byte[] mainData = frames.ToArray(); anime_pointer = U.toOffset(anime_pointer); if (!U.isSafetyOffset(anime_pointer)) { return(R._("アドレスが無効です")); } uint anime_address = Program.ROM.p32(anime_pointer); List <Address> recycle = new List <Address>(); RecycleOldAnime(ref recycle, basename, false, anime_address); RecycleAddress ra = new RecycleAddress(recycle); Undo.UndoData undodata = Program.Undo.NewUndoData("ImageUtilMapActionAnimation.Import"); uint n = 0; for (int i = 0; i < poolList.Count; i++, n += 12) { uint image_addr = CheckDupImage(poolList, i); if (image_addr == U.NOT_FOUND) { image_addr = ra.Write(poolList[i].image, undodata); poolList[i].image_addr = image_addr; } uint pal_addr = CheckDupPal(poolList, i); if (pal_addr == U.NOT_FOUND) { pal_addr = ra.Write(poolList[i].pal, undodata); poolList[i].pal_addr = pal_addr; } U.write_p32(mainData, n + 4, image_addr); U.write_p32(mainData, n + 8, pal_addr); } //アニメポインタの書き換え. ra.WriteAndWritePointer(anime_pointer, mainData, undodata); //名前の設定 MakeImportDataName(anime_pointer, filename, lines); Program.Undo.Push(undodata); return(""); }
private void ObjImportButton_Click(object sender, EventArgs e) { if (this.MapStyle.SelectedIndex < 0) { return; } uint obj_plist = this.MapEditConf[this.MapStyle.SelectedIndex].obj_plist; uint obj2_plist = (obj_plist >> 8) & 0xFF; //FE8にはないが FE7は、 plistを2つ設定できることがある. Bitmap bitmap = ImageFormRef.ImportFilenameDialog(this); if (bitmap == null) { return; } int width = 32 * 8; int height = 32 * 8; int palette_count = MAX_MAP_PALETTE_COUNT; if (bitmap.Width != width || bitmap.Height < 128) { R.ShowStopError("画像サイズが正しくありません。\r\nWidth:{2} Height:{3} でなければなりません。\r\n\r\n選択された画像のサイズ Width:{0} Height:{1}", bitmap.Width, bitmap.Height, width, height); return; } height = ImageUtil.CalcHeight(width, width * bitmap.Height / 2); if (ObjImportOption.SelectedIndex == 1) {//パレットもインポートする場合 パレット数のチェック. int bitmap_palette_count = ImageUtil.GetPalette16Count(bitmap); if (bitmap_palette_count > palette_count) { R.ShowStopError("パレット数が正しくありません。\r\n{1}種類以下(16色*{1}種類) でなければなりません。\r\n\r\n選択された画像のパレット種類:{0}種類", bitmap_palette_count, palette_count); return; } bitmap = PaletteSwapper(bitmap); } //画像 byte[] image = ImageUtil.ImageToByte16Tile(bitmap, width, height); //画像等データの書き込み Undo.UndoData undodata = Program.Undo.NewUndoData(this); if (obj2_plist > 0) {//FE7とかあるフィールド画像分割 byte[] image1 = U.subrange(image, 0, (uint)(image.Length / 2)); byte[] image2 = U.subrange(image, (uint)(image.Length / 2), (uint)image.Length); byte[] image1Z = LZ77.compress(image1); byte[] image2Z = LZ77.compress(image2); uint newaddr = InputFormRef.WriteBinaryData(this, (uint)ObjAddress.Value, image1Z, InputFormRef.get_data_pos_callback_lz77, undodata); if (newaddr == U.NOT_FOUND) { Program.Undo.Rollback(undodata); return; } ObjAddress.Value = newaddr; //拡張領域に書き込んでいる可能性もあるので plstを更新する. MapPointerForm.Write_Plsit(MapPointerForm.PLIST_TYPE.OBJECT, obj_plist, newaddr, undodata); //分割されたデータを書き込み newaddr = InputFormRef.WriteBinaryData(this, (uint)ObjAddress2.Value, image2Z, InputFormRef.get_data_pos_callback_lz77, undodata); if (newaddr == U.NOT_FOUND) { Program.Undo.Rollback(undodata); return; } ObjAddress2.Value = newaddr; //拡張領域に書き込んでいる可能性もあるので plstを更新する. bool r = MapPointerForm.Write_Plsit(MapPointerForm.PLIST_TYPE.OBJECT, obj2_plist, newaddr, undodata); if (!r) { Program.Undo.Rollback(undodata); return; } //書き込んだ通知. InputFormRef.ShowWriteNotifyAnimation(this, newaddr); } else { byte[] imageZ = LZ77.compress(image); uint newaddr = InputFormRef.WriteBinaryData(this, (uint)ObjAddress.Value, imageZ, InputFormRef.get_data_pos_callback_lz77, undodata); if (newaddr == U.NOT_FOUND) { Program.Undo.Rollback(undodata); return; } ObjAddress.Value = newaddr; //拡張領域に書き込んでいる可能性もあるので plstを更新する. bool r = MapPointerForm.Write_Plsit(MapPointerForm.PLIST_TYPE.OBJECT, obj_plist, newaddr, undodata); if (!r) { Program.Undo.Rollback(undodata); return; } //書き込んだ通知. InputFormRef.ShowWriteNotifyAnimation(this, newaddr); } if (ObjImportOption.SelectedIndex == 1) {//パレットもインポートする場合 //パレットの交換 MapObjImage = bitmap; U.ForceUpdate(this.PaletteTypeCombo, 0); U.ForceUpdate(this.PaletteCombo, 0); //パレット情報の書き込み. uint palette_plist = this.MapEditConf[this.MapStyle.SelectedIndex].palette_plist; uint palette_address = MapPointerForm.PlistToOffsetAddr(MapPointerForm.PLIST_TYPE.PALETTE, palette_plist); if (palette_address == 0) {//未割り当てならば新規確保しようか palette_address = InputFormRef.AppendBinaryData(PaletteFormRef.NewNullPalette(palette_count), undodata); } PaletteFormRef.MakePaletteBitmapToROM(this, bitmap, palette_address, palette_count, undodata); //拡張領域に書き込んでいる可能性もあるので plstを更新する. bool r = MapPointerForm.Write_Plsit(MapPointerForm.PLIST_TYPE.PALETTE, palette_plist, palette_address, undodata); if (!r) { Program.Undo.Rollback(undodata); return; } PaletteAddress.Value = palette_address; } else {//パレットはインポートしない場合 //パレット情報の継承. bitmap.Palette = this.MapObjImage.Palette; //obj Bitmap交換 this.MapObjImage = bitmap; } Program.Undo.Push(undodata); //チップセットの更新. Chipset_Update(); SelectedChipset_Update(); MapStyle_SelectedIndexChanged(sender, e); InputFormRef.WriteButtonToYellow(this.PaletteWriteButton, false); //マップエディタが開いていれば更新する MapEditorForm.UpdateMapStyleIfOpen(); }