DirtyEncoder.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text;
  7. namespace FF8
  8. {
  9. /// <summary>
  10. /// class to add function to dictionary
  11. /// </summary>
  12. /// <see cref="https://stackoverflow.com/questions/22595655/how-to-do-a-dictionary-reverse-lookup"/>
  13. public static class DictionaryEx
  14. {
  15. #region Methods
  16. /// <summary>
  17. /// Reverses Key and Value of dictionary.
  18. /// </summary>
  19. /// <typeparam name="TKey"></typeparam>
  20. /// <typeparam name="TValue"></typeparam>
  21. /// <param name="source"></param>
  22. /// <returns></returns>
  23. public static Dictionary<TValue, TKey> Reverse<TKey, TValue>(this IDictionary<TKey, TValue> source)
  24. {
  25. Dictionary<TValue, TKey> dictionary = new Dictionary<TValue, TKey>();
  26. foreach (KeyValuePair<TKey, TValue> entry in source)
  27. {
  28. if (!dictionary.ContainsKey(entry.Value))
  29. dictionary.Add(entry.Value, entry.Key);
  30. }
  31. return dictionary;
  32. }
  33. #endregion Methods
  34. }
  35. /// <summary>
  36. /// This holds the encoded bytes and provides implict casts to string and byte[]
  37. /// </summary>
  38. public class FF8String : IEnumerator, IEnumerable
  39. {
  40. #region Fields
  41. private byte[] value;
  42. private int position = 0;
  43. #endregion Fields
  44. #region Constructors
  45. public FF8String()
  46. {
  47. }
  48. public FF8String(byte[] @value) => Value = @value;
  49. public FF8String(string @value) => Value = Memory.DirtyEncoding.GetBytes(@value);
  50. #endregion Constructors
  51. #region Properties
  52. public byte[] Value { get => value; set => this.value = value; }
  53. public string Value_str => ToString();
  54. public int Length => value==null? 0:value.Length;
  55. public object Current { get => Value[position-1] ; }
  56. #endregion Properties
  57. #region Indexers
  58. public byte this[int index] => value[index];
  59. #endregion Indexers
  60. #region Methods
  61. public static implicit operator byte[] (FF8String input) => input?.Value;
  62. public static implicit operator FF8String(string input) => new FF8String(input);
  63. public static implicit operator FF8String(byte[] input) => new FF8String(input);
  64. public static implicit operator string(FF8String input) => input?.ToString();
  65. public override string ToString() => Memory.DirtyEncoding.GetString(Value);
  66. public bool MoveNext() => ++position <= Length;
  67. public void Reset() => position = 0;
  68. public IEnumerator GetEnumerator() => this;
  69. public FF8String Append(FF8String end)
  70. {
  71. if (end != null && end.Length > 0)
  72. {
  73. Array.Resize(ref value, Length + end.Length);
  74. Array.Copy(end, 0, value, Length, end.Length);
  75. }
  76. return this;
  77. }
  78. public static FF8String Combine(FF8String start,FF8String end)
  79. {
  80. if (end != null && end.Length > 0)
  81. {
  82. byte[] combine = new byte[start.Length + end.Length];
  83. Array.Copy(start, 0, combine, 0, start.Length);
  84. Array.Copy(end, 0, combine, start.Length, end.Length);
  85. return combine;
  86. }
  87. else
  88. return start;
  89. }
  90. public FF8String ReplaceRegion()
  91. {
  92. int i = 0;
  93. do
  94. {
  95. i = Array.FindIndex(value, i, Length - i, x => x == 0x0E);
  96. if (i >= 0)
  97. {
  98. byte id = (byte)(value[i + 1] - 0x20);
  99. //byte[] start = value.Take(i).ToArray();
  100. byte[] newdata = Memory.Strings.Read(Strings.FileID.NAMEDIC, 0, id);
  101. byte[] end = value.Skip(2 + i).ToArray();
  102. Array.Resize(ref value, Length + newdata.Length - 2);
  103. Array.Copy(newdata,0,value,i,newdata.Length);
  104. Array.Copy(end, 0, value, i+newdata.Length, end.Length);
  105. i+=newdata.Length;
  106. }
  107. }
  108. while (i >= 0&& i < Length);
  109. return this;
  110. }
  111. #endregion Methods
  112. }
  113. /// <summary>
  114. /// Goal is to improve conversion from FF8 byte[] to string and back. possible 0 to 4 ratio on
  115. /// special chracters.
  116. /// </summary>
  117. internal class DirtyEncoding : Encoding
  118. {
  119. #region Fields
  120. public static readonly Dictionary<byte, char> BytetoChar = new Dictionary<byte, char>
  121. {
  122. //Commented out special bytes so they are passed through and I can see them in the dump file. Then I can figure out what to do with them.
  123. {0x00, '\0'},// pos:-32, col:0, row:-1 -- is end of a string. MSG files have more than one string sepperated by \0
  124. //{0x01, ''},// pos:-31, col:0, row:0 -- //some strings start with 0x01. might mark correct answer on SeeD exams.
  125. {0x02, '\n'},// pos:-30, col:0, row:0 -- new line
  126. //{0x03, ''},// pos:-29, col:0, row:0 -- special character. {0x03,0x40 = [Angelo's Name]}
  127. //{0x04, ''},// pos:-28, col:0, row:0 --
  128. //{0x05, ''},// pos:-27, col:0, row:0 --
  129. //{0x06, ''},// pos:-26, col:0, row:0 --
  130. //{0x07, ''},// pos:-25, col:0, row:0 --
  131. //{0x08, ''},// pos:-24, col:0, row:0 --
  132. //{0x09, ''},// pos:-23, col:0, row:0 --
  133. //{0x0A, ''},// pos:-22, col:0, row:0 --
  134. //{0x0B, ''},// pos:-21, col:0, row:0 --
  135. //{0x0C, ''},// pos:-20, col:0, row:0 -- <MAGBYTE>
  136. //{0x0D, ''},// pos:-19, col:0, row:0 --
  137. //{0x0E, ''},// pos:-18, col:0, row:0 -- <$>
  138. //{0x0F, ''},// pos:-17, col:0, row:0 --
  139. //{0x10, ''},// pos:-16, col:0, row:0 --
  140. //{0x11, ''},// pos:-15, col:0, row:0 --
  141. //{0x12, ''},// pos:-14, col:0, row:0 --
  142. //{0x13, ''},// pos:-13, col:0, row:0 --
  143. //{0x14, ''},// pos:-12, col:0, row:0 --
  144. //{0x15, ''},// pos:-11, col:0, row:0 --
  145. //{0x16, ''},// pos:-10, col:0, row:1 --
  146. //{0x17, ''},// pos:-9, col:0, row:0 --
  147. //{0x18, ''},// pos:-8, col:0, row:0 --
  148. //{0x19, ''},// pos:-7, col:0, row:0 --
  149. //{0x1A, ''},// pos:-6, col:0, row:0 --
  150. //{0x1B, ''},// pos:-5, col:0, row:0 --
  151. //{0x1C, ''},// pos:-4, col:0, row:0 --
  152. //{0x1D, ''},// pos:-3, col:0, row:0 --
  153. //{0x1E, ''},// pos:-2, col:0, row:0 --
  154. //{0x1F, ''},// pos:-1, col:0, row:0 --
  155. {0x20, ' '},// pos:0, col:1, row:1 -- Start of font texture
  156. {0x21, '0'},// pos:1, col:2, row:1 --
  157. {0x22, '1'},// pos:2, col:3, row:1 --
  158. {0x23, '2'},// pos:3, col:4, row:1 --
  159. {0x24, '3'},// pos:4, col:5, row:1 --
  160. {0x25, '4'},// pos:5, col:6, row:1 --
  161. {0x26, '5'},// pos:6, col:7, row:1 --
  162. {0x27, '6'},// pos:7, col:8, row:1 --
  163. {0x28, '7'},// pos:8, col:9, row:1 --
  164. {0x29, '8'},// pos:9, col:10, row:1 --
  165. {0x2A, '9'},// pos:10, col:11, row:1 --
  166. {0x2B, '%'},// pos:11, col:12, row:2 --
  167. {0x2C, '/'},// pos:12, col:13, row:2 --
  168. {0x2D, ':'},// pos:13, col:14, row:2 --
  169. {0x2E, '!'},// pos:14, col:15, row:2 --
  170. {0x2F, '?'},// pos:15, col:16, row:2 --
  171. {0x30, '…'},// pos:16, col:17, row:2 --
  172. {0x31, '+'},// pos:17, col:18, row:2 --
  173. {0x32, '-'},// pos:18, col:19, row:2 --
  174. {0x33, '='},// pos:19, col:20, row:2 --
  175. {0x34, '*'},// pos:20, col:21, row:2 --
  176. {0x35, '&'},//&amp; pos:21, col:1, row:2 -- temporarly set to this so i could have formatting on pastebin
  177. {0x36, '「'},// pos:22, col:2, row:2 --
  178. {0x37, '」'},// pos:23, col:3, row:2 --
  179. {0x38, '('},// pos:24, col:4, row:2 --
  180. {0x39, ')'},// pos:25, col:5, row:2 --
  181. {0x3A, '·'},// pos:26, col:6, row:2 --
  182. {0x3B, '.'},// pos:27, col:7, row:2 --
  183. {0x3C, ','},// pos:28, col:8, row:2 --
  184. {0x3D, '~'},// pos:29, col:9, row:2 --
  185. {0x3E, '“'},// pos:30, col:10, row:2 --
  186. {0x3F, '”'},// pos:31, col:11, row:2 --
  187. {0x40, '\''},// pos:32, col:12, row:3 --
  188. {0x41, '#'},// pos:33, col:13, row:3 --
  189. {0x42, '$'},// pos:34, col:14, row:3 --
  190. {0x43, '`'},// pos:35, col:15, row:3 --
  191. {0x44, '_'},// pos:36, col:16, row:3 --
  192. {0x45, 'A'},// pos:37, col:17, row:3 --
  193. {0x46, 'B'},// pos:38, col:18, row:3 --
  194. {0x47, 'C'},// pos:39, col:19, row:3 --
  195. {0x48, 'D'},// pos:40, col:20, row:3 --
  196. {0x49, 'E'},// pos:41, col:21, row:3 --
  197. {0x4A, 'F'},// pos:42, col:1, row:3 --
  198. {0x4B, 'G'},// pos:43, col:2, row:3 --
  199. {0x4C, 'H'},// pos:44, col:3, row:3 --
  200. {0x4D, 'I'},// pos:45, col:4, row:3 --
  201. {0x4E, 'J'},// pos:46, col:5, row:3 --
  202. {0x4F, 'K'},// pos:47, col:6, row:3 --
  203. {0x50, 'L'},// pos:48, col:7, row:3 --
  204. {0x51, 'M'},// pos:49, col:8, row:3 --
  205. {0x52, 'N'},// pos:50, col:9, row:3 --
  206. {0x53, 'O'},// pos:51, col:10, row:3 --
  207. {0x54, 'P'},// pos:52, col:11, row:3 --
  208. {0x55, 'Q'},// pos:53, col:12, row:4 --
  209. {0x56, 'R'},// pos:54, col:13, row:4 --
  210. {0x57, 'S'},// pos:55, col:14, row:4 --
  211. {0x58, 'T'},// pos:56, col:15, row:4 --
  212. {0x59, 'U'},// pos:57, col:16, row:4 --
  213. {0x5A, 'V'},// pos:58, col:17, row:4 --
  214. {0x5B, 'W'},// pos:59, col:18, row:4 --
  215. {0x5C, 'X'},// pos:60, col:19, row:4 --
  216. {0x5D, 'Y'},// pos:61, col:20, row:4 --
  217. {0x5E, 'Z'},// pos:62, col:21, row:4 --
  218. {0x5F, 'a'},// pos:63, col:1, row:4 --
  219. {0x60, 'b'},// pos:64, col:2, row:4 --
  220. {0x61, 'c'},// pos:65, col:3, row:4 --
  221. {0x62, 'd'},// pos:66, col:4, row:4 --
  222. {0x63, 'e'},// pos:67, col:5, row:4 --
  223. {0x64, 'f'},// pos:68, col:6, row:4 --
  224. {0x65, 'g'},// pos:69, col:7, row:4 --
  225. {0x66, 'h'},// pos:70, col:8, row:4 --
  226. {0x67, 'i'},// pos:71, col:9, row:4 --
  227. {0x68, 'j'},// pos:72, col:10, row:4 --
  228. {0x69, 'k'},// pos:73, col:11, row:4 --
  229. {0x6A, 'l'},// pos:74, col:12, row:5 --
  230. {0x6B, 'm'},// pos:75, col:13, row:5 --
  231. {0x6C, 'n'},// pos:76, col:14, row:5 --
  232. {0x6D, 'o'},// pos:77, col:15, row:5 --
  233. {0x6E, 'p'},// pos:78, col:16, row:5 --
  234. {0x6F, 'q'},// pos:79, col:17, row:5 --
  235. {0x70, 'r'},// pos:80, col:18, row:5 --
  236. {0x71, 's'},// pos:81, col:19, row:5 --
  237. {0x72, 't'},// pos:82, col:20, row:5 --
  238. {0x73, 'u'},// pos:83, col:21, row:5 --
  239. {0x74, 'v'},// pos:84, col:1, row:5 --
  240. {0x75, 'w'},// pos:85, col:2, row:5 --
  241. {0x76, 'x'},// pos:86, col:3, row:5 --
  242. {0x77, 'y'},// pos:87, col:4, row:5 --
  243. {0x78, 'z'},// pos:88, col:5, row:5 --
  244. {0x79, 'À'},// pos:89, col:6, row:5 --
  245. {0x7A, 'Á'},// pos:90, col:7, row:5 --
  246. {0x7B, 'Â'},// pos:91, col:8, row:5 --
  247. {0x7C, 'Ä'},// pos:92, col:9, row:5 --
  248. {0x7D, 'Ç'},// pos:93, col:10, row:5 --
  249. {0x7E, 'È'},// pos:94, col:11, row:5 --
  250. {0x7F, 'É'},// pos:95, col:12, row:6 --
  251. {0x80, 'Ê'},// pos:96, col:13, row:6 --
  252. {0x81, 'Ë'},// pos:97, col:14, row:6 --
  253. {0x82, 'Ì'},// pos:98, col:15, row:6 --
  254. {0x83, 'Í'},// pos:99, col:16, row:6 --
  255. {0x84, 'Î'},// pos:100, col:17, row:6 --
  256. {0x85, 'Ï'},// pos:101, col:18, row:6 --
  257. {0x86, 'Ñ'},// pos:102, col:19, row:6 --
  258. {0x87, 'Ò'},// pos:103, col:20, row:6 --
  259. {0x88, 'Ó'},// pos:104, col:21, row:6 --
  260. {0x89, 'Ô'},// pos:105, col:1, row:6 --
  261. {0x8A, 'Ö'},// pos:106, col:2, row:6 --
  262. {0x8B, 'Ù'},// pos:107, col:3, row:6 --
  263. {0x8C, 'Ú'},// pos:108, col:4, row:6 --
  264. {0x8D, 'Û'},// pos:109, col:5, row:6 --
  265. {0x8E, 'Ü'},// pos:110, col:6, row:6 --
  266. {0x8F, 'Œ'},// pos:111, col:7, row:6 --
  267. {0x90, 'Ʀ'},// pos:112, col:8, row:6 --
  268. {0x91, 'à'},// pos:113, col:9, row:6 --
  269. {0x92, 'á'},// pos:114, col:10, row:6 --
  270. {0x93, 'â'},// pos:115, col:11, row:6 --
  271. {0x94, 'ä'},// pos:116, col:12, row:7 --
  272. {0x95, 'ç'},// pos:117, col:13, row:7 --
  273. {0x96, 'è'},// pos:118, col:14, row:7 --
  274. {0x97, 'é'},// pos:119, col:15, row:7 --
  275. {0x98, 'ê'},// pos:120, col:16, row:7 --
  276. {0x99, 'ë'},// pos:121, col:17, row:7 --
  277. {0x9A, 'ì'},// pos:122, col:18, row:7 --
  278. {0x9B, 'í'},// pos:123, col:19, row:7 --
  279. {0x9C, 'î'},// pos:124, col:20, row:7 --
  280. {0x9D, 'ï'},// pos:125, col:21, row:7 --
  281. {0x9E, 'ñ'},// pos:126, col:1, row:7 --
  282. {0x9F, 'ò'},// pos:127, col:2, row:7 --
  283. {0xA0, 'ó'},// pos:128, col:3, row:7 --
  284. {0xA1, 'ô'},// pos:129, col:4, row:7 --
  285. {0xA2, 'ö'},// pos:130, col:5, row:7 --
  286. {0xA3, 'ù'},// pos:131, col:6, row:7 --
  287. {0xA4, 'ú'},// pos:132, col:7, row:7 --
  288. {0xA5, 'û'},// pos:133, col:8, row:7 --
  289. {0xA6, 'ü'},// pos:134, col:9, row:7 --
  290. {0xA7, 'œ'},// pos:135, col:10, row:7 --
  291. {0xA8, 'Ⅷ'},// pos:136, col:11, row:7 --
  292. {0xA9, '['},// pos:137, col:12, row:8 --
  293. {0xAA, ']'},// pos:138, col:13, row:8 --
  294. {0xAB, '⬛'},// pos:139, col:14, row:8 --
  295. {0xAC, '⦾'},// pos:140, col:15, row:8 --
  296. {0xAD, '◆'},// pos:141, col:16, row:8 --
  297. {0xAE, '【'},// pos:142, col:17, row:8 --
  298. {0xAF, '】'},// pos:143, col:18, row:8 --
  299. {0xB0, '⬜'},// pos:144, col:19, row:8 --
  300. {0xB1, '★'},// pos:145, col:20, row:8 --
  301. {0xB2, '『'},// pos:146, col:21, row:8 --
  302. {0xB3, '』'},// pos:147, col:1, row:8 --
  303. {0xB4, '▽'},// pos:148, col:2, row:8 --
  304. {0xB5, ';'},// pos:149, col:3, row:8 --
  305. {0xB6, '▼'},// pos:150, col:4, row:8 --
  306. {0xB7, '‾'},// pos:151, col:5, row:8 --
  307. {0xB8, '×'},// pos:152, col:6, row:8 --
  308. {0xB9, '☆'},// pos:153, col:7, row:8 --
  309. {0xBA, '’'},// pos:154, col:8, row:8 --
  310. {0xBB, '↓'},// pos:155, col:9, row:8 --
  311. {0xBC, '°'},// pos:156, col:10, row:8 --
  312. {0xBD, '¡'},// pos:157, col:11, row:8 --
  313. {0xBE, '¿'},// pos:158, col:12, row:9 -- // pc version sysfld00 and 01 has "Slo" here so there isn't a upside down questionmark on highres.
  314. {0xBF, '—'},// pos:159, col:13, row:9 --
  315. {0xC0, '«'},// pos:160, col:14, row:9 --
  316. {0xC1, '»'},// pos:161, col:15, row:9 --
  317. {0xC2, '±'},// pos:162, col:16, row:9 --
  318. {0xC3, '♫'},// pos:163, col:17, row:9 --
  319. //{0xC4, ''},// pos:164, col:18, row:9 -- seems to be used as an alignment or a place holder many strings have 3 of these in a row.
  320. {0xC5, '↑'},// pos:165, col:19, row:9 --
  321. {0xC8, '¡'},// pos:168, col:1, row:9 --
  322. {0xC9, '™'},// pos:169, col:2, row:9 --
  323. {0xCA, '<'},// pos:170, col:3, row:9 --
  324. {0xCB, '>'},// pos:171, col:4, row:9 --
  325. {0xE2, '®'},// pos:194, col:6, row:10 -- End of font texture
  326. };
  327. /// <summary>
  328. /// multi characters bytes and double character bytes
  329. /// </summary>
  330. public static readonly Dictionary<byte, string> BytetoStr = new Dictionary<byte, string>
  331. {
  332. //{0x01, "" },
  333. {0xC6, "VI"},// pos:166, col:20, row:9 --
  334. {0xC7, "II"},// pos:167, col:21, row:9 --
  335. //pc version sysfld00 and 01
  336. {0xCC, "GA"},// pos:172, col:5, row:9 --
  337. {0xCD, "ME"},// pos:173, col:6, row:9 --
  338. {0xCE, "FO"},// pos:174, col:7, row:9 --
  339. {0xCF, "LD"},// pos:175, col:8, row:9 --
  340. {0xD0, "ER"},// pos:176, col:9, row:9 --
  341. ////original texture - sysfont
  342. //{0xCC, "ME"},// pos:172, col:5, row:9 --
  343. //{0xCD, "MO"},// pos:173, col:6, row:9 --
  344. //{0xCE, "RY"},// pos:174, col:7, row:9 --
  345. //{0xCF, "CA"},// pos:175, col:8, row:9 --
  346. //{0xD0, "RD"},// pos:176, col:9, row:9 --
  347. {0xD1, "Sl"},// pos:177, col:10, row:9 --
  348. {0xD2, "ot"},// pos:178, col:11, row:9 --
  349. {0xD3, "ing"},// pos:179, col:12, row:10 --
  350. {0xD4, "St"},// pos:180, col:13, row:10 --
  351. {0xD5, "ec"},// pos:181, col:14, row:10 --
  352. {0xD6, "kp"},// pos:182, col:15, row:10 --
  353. {0xD7, "la"},// pos:183, col:16, row:10 --
  354. {0xD8, ":z"},// pos:184, col:17, row:10 --
  355. {0xD9, "Fr"},// pos:185, col:18, row:10 --
  356. {0xDA, "nt"},// pos:186, col:19, row:10 --
  357. {0xDB, "elng"},// pos:187, col:20, row:10 --
  358. {0xDC, "re"},// pos:188, col:21, row:10 --
  359. {0xDD, "S:"},// pos:189, col:1, row:10 --
  360. {0xDE, "so"},// pos:190, col:2, row:10 --
  361. {0xDF, "Ra"},// pos:191, col:3, row:10 --
  362. {0xE0, "nu"},// pos:192, col:4, row:10 --
  363. {0xE1, "ra"},// pos:193, col:5, row:10 --
  364. //{0xE3, ""},// pos:195, col:0, row:0 --
  365. //{0xE4, ""},// pos:196, col:0, row:0 --
  366. //{0xE5, ""},// pos:197, col:0, row:0 --
  367. //{0xE6, ""},// pos:198, col:0, row:0 --
  368. //{0xE7, ""},// pos:199, col:0, row:0 --
  369. {0xE8, "in"},// pos:200, col:0, row:0 --
  370. {0xE9, "e "},// pos:201, col:0, row:0 --
  371. {0xEA, "ne"},// pos:202, col:0, row:0 --
  372. {0xEB, "to"},// pos:203, col:0, row:0 --
  373. {0xEC, "re"},// pos:204, col:0, row:0 --
  374. {0xED, "HP"},// pos:205, col:0, row:0 --
  375. {0xEE, "l "},// pos:206, col:0, row:0 --
  376. {0xEF, "ll"},// pos:207, col:0, row:0 --
  377. {0xF0, "GF"},// pos:208, col:0, row:0 --
  378. {0xF1, "nt"},// pos:209, col:0, row:0 --
  379. {0xF2, "il"},// pos:210, col:0, row:0 --
  380. {0xF3, "o "},// pos:211, col:0, row:0 --
  381. {0xF4, "ef"},// pos:212, col:0, row:0 --
  382. {0xF5, "on"},// pos:213, col:0, row:0 --
  383. {0xF6, " w"},// pos:214, col:0, row:0 --
  384. {0xF7, " r"},// pos:215, col:0, row:0 --
  385. {0xF8, "wi"},// pos:216, col:0, row:0 --
  386. {0xF9, "fi"},// pos:217, col:0, row:0 --
  387. //{0xFA, ""},// pos:218, col:0, row:0 --
  388. {0xFB, "s "},// pos:219, col:0, row:0 --
  389. {0xFC, "ar"},// pos:220, col:0, row:0 --
  390. //{0xFD, ""},// pos:221, col:0, row:0 --
  391. {0xFE, " S"},// pos:222, col:0, row:0 --
  392. {0xFF, "ag"},// pos:223, col:0, row:0 --
  393. };
  394. public static readonly Dictionary<char, byte> ChartoByte = BytetoChar.Reverse();
  395. public static readonly Dictionary<string, byte> StrtoByte = BytetoStr.Reverse();
  396. #endregion Fields
  397. #region Constructors
  398. public DirtyEncoding()
  399. {
  400. //reverse key and value pairs for dictionarys for the reverse lookup
  401. SpecialCharacters = new byte[256 - BytetoChar.Count() - BytetoStr.Count];
  402. int i = 0;
  403. for (byte b = byte.MinValue; b <= byte.MaxValue && i < SpecialCharacters.Length; b++)
  404. {
  405. if (!BytetoChar.ContainsKey(b) && !BytetoStr.ContainsKey(b))
  406. SpecialCharacters[i++] = b;
  407. }
  408. }
  409. #endregion Constructors
  410. #region Properties
  411. /// <summary>
  412. /// Lists all bytes directly passed through unalterd. Functions are expected to handle or
  413. /// skip these.
  414. /// </summary>
  415. public byte[] SpecialCharacters { get; private set; }
  416. #endregion Properties
  417. //NOTE: There are some abstract members requiring you to implement or declare in this derived class.
  418. #region Methods
  419. public override int GetByteCount(char[] chars, int index, int count) => count + index <= chars.Length ? count - index : chars.Length - index;
  420. public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex) => throw new System.NotImplementedException();
  421. public override byte[] GetBytes(string s)
  422. {
  423. if (s == null)
  424. return null;
  425. using (MemoryStream ms = new MemoryStream(GetMaxCharCount(s.Length)))
  426. using (BinaryWriter bw = new BinaryWriter(ms))
  427. {
  428. //Only way I could see to do MCB or DCB is to do a string.replace for each strtobyte.
  429. //So why not just only do SCB
  430. foreach (char c in s)
  431. {
  432. byte b = ChartoByte.ContainsKey(c) ? ChartoByte[c] : byte.Parse(c.ToString());
  433. bw.Write(b);
  434. }
  435. return ms.ToArray();
  436. }
  437. }
  438. public override int GetCharCount(byte[] bytes, int index, int count) => GetString(bytes.Skip(index).Take(count).ToArray()).Length;
  439. public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex) => throw new System.NotImplementedException();
  440. public override int GetMaxByteCount(int charCount) => charCount;
  441. public override int GetMaxCharCount(int byteCount) => byteCount * 4; //largest multichar byte is 4;
  442. public override string GetString(byte[] bytes)
  443. {
  444. //using (MemoryStream ms = new MemoryStream(GetMaxByteCount(bytes.Length)))
  445. //using (BinaryWriter bw = new BinaryWriter(ms))
  446. //using (StreamReader sr = new StreamReader(ms))
  447. //{
  448. string @out = "";
  449. foreach (byte c in bytes)
  450. {
  451. string b = BytetoChar.ContainsKey(c) ? BytetoChar[c].ToString() :
  452. BytetoStr.ContainsKey(c) ? BytetoStr[c] :
  453. ((char)c).ToString();
  454. //bw.Write(b);
  455. @out += b;
  456. }
  457. return @out;
  458. //ms.Seek(0, SeekOrigin.Begin);
  459. //return sr.ReadToEnd();
  460. // }
  461. }
  462. #endregion Methods
  463. //And many other virtual (overridable) methods which you can override to implement your custom Encoding fully
  464. }
  465. }