static void Main(string[] args) { Parser.Default.ParseArguments <Options>(args).WithParsed(o => { CharTable charTable = new CharTable(o.ChartablePath); Narc font = new Narc(o.FontPath); FontTable fontTable_0 = new FontTable(font.Files[0]); Generation.Gen gen = fontTable_0.Gen; switch (gen) { case Generation.Gen.Gen4: font.Files[0] = fontTable_0.Save(charTable); font.Files[1] = new FontTable(font.Files[1]).Save(charTable); font.Files[2] = new FontTable(font.Files[2]).Save(charTable, StyleType.TOP_LEFT); if (font.Files.Count == 10) // HGSS { font.Files[4] = new FontTable(font.Files[4]).Save(charTable, StyleType.ROUND); } break; case Generation.Gen.Gen5: font.Files[0] = fontTable_0.Save(charTable, StyleType.BOTTOM_RIGHT_5); font.Files[1] = new FontTable(font.Files[1]).Save(charTable, StyleType.BOTTOM_RIGHT_5, FontType.PIXEL_9); font.Files[2] = new FontTable(font.Files[2]).Save(charTable, StyleType.ROUND, FontType.PIXEL_9); break; default: return; } font.Save(o.OutputPath); }); }
/// <summary> /// 将文本根据保存为 narc 文件。 /// </summary> /// <param name="files">narc 文件</param> /// <param name="charTable">码表</param> public void Save(ref Narc msg, CharTable charTable) { if (this is Text_4) { ((Text_4)this).Save(ref msg, charTable); } else if (this is Text_5) { ((Text_5)this).Save(ref msg); } }
public void Save(ref Narc files) { for (int i = 0; i < files.Files.Count; i++) { MemoryStream ms = new MemoryStream(); BinaryWriter bw = new BinaryWriter(ms); BinaryReader br = new BinaryReader(new MemoryStream(files.Files[i])); uint[] sizeSections = { 0, 0 }; uint[] sectionOffset = { 0, 0 }; uint[] newsizeSections = { 0, 0 }; ushort numSections = br.ReadUInt16(), numEntries = br.ReadUInt16(); sizeSections[0] = br.ReadUInt32(); uint unk1 = br.ReadUInt32(); List <byte[]> newEntries = new List <byte[]>(); for (int j = 0; j < numSections; j++) { newEntries.Add(MakeSection(TextList[j][i], j, i, numEntries)); newsizeSections[j] = (uint)newEntries[j].Length; } for (int j = 0; j < numSections; j++) { sectionOffset[j] = br.ReadUInt32(); } for (int j = 0; j < numSections; j++) { br.BaseStream.Position = sectionOffset[j]; sizeSections[j] = br.ReadUInt32(); } bw.Write(numSections); bw.Write(numEntries); bw.Write(newsizeSections[0]); bw.Write(unk1); bw.Write(sectionOffset[0]); if (numSections == 2) { bw.Write(newsizeSections[0] + sectionOffset[0]); } for (int j = 0; j < numSections; j++) { bw.Write(newEntries[j]); } byte[] bytes = new byte[ms.Position]; ms.Position = 0; ms.Read(bytes, 0, bytes.Length); files.Files[i] = bytes; bw.Close(); br.Close(); } }
static void Main(string[] args) { Parser.Default.ParseArguments <Options>(args).WithParsed(o => { CharTable charTable = new CharTable(o.ChartablePath); Narc msg = new Narc(o.MessagePath); Text text; switch (msg.Files.Count) { case 610: // DP case 709: // Pt case 814: // HGSS text = new Text_4(msg, charTable); break; case 273: case 472: text = new Text_5(msg, charTable); break; default: throw new FormatException(); } if (o.ExtractPath != null) { text.Extract(o.ExtractPath); } if (o.ImportPath != null && o.OutputPath != null) { text.Import(o.ImportPath); text.Save(ref msg, charTable); msg.Save(o.OutputPath); } if (charTable.NoCode.Count > 0) { Console.WriteLine("以下字符未在码表中:" + string.Join("", charTable.NoCode)); } if (charTable.NoChar.Count > 0) { Console.WriteLine("以下编码未在码表中:" + string.Join(", ", charTable.NoChar)); } }); }
new public void Save(ref Narc files, CharTable charTable) { for (int i = 0; i < files.Files.Count; i++) { List <string> subList = TextList[0][i]; MemoryStream ms = new MemoryStream(); BinaryWriter bw = new BinaryWriter(ms); bw.Write((ushort)subList.Count); bw.Write((ushort)OriginalKeys[i]); int num = (OriginalKeys[i] * 0x2fd) & 0xffff, num4 = 4 + (subList.Count * 8); int[] numArray = new int[subList.Count]; for (int j = 0; j < subList.Count; j++) { int num2 = (num * (j + 1)) & 0xffff; int num3 = num2 | (num2 << 16); bw.Write((uint)(num4 ^ num3)); numArray[j] = GetRealSize(subList[j]); bw.Write((uint)(GetRealSize(subList[j]) ^ num3)); num4 += GetRealSize(subList[j]) * 2; } for (int k = 0; k < subList.Count; k++) { num = (0x91bd3 * (k + 1)) & 0xffff; int[] numArray2 = EncodeText(subList[k], numArray[k], charTable); for (int l = 0; l < numArray[k] - 1; l++) { bw.Write((short)(numArray2[l] ^ num)); num += 0x493d; num &= 0xffff; } bw.Write((short)(0xffff ^ num)); } byte[] bytes = new byte[ms.Position]; ms.Position = 0; ms.Read(bytes, 0, bytes.Length); files.Files[i] = bytes; bw.Close(); } }
public Text_4(Narc files, CharTable charTable) { Version = 3; TextList.Clear(); TextList.Add(new List <List <string> >()); foreach (byte[] bytes in files.Files) { BinaryReader br = new BinaryReader(new MemoryStream(bytes)); List <string> s4 = new List <string>(); bool flag2 = false; int stringCount = br.ReadUInt16(), originalKey = br.ReadUInt16(); OriginalKeys.Add(originalKey); int num = (originalKey * 0x2fd) & 0xffff; int[] numArray = new int[stringCount]; int[] numArray2 = new int[stringCount]; for (int i = 0; i < stringCount; i++) { int num2 = (num * (i + 1)) & 0xffff; int num3 = num2 | (num2 << 16); numArray[i] = br.ReadInt32(); numArray[i] = numArray[i] ^ num3; numArray2[i] = br.ReadInt32(); numArray2[i] = numArray2[i] ^ num3; } for (int j = 0; j < stringCount; j++) { int control = 0; num = (0x91bd3 * (j + 1)) & 0xffff; string text = ""; for (int k = 0; k < numArray2[j]; k++) { int num4 = br.ReadUInt16(); num4 ^= num; switch (control) { case 0: switch (num4) { case 0xE000: text += "\\n"; break; case 0x25BC: if (Version > 2) { text += "\\f"; } else { text += "\\r"; } break; case 0x25BD: if (Version > 2) { text += "\\r"; } else { text += "\\f"; } break; case 0xF100: flag2 = true; break; case 0xFFFE: text += "["; control = 1; break; case 0xFFFF: break; default: if (flag2) { int num5 = 0; int num6 = 0; string str = null; while (true) { if (num5 >= 15) { num5 -= 15; if (num5 > 0) { int num8 = num6 | (num4 << 9 - num5 & 511); if ((num8 & 255) == 255) { break; } if (num8 != 0 && num8 != 1) { char str2 = charTable.GetCharacter(num8); if (str2 == '\0') { text += "\\x" + num8.ToString("X4"); } else { text += str2; } } } } else { int num8 = num4 >> num5 & 511; if ((num8 & 255) == 255) { break; } if (num8 != 0 && num8 != 1) { char str3 = charTable.GetCharacter(num8); if (str3 == '\0') { text += "\\x" + num8.ToString("X4"); } else { text += str3; } } num5 += 9; if (num5 < 15) { num6 = num4 >> num5 & 511; num5 += 9; } num += 18749; num &= 65535; num4 = br.ReadUInt16(); num4 ^= num; k++; } } text += str; } else { char str3 = charTable.GetCharacter(num4); if (str3 == '\0') { text += "\\x" + num4.ToString("X4"); } else { text += str3; } } break; } break; case 1: text += num4.ToString("X4"); if (num4 == 0x0129) // 不知道为何,很奇怪的控制符 { control = 3; } else { control = 2; } break; case 2: control = -num4; if (control == 0) { text += "]"; } break; case 3: control = -num4 + 1; if (control == 0) { text += "]"; } break; default: text += "," + num4.ToString("X4"); control++; if (control == 0) { text += "]"; } break; } num += 18749; num &= 65535; } s4.Add(text); } TextList[0].Add(s4); } }
public Text_5(Narc files, CharTable charTable) { TextList.Clear(); TextList.Add(new List <List <string> >()); TextList.Add(new List <List <string> >()); foreach (byte[] bytes in files.Files) { BinaryReader br = new BinaryReader(new MemoryStream(bytes)); ushort numSections, numEntries, tmpCharCount, tmpUnknown, tmpChar; uint unk1, tmpOffset; uint[] sizeSections = new uint[] { 0, 0 }; uint[] sectionOffset = new uint[] { 0, 0 }; ushort key; numSections = br.ReadUInt16(); numEntries = br.ReadUInt16(); sizeSections[0] = br.ReadUInt32(); unk1 = br.ReadUInt32(); for (int i = 0; i < numSections; i++) { sectionOffset[i] = br.ReadUInt32(); } for (int i = 0; i < TextList.Count; i++) { List <string> s = new List <string>(); List <ushort> keys = new List <ushort>(); List <ushort> unknowns = new List <ushort>(); List <ushort> characterCount = new List <ushort>(); if (i < numSections) { br.BaseStream.Position = sectionOffset[i]; sizeSections[i] = br.ReadUInt32(); List <uint> tableOffsets = new List <uint>(); List <List <ushort> > encText = new List <List <ushort> >(); for (int j = 0; j < numEntries; j++) { tmpOffset = br.ReadUInt32(); tmpCharCount = br.ReadUInt16(); tmpUnknown = br.ReadUInt16(); tableOffsets.Add(tmpOffset); characterCount.Add(tmpCharCount); unknowns.Add(tmpUnknown); } for (int j = 0; j < numEntries; j++) { List <ushort> tmpEncChars = new List <ushort>(); br.BaseStream.Position = sectionOffset[i] + tableOffsets[j]; for (int k = 0; k < characterCount[j]; k++) { tmpChar = br.ReadUInt16(); tmpEncChars.Add(tmpChar); } encText.Add(tmpEncChars); key = (ushort)(encText[j][characterCount[j] - 1] ^ 0xFFFF); for (int k = characterCount[j] - 1; k >= 0; k--) { encText[j][k] ^= key; if (k == 0) { keys.Add(key); } key = (ushort)(((key >> 3) | (key << 13)) & 0xFFFF); } string line = ""; for (int k = 0; k < characterCount[j]; k++) { if (encText[j][k] > 20 && encText[j][k] <= 0xFFF0 && encText[j][k] != 0xF000) { line += (char)encText[j][k]; } else if (encText[j][k] == 0xFFFE) { line += "\\n"; } else if (encText[j][k] == 0xFFFF) { // line += "\\xFFFF"; } else if (encText[j][k] == 0xF000) { switch (encText[j][k + 1]) { case 0xBE00: line += "\\r"; break; case 0xBE01: line += "\\f"; break; default: line += $"[{encText[j][k + 1]:X4}"; for (int control = 0; control < encText[j][k + 2]; control++) { line += $",{encText[j][k + 3 + control]:X4}"; } line += "]"; break; } k += 2 + encText[j][k + 2]; } else { line += $"\\x{encText[j][k]:X4}"; } } s.Add(line); } } TextList[i].Add(s); Keys[i].Add(keys); Unknowns[i].Add(unknowns); OriginalLengths[i].Add(characterCount); } } }