static InputFormRef Init(Form self) { return(new InputFormRef(self , "" , Program.ROM.RomInfo.mask_pointer() , 4 , (int i, uint addr) => { return Program.ROM.u8(addr) != 255; } , (int i, uint addr) => { uint c = Program.ROM.u16(addr); string str = Program.ROM.getString(addr, 2); if (!Program.ROM.RomInfo.is_multibyte()) { if (c >= 0x81 && c <= 0xFF) { //英語版FEにはUnicodeの1バイトだけ表記があるらしい. str = "@00" + c.ToString("X02"); } } str = FETextEncode.RevConvertSPMoji(str); return i.ToString("X04") + " " + c.ToString("X04") + " " + str; } )); }
static uint CheckMoveToUnuseSpaceTop( uint index_start_addr //indexの開始 , uint index_end_addr //indexの終端 , uint data_start_addr //データの開始 , uint data_end_addr //データの終端 , Func <uint, bool, MoveToUnuseSpace.ADDR_AND_LENGTH> get_data_pos_callback //データサイズを求める. ) { uint free_size = 0; for (uint addr = index_start_addr; addr < index_end_addr; addr += 4) { //uHuffman patchを使っているかどうか. bool useUnHuffmanPatch = false; uint data_s = Program.ROM.u32(addr); if (!U.isPointer(data_s)) { //ポインタではない if (!FETextEncode.IsUnHuffmanPatchPointer(data_s)) { //不明 continue; } //unHuffman patch適応データ useUnHuffmanPatch = true; data_s = FETextEncode.ConvertUnHuffmanPatchToPointer(data_s); } data_s = U.toOffset(data_s); ADDR_AND_LENGTH aal = get_data_pos_callback(data_s, useUnHuffmanPatch); if (aal.addr < data_start_addr || aal.addr + aal.length > data_end_addr) { //独自拡張され、データ領域以外に設置されている. continue; } if (aal.length >= 0x00200000) {//長すぎる. continue; } uint aaladdr = aal.addr + aal.length; //次のデータのポインタを取得 uint next_addr = Program.ROM.u32(addr + 4); if (FETextEncode.IsUnHuffmanPatchPointer(next_addr)) { next_addr = FETextEncode.ConvertUnHuffmanPatchToPointer(next_addr); } next_addr = U.toOffset(next_addr); if (next_addr == aaladdr) {//ちょうど利用している.空き領域なし.次に行ってみよう. continue; } if (next_addr < aaladdr) {//アドレスが逆転している...放置 continue; } //フリーサイズ free_size += (next_addr - aaladdr); } return(free_size); }
static bool RunMoveToUnuseSpaceTop( uint index_start_addr //indexの開始 , uint index_end_addr //indexの終端 , uint data_start_addr //データの開始 , uint data_end_addr //データの終端 , Func <uint, bool, MoveToUnuseSpace.ADDR_AND_LENGTH> get_data_pos_callback //データサイズを求める. , List <Undo.UndoPostion> undolist ) { uint use_data_addr = data_start_addr; uint addr; for (addr = index_start_addr; addr < index_end_addr; addr += 4) { //uHuffman patchを使っているかどうか. bool useUnHuffmanPatch = false; uint data_s = Program.ROM.u32(addr); if (!U.isPointer(data_s)) { //ポインタではない if (!FETextEncode.IsUnHuffmanPatchPointer(data_s)) { //不明 continue; } //unHuffman patch適応データ useUnHuffmanPatch = true; data_s = FETextEncode.ConvertUnHuffmanPatchToPointer(data_s); } data_s = U.toOffset(data_s); ADDR_AND_LENGTH aal = get_data_pos_callback(data_s, useUnHuffmanPatch); if (aal.addr < data_start_addr || aal.addr + aal.length > data_end_addr) {//独自拡張され、データ領域以外に設置されている. //無視して次行ってみよう. continue; } //空き領域を作るためにデータを移動 movemem byte[] original = Program.ROM.getBinaryData(aal.addr, aal.length); undolist.Add(new Undo.UndoPostion(aal.addr, original)); Program.ROM.write_range(use_data_addr, original); //移動したので挿げ替え. undolist.Add(new Undo.UndoPostion(addr, 4)); if (useUnHuffmanPatch) { Program.ROM.write_u32(addr, FETextEncode.ConvertPointerToUnHuffmanPatchPointer(U.toPointer(use_data_addr))); } else { Program.ROM.write_p32(addr, use_data_addr); } use_data_addr += aal.length; } return(true); }
void AddRecycle(uint id, List <Address> list) { //無効なID if (id <= 0) { return; } if (id < this.MaxTextCount) { uint addr = this.TextBaseAddress + (id * 4); uint paddr = Program.ROM.u32(addr); if (TextForm.Is_RAMPointerArea(paddr)) { return; } uint data_addr; int length; if (FETextEncode.IsUnHuffmanPatchPointer(paddr)) {//un-huffman patch? uint unhuffman_addr = U.toOffset(FETextEncode.ConvertUnHuffmanPatchToPointer(paddr)); data_addr = unhuffman_addr; TextDecode.UnHffmanPatchDecode(unhuffman_addr, out length); } else if (U.isPointer(paddr)) { data_addr = U.toOffset(paddr); TextDecode.huffman_decode(data_addr, out length); } else { return; } if (length <= 0) { return; } if (data_addr == this.TextID0Addr) { return; } FEBuilderGBA.Address.AddAddress(list , data_addr , (uint)length , U.NOT_FOUND , "text " + U.ToHexString(id) , FEBuilderGBA.Address.DataTypeEnum.BIN); } //CStringに対しては、リサイクルバッファを利用する方式を利用しない //なぜなら、FE6には大量のポインタ参照があるためです。 //容量も大きくないので、メリットよりデメリットの方が上回る // else if (U.isSafetyPointer(id)) // { // uint p = U.toOffset(id); // FEBuilderGBA.Address.AddCString(list, p); // } }
public String DecodeAddr(uint addr, out int out_DataSize) { addr = U.toOffset(addr); if (!U.isSafetyOffset(addr, this.ROM)) { out_DataSize = 0; return(""); } uint paddr = this.ROM.u32(addr); if (FETextEncode.IsUnHuffmanPatchPointer(paddr)) {//un-huffman patch? uint unhuffman_addr = U.toOffset(FETextEncode.ConvertUnHuffmanPatchToPointer(paddr)); return(UnHffmanPatchDecode(unhuffman_addr, out out_DataSize)); } else if (U.isPointer(paddr)) { return(huffman_decode(U.toOffset(paddr), out out_DataSize)); } out_DataSize = 0; return(""); }
//改造ROMだとデータを共有している場合があるので、本当にそのサイズは正しいのか、 //すべての文字列データから再検証します。 //遅くなるけど、これは必須です。 static uint ConvertSafetyLength( uint length , uint index_start_addr //indexの開始 , uint index_end_addr //indexの終端 , uint data_s //入れたいデータのアドレス ) { //念のため、その範囲からスタートするポインタがないか確認します. //tlpとか、途中からアドレスが逆転していることがあるらしいので。 for (uint p = index_start_addr; p < index_end_addr; p += 4) { uint data_s_dupcheck = Program.ROM.u32(p); if (!U.isPointer(data_s_dupcheck)) { if (!FETextEncode.IsUnHuffmanPatchPointer(data_s_dupcheck)) {//ポインタが不明 continue; } data_s_dupcheck = FETextEncode.ConvertUnHuffmanPatchToPointer(data_s_dupcheck); } data_s_dupcheck = U.toOffset(data_s_dupcheck); if (data_s_dupcheck == data_s) {//自分自身 continue; } if (data_s_dupcheck >= data_s && data_s_dupcheck < data_s + length) {//データを共有しているらしいので、サイズを切り詰めないとダメだ. uint new_length = data_s_dupcheck - data_s; if (new_length < length) {//より小さくなる場合は、縮める. length = new_length; } } } return(length); }
void WriteTextUnHffman(uint id, string text, Undo.UndoData undodata) { uint addr = this.TextBaseAddress + (id * 4); uint paddr = Program.ROM.u32(addr); if (TextForm.Is_RAMPointerArea(paddr)) {//iw-ram / ew-ram にデータをおいている人がいるらしい return; } byte[] encode; Program.FETextEncoder.UnHuffmanEncode(text, out encode); string undoname = "Text:" + U.ToHexString(id); uint newaddr = this.Recycle.Write(encode, undodata); if (newaddr == U.NOT_FOUND) { return; } newaddr = U.toPointer(newaddr); newaddr = FETextEncode.ConvertPointerToUnHuffmanPatchPointer(newaddr); Program.ROM.write_u32(addr, newaddr, undodata); }
public static uint OriginalDataSize( uint index_start_addr //indexの開始 , uint index_end_addr //indexの終端 , uint data_start_addr //データの開始 , uint data_end_addr //データの終端 , uint now_index //データを入れたいindex場所 , Func <uint, bool, MoveToUnuseSpace.ADDR_AND_LENGTH> get_data_pos_callback //データサイズを求める. ) { //uHuffman patchを使っているかどうか. bool useUnHuffmanPatch = false; uint addr = index_start_addr + (now_index * 4); uint data_s = Program.ROM.u32(addr); //他と共有していないか調べる. for (uint p = index_start_addr; p < index_end_addr; p += 4) { uint data_s2 = Program.ROM.u32(p); if (p == addr) { continue; } if (data_s2 == data_s) {//他と共有しているのでリサイクルしてはいけません. return(0); } } if (!U.isPointer(data_s)) {//ポインタではない 単体データ if (!FETextEncode.IsUnHuffmanPatchPointer(data_s)) { MoveToUnuseSpace.ADDR_AND_LENGTH aal = get_data_pos_callback(data_s, false); return(ConvertSafetyLength(aal.length, index_start_addr, index_end_addr, data_s)); } //unHuffman patch適応データ useUnHuffmanPatch = true; data_s = FETextEncode.ConvertUnHuffmanPatchToPointer(data_s); } data_s = U.toOffset(data_s); if (data_s < data_start_addr || data_s >= data_end_addr) {//拡張領域にあるらしいので基底サイズは不明. 自サイズしかわからない. MoveToUnuseSpace.ADDR_AND_LENGTH aal = get_data_pos_callback(data_s, useUnHuffmanPatch); return(ConvertSafetyLength(aal.length, index_start_addr, index_end_addr, data_s)); } uint i = 1; uint data_s_next; do { uint next_addr = index_start_addr + ((now_index + i) * 4); data_s_next = Program.ROM.u32(next_addr); if (!U.isPointer(data_s_next)) { if (!FETextEncode.IsUnHuffmanPatchPointer(data_s_next)) {//次のポインタが不明なので自サイズしかわからない. MoveToUnuseSpace.ADDR_AND_LENGTH aal = get_data_pos_callback(data_s, useUnHuffmanPatch); return(ConvertSafetyLength(aal.length, index_start_addr, index_end_addr, data_s)); } //unHuffman patch適応データ useUnHuffmanPatch = true; data_s_next = FETextEncode.ConvertUnHuffmanPatchToPointer(data_s_next); } data_s_next = U.toOffset(data_s_next); if (data_s_next < data_start_addr || data_s_next >= data_end_addr) {//拡張領域にあるらしいので次のデータを参照したい i++; continue; } if (data_s_next < data_s) { //アドレスが逆転してます. 危険なので自分のデータの長さだけを求めます.input MoveToUnuseSpace.ADDR_AND_LENGTH aal = get_data_pos_callback(data_s, useUnHuffmanPatch); return(ConvertSafetyLength(aal.length, index_start_addr, index_end_addr, data_s)); } break; }while(true); uint length = data_s_next - data_s; return(ConvertSafetyLength(length, index_start_addr, index_end_addr, data_s)); }
String CString(uint p, out int out_DataSize) { string str = this.ROM.getString(p, out out_DataSize); return(FETextEncode.RevConvertSPMoji(str)); }
String listbyte_to_string_low(byte[] str, int len) { string r = this.SystemTextEncoder.Decode(str, 0, len); return(FETextEncode.RevConvertSPMoji(r)); }
static void ReBuildFETextEncoder() { FETextEncoder = new FETextEncode(); }
void AddRecycle(uint id, List <Address> recycle) { //無効なID if (id <= 0) { return; } if (id < this.MaxTextCount) { uint addr = this.TextBaseAddress + (id * 4); uint paddr = Program.ROM.u32(addr); if (TextForm.Is_RAMPointerArea(paddr)) { return; } uint data_addr; int length; if (FETextEncode.IsUnHuffmanPatchPointer(paddr)) {//un-huffman patch? uint unhuffman_addr = U.toOffset(FETextEncode.ConvertUnHuffmanPatchToPointer(paddr)); data_addr = unhuffman_addr; TextDecode.UnHffmanPatchDecode(unhuffman_addr, out length); } else if (U.isPointer(paddr)) { data_addr = U.toOffset(paddr); TextDecode.huffman_decode(data_addr, out length); } else { return; } if (length <= 0) { return; } if (data_addr == this.TextID0Addr) { return; } FEBuilderGBA.Address.AddAddress(recycle , data_addr , (uint)length , U.NOT_FOUND , "text " + U.ToHexString(id) , FEBuilderGBA.Address.DataTypeEnum.BIN); } else if (U.isSafetyPointer(id)) { uint data_addr = Program.ROM.p32(U.toOffset(id)); if (!U.isSafetyOffset(id)) { return; } int length = 0; string str = Program.ROM.getString(data_addr, out length); FEBuilderGBA.Address.AddAddress(recycle , data_addr , (uint)length , U.NOT_FOUND , "CString " + U.To0xHexString(id) , FEBuilderGBA.Address.DataTypeEnum.BIN); } }