/[MorrowindCustomClothingSlotCreator]/trunk/libTES3FileFormat/PlugingClothing.cs
ViewVC logotype

Contents of /trunk/libTES3FileFormat/PlugingClothing.cs

Parent Directory Parent Directory | Revision Log Revision Log


Revision 33 - (show annotations) (download)
Sat Jul 30 11:47:53 2011 UTC (8 years, 6 months ago) by william
File size: 19270 byte(s)
*** work out committing individual entries back into the main data stream

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.IO;
6 using System.Diagnostics;
7 using System.Windows.Forms;
8
9 namespace libTES3FileFormat
10 {
11
12 public enum ClothingTypes
13 {
14 Pants, /* 0 */
15 Shoes, /* 1 */
16 Shirt, /* 2 */
17 Belt, /* 3 */
18 Robe, /* 4 */
19 RightGlove, /* 5 */
20 LeftGlove, /* 6 */
21 Skirt, /* 7 */
22 Ring, /* 8 */
23 Amulet, /* 9 */
24 }
25
26 public interface IClothingEntry : IOffset
27 {
28 byte[] CLOT_MAGIC { get; } // 4bytes, CLOT
29 byte[] CLOT_SIZE { get; set; } // 12 bytes
30
31 byte[] CLOT_NAME_MAGIC { get; } // 4bytes, NAME
32 int CLOT_NAME_LENGTH { get; }//4 bytes, name length
33 string CLOT_NAME { get; set; } // variable length, null terminated
34
35 byte[] CLOT_MODL_MAGIC { get; } // 4bytes, MODL
36 int CLOT_MODL_LENGTH { get; }//4 bytes, MODL length
37 string CLOT_MODL { get; set; } // variable length, null terminated
38
39 byte[] CLOT_FULLNAME_MAGIC { get; } // 4bytes, FNAM
40 int CLOT_FULLNAME_LENGTH { get; }//4 bytes, FNAM length
41 string CLOT_FULLNAME { get; set; } // variable length, null terminated
42
43 byte[] CLOT_CTDT_MAGIC { get; } // 4bytes, CTDT
44 int CLOT_CTDT_TYPE { get; set; }//4 bytes
45 float CLOT_CTDT_WEIGHT { get; set; }//4 bytes
46 short CLOT_CTDT_VALUE { get; set; }//2 bytes
47 short CLOT_CTDT_ENCHANTPTS { get; set; }//2 bytes
48
49 byte[] CLOT_OTHER_DATA { get; set; } // the rest of the clothing data entry
50 }
51 public class ClothingEntry : IClothingEntry, IComparable
52 {
53 internal EntryCommitEvent<ClothingEntry> OnEntryCommitEvent;
54
55 //internal BinaryWriter writer = null;
56
57 public bool Commit(ICommitWriter commit_writer)
58 {
59 if (this.OnEntryCommitEvent != null)
60 {
61 return this.OnEntryCommitEvent.Invoke(this, commit_writer);
62 }
63 return false;
64 }
65
66
67 internal bool WriteCommit(ICommitWriter commit_writer)
68 {
69 bool ret = true;
70 BinaryWriter bw = commit_writer.GetWriter();
71 if (bw == null) return false;
72 bw.Seek(this.Offset, SeekOrigin.Begin);
73 // write out the data
74 try
75 {
76 bw.Write(this.CLOT_MAGIC);
77 bw.Write(this.CLOT_SIZE);
78
79 bw.Write(this.CLOT_NAME_MAGIC);
80 bw.Write(this.CLOT_NAME_LENGTH);
81 bw.Write(ASCIIEncoding.ASCII.GetBytes(this.CLOT_NAME));
82
83 bw.Write(this.CLOT_MODL_MAGIC);
84 bw.Write(this.CLOT_MODL_LENGTH);
85 bw.Write(ASCIIEncoding.ASCII.GetBytes(this.CLOT_MODL));
86
87 bw.Write(this.CLOT_FULLNAME_MAGIC);
88 bw.Write(this.CLOT_FULLNAME_LENGTH);
89 bw.Write(ASCIIEncoding.ASCII.GetBytes(this.CLOT_FULLNAME));
90
91 bw.Write(this.CLOT_CTDT_MAGIC);
92 bw.Write(this.CLOT_CTDT_SIZE);
93 bw.Write(this.CLOT_CTDT_TYPE);
94 bw.Write(this.CLOT_CTDT_WEIGHT);
95 bw.Write(this.CLOT_CTDT_VALUE);
96 bw.Write(this.CLOT_CTDT_ENCHANTPTS);
97
98 bw.Write(this.CLOT_OTHER_DATA);
99 }
100 catch (Exception ex) { Console.WriteLine(ex.ToString()); ret = false; }
101 return ret;
102 }
103
104 #region IComparable Members
105 public int CompareTo(object obj) { return this.CLOT_NAME.CompareTo((obj as ClothingEntry).CLOT_NAME); }
106 #endregion
107 public ClothingEntry()
108 {
109 this.Offset = 0;
110 this.CLOT_SIZE = new byte[12];
111 this.CLOT_NAME = "";
112 this.CLOT_MODL = "";
113 this.CLOT_FULLNAME = "";
114 this.CLOT_CTDT_TYPE = (int)ClothingTypes.Amulet;
115 this.CLOT_CTDT_WEIGHT = 0;
116 this.CLOT_CTDT_VALUE = 0;
117 this.CLOT_CTDT_ENCHANTPTS = 0;
118 this.CLOT_OTHER_DATA = new byte[0];
119 }
120 #region IOffset Members
121 private int _Offset;
122 public int Offset { get { return _Offset; } set { _Offset = value; } }
123 #endregion
124 #region IClothingEntry Members
125 public byte[] CLOT_MAGIC { get { return ASCIIEncoding.ASCII.GetBytes("CLOT"); } } // 4bytes, CLOT
126 private byte[] _CLOT_SIZE;
127 public byte[] CLOT_SIZE { get { return _CLOT_SIZE; } set { _CLOT_SIZE = value; Debug.Assert(value.Length == 12, "Excepted CLOT_SIZE of 12 bytes. Found: " + value.Length + " bytes"); } }// 12 bytes
128
129 public byte[] CLOT_NAME_MAGIC { get { return ASCIIEncoding.ASCII.GetBytes("NAME"); } } // 4bytes, NAME
130 public int CLOT_NAME_LENGTH { get { return CLOT_NAME.Length; } }//4 bytes, name length
131 private string _CLOT_NAME;
132 public string CLOT_NAME { get { return _CLOT_NAME; } set { _CLOT_NAME = value; } } // variable length, null terminated
133
134 public byte[] CLOT_MODL_MAGIC { get { return ASCIIEncoding.ASCII.GetBytes("MODL"); } } // 4bytes, MODL
135 public int CLOT_MODL_LENGTH { get { return CLOT_MODL.Length; } }//4 bytes, MODL length
136 private string _CLOT_MODL;
137 public string CLOT_MODL { get { return _CLOT_MODL; } set { _CLOT_MODL = value; } } // variable length, null terminated
138
139 public byte[] CLOT_FULLNAME_MAGIC { get { return ASCIIEncoding.ASCII.GetBytes("FNAM"); } } // 4bytes, FNAM
140 public int CLOT_FULLNAME_LENGTH { get { return CLOT_FULLNAME.Length; } }//4 bytes, FNAM length
141 private string _CLOT_FULLNAME;
142 public string CLOT_FULLNAME { get { return _CLOT_FULLNAME; } set { _CLOT_FULLNAME = value; } } // variable length, null terminated
143
144 public byte[] CLOT_CTDT_MAGIC { get { return ASCIIEncoding.ASCII.GetBytes("CTDT"); } } // 4bytes, CTDT
145
146 private int _CLOT_CTDT_SIZE;
147 private int _CLOT_CTDT_TYPE;
148 private float _CLOT_CTDT_WEIGHT;
149 private short _CLOT_CTDT_VALUE;
150 private short _CLOT_CTDT_ENCHANTPTS;
151
152 public int CLOT_CTDT_SIZE { get { return _CLOT_CTDT_SIZE; } set { _CLOT_CTDT_SIZE = value; } }//4 bytes
153
154 public int CLOT_CTDT_TYPE { get { return _CLOT_CTDT_TYPE; } set { _CLOT_CTDT_TYPE = value; } }//4 bytes
155 public float CLOT_CTDT_WEIGHT { get { return _CLOT_CTDT_WEIGHT; } set { _CLOT_CTDT_WEIGHT = value; } }//4 bytes
156 public short CLOT_CTDT_VALUE { get { return _CLOT_CTDT_VALUE; } set { _CLOT_CTDT_VALUE = value; } }//2 bytes
157 public short CLOT_CTDT_ENCHANTPTS { get { return _CLOT_CTDT_ENCHANTPTS; } set { _CLOT_CTDT_ENCHANTPTS = value; } }//2 bytes
158
159 private byte[] _CLOT_OTHER_DATA;
160 public byte[] CLOT_OTHER_DATA { get { return _CLOT_OTHER_DATA; } set { _CLOT_OTHER_DATA = value; } } // the rest of the clothing data entry
161 #endregion
162
163
164 }
165
166 public interface IPlugingClothing : IParse, ICommit, IAsBytes, ISizeOffset
167 {
168 Dictionary<string, ClothingEntry> ClothingEntries { get; }
169 //bool CommitEntry(ClothingEntry entry);
170 }
171 public class PlugingClothing : IPlugingClothing, ICommitParseAsBytes
172 {
173 private ConsoleLog Log;
174 private const string CLOTHING_MAGIC = "\0CLOT";
175 private const string CLOTHING_NAME_MAGIC = "NAME";
176 MemoryStream reader = new MemoryStream();
177 private List<int> SectionOffsets = new List<int>();
178 public PlugingClothing()
179 {
180 this.reader = new MemoryStream();
181 this.Offset = 0;
182 this.Size = 0;
183 this.SectionOffsets = new List<int>();
184 this.ClothingEntries = new Dictionary<string, ClothingEntry>();
185 }
186 public PlugingClothing(BinaryReader br, List<int> SectionOffsets, bool ReadOnly, ConsoleLog Log)
187 : this()
188 {
189 this.Log = Log;
190 br.BaseStream.Seek(0, SeekOrigin.Begin);
191 //this.Offset = offset;
192 //this.Size = size;
193 this.SectionOffsets = SectionOffsets;
194 this.reader = new MemoryStream(br.ReadBytes((int)br.BaseStream.Length), 0, (int)br.BaseStream.Length);
195 this.Parse(this.reader);
196 }
197 #region IPlugingClothing Members
198 private Dictionary<string, ClothingEntry> _ClothingEntries;
199 public Dictionary<string, ClothingEntry> ClothingEntries
200 {
201 get { return _ClothingEntries; }
202 private set { _ClothingEntries = value; }
203 }
204
205 #endregion
206
207 internal bool CommitEntry(ClothingEntry entry, ICommitWriter writer)
208 {
209 bool ret = false;
210 //if (writer == null) writer = new BinaryWriter(this.reader);
211
212 ret = entry.WriteCommit(writer);
213 return ret;
214 }
215 internal bool CommitAllEntries(ICommitWriter writer)
216 {
217 bool ret = false;
218 foreach (KeyValuePair<string, ClothingEntry> key_pair in this.ClothingEntries)
219 {
220 ret = key_pair.Value.OnEntryCommitEvent(key_pair.Value, writer);
221 }
222 return ret;
223 }
224 #region IParse Members
225
226 public bool Parse(MemoryStream stream)
227 {
228 BinaryReader br = new BinaryReader(stream);
229 this.Log.WriteLine();
230 // read header section magic
231
232 for (int i = 0; i < this.SectionOffsets.Count; i++)
233 {
234 ClothingEntry entry = new ClothingEntry();
235 entry.OnEntryCommitEvent = new EntryCommitEvent<ClothingEntry>(this.CommitEntry); // commit callback
236 entry.Offset = this.SectionOffsets[i]; // set the offset for this entry
237
238 br.BaseStream.Seek(this.SectionOffsets[i], SeekOrigin.Begin);
239 this.Log.WriteLine(string.Format("Clothing Section: Index=0x{0:x8} Offset=0x{1:x8}", i,(int)br.BaseStream.Position));
240
241 byte[] magic = br.ReadBytes(4);
242 string str_magic = ASCIIEncoding.ASCII.GetString(magic);
243 Debug.Assert(str_magic == "CLOT", string.Format("Excepted: {0} found: {1}", "CLOT", str_magic));
244
245 // Clothing Name
246 byte[] section_size_bytes = br.ReadBytes(12);
247 int section_size = BitConverter.ToInt32(section_size_bytes, 0);
248
249 entry.CLOT_SIZE = section_size_bytes; // set the clot size
250
251 int name_offset = (int)br.BaseStream.Position;
252 magic = br.ReadBytes(4);
253 str_magic = ASCIIEncoding.ASCII.GetString(magic);
254 Debug.Assert(str_magic == "NAME", string.Format("Excepted: {0} found: {1}", "NAME", str_magic));
255
256 int name_size = br.ReadInt32();
257
258 this.Log.WriteLine("\t\tClothing Name Size: " + name_size.ToString());
259 byte[] name_bytes = br.ReadBytes(name_size);
260 string ClothingName = ASCIIEncoding.ASCII.GetString(name_bytes);
261
262 entry.CLOT_NAME = ClothingName; // set the NAME
263
264 this.Log.WriteLine("\t\tClothing Name : " + ClothingName);
265
266
267 // Clothing Model
268 magic = br.ReadBytes(4);
269 str_magic = ASCIIEncoding.ASCII.GetString(magic);
270 Debug.Assert(str_magic == "MODL", string.Format("Excepted: {0} found: {1}", "MODL", str_magic));
271
272 int modl_name_size = br.ReadInt32();
273 this.Log.WriteLine("\t\tClothing Model Name Size: " + modl_name_size.ToString());
274 byte[] modl_name_bytes = br.ReadBytes(modl_name_size);
275 string ClothingModelName = ASCIIEncoding.ASCII.GetString(modl_name_bytes);
276
277 entry.CLOT_MODL = ClothingModelName; // set the MODL
278
279 this.Log.WriteLine("\t\tClothing Model Name: " + ClothingModelName);
280
281 // Clothing Full Name
282 magic = br.ReadBytes(4);
283 str_magic = ASCIIEncoding.ASCII.GetString(magic);
284 Debug.Assert(str_magic == "FNAM", string.Format("Excepted: {0} found: {1}", "FNAM", str_magic));
285
286 int fname_size = br.ReadInt32();
287 this.Log.WriteLine("\t\tClothing FullName Size: " + fname_size.ToString());
288 byte[] fname_bytes = br.ReadBytes(fname_size);
289 string ClothingFullName = ASCIIEncoding.ASCII.GetString(fname_bytes);
290 entry.CLOT_FULLNAME = ClothingFullName; // set the full name
291 this.Log.WriteLine("\t\tClothing FullName: " + ClothingFullName);
292
293 // Clothing Data
294 magic = br.ReadBytes(4);
295 str_magic = ASCIIEncoding.ASCII.GetString(magic);
296 Debug.Assert(str_magic == "CTDT", string.Format("Excepted: {0} found: {1}", "CTDT", str_magic));
297
298 int ctdt_size = br.ReadInt32();
299
300 int ctdt_type = br.ReadInt32();
301 string ctdt_type_string = "";
302
303 try
304 {
305 ctdt_type_string = Enum.GetName(typeof(ClothingTypes), ctdt_type);
306 }
307 catch { ctdt_type_string = "unknown"; }
308
309
310 float ctdt_weight = br.ReadSingle();
311 short ctdt_value = br.ReadInt16();
312 short ctdt_echant_pts = br.ReadInt16();
313
314
315 entry.CLOT_CTDT_SIZE = ctdt_size; // set the size
316 entry.CLOT_CTDT_TYPE = ctdt_type; // set the type
317 entry.CLOT_CTDT_WEIGHT = ctdt_weight; // set the weight
318 entry.CLOT_CTDT_VALUE = ctdt_value; // set the value
319 entry.CLOT_CTDT_ENCHANTPTS = ctdt_echant_pts; // set the enchant pts
320
321 this.Log.WriteLine("\t\tClothing Data: ");
322 this.Log.WriteLine("\t\t\tType: " + ctdt_type + " (" + ctdt_type_string +")");
323 this.Log.WriteLine("\t\t\tWeight: " + ctdt_weight);
324 this.Log.WriteLine("\t\t\tValue: " + ctdt_value);
325 this.Log.WriteLine("\t\t\tEnchant Points: " + ctdt_echant_pts);
326
327
328
329 //magic = br.ReadBytes(4);
330 //str_magic = ASCIIEncoding.ASCII.GetString(magic);
331 //Debug.Assert(str_magic == "SCRI", string.Format("Excepted: {0} found: {1}", "SCRI", str_magic));
332 //br.BaseStream.Position = br.BaseStream.Position - 4; // back up 4 bytes
333 //int length_till_end_of_section = (name_offset + section_size) + 0x10;
334 int length_till_end_of_section = (name_offset + section_size) - (int)br.BaseStream.Position;
335
336
337 //try
338 //{
339 byte[] extra_clothing_data = br.ReadBytes(length_till_end_of_section);
340 entry.CLOT_OTHER_DATA = extra_clothing_data; // set the extra data
341 //}
342 //catch { break; }
343
344 //break;
345 this.ClothingEntries.Add(entry.CLOT_NAME, entry);
346 //this.ClothingEntries.Sort(); // sorting should not cause any major issues, since each entry holds its own offset
347 }
348
349
350 return true;
351 }
352
353 #endregion
354
355 #region ICommit Members
356
357 public bool Commit(ICommitWriter writer)
358 {
359 return this.CommitAllEntries(writer);
360 }
361
362 #endregion
363
364 #region IAsBytes Members
365
366 public byte[] AsBytes
367 {
368 get
369 {
370 this.reader.Seek(0, SeekOrigin.Begin);
371 BinaryReader br = new BinaryReader(this.reader);
372 return br.ReadBytes(this.Size);
373 }
374 }
375
376 #endregion
377
378 #region ISizeOffset Members
379
380 private int _Size;
381 public int Size { get { return _Size; } private set { _Size = value; } } // headersize
382
383 private int _Offset;
384 public int Offset { get { return _Offset; } private set { _Offset = value; } }
385 public int OffsetToNext { get { return this.Size + this.Offset; } } // force this to 16 bytes
386 #endregion
387
388 #region Sub-Classes
389 public class SectionLocater : IParse, IOffset, ISize
390 {
391 private ConsoleLog Log;
392 MemoryStream reader = new MemoryStream();
393 public SectionLocater()
394 {
395 this.reader = new MemoryStream();
396 this.Log = new ConsoleLog();
397 this.ClothingSectionOffsets = new List<int>();
398
399 }
400 public SectionLocater(BinaryReader br, int CurrentOffset, ConsoleLog Log) : this()
401 {
402 this.Log = Log;
403 br.BaseStream.Seek(0, SeekOrigin.Begin);
404 this.Offset = CurrentOffset;
405 this.reader = new MemoryStream(br.ReadBytes((int)br.BaseStream.Length), CurrentOffset, (int)br.BaseStream.Length - CurrentOffset);
406 this.Parse(this.reader);
407 }
408
409 #region IParse Members
410
411 public bool Parse(MemoryStream stream)
412 {
413 BinaryReader br = new BinaryReader(stream);
414 this.Log.WriteLine();
415
416 byte[] data = br.ReadBytes((int)br.BaseStream.Length);
417
418
419 this.ClothingSectionOffsets = new List<int>();
420
421 foreach (var position in data.Locate(ASCIIEncoding.ASCII.GetBytes(PlugingClothing.CLOTHING_MAGIC)))
422 {
423 this.ClothingSectionOffsets.Add(position + 0x1); // add 1 byte to remove the \0,
424 }
425
426 if (this.ClothingSectionOffsets.Count == 0)
427 {
428 this.Log.WriteLine("\t\tNo Clothing Section Could be Found!");
429 }
430 else
431 {
432 this.Log.WriteLine("\t\tFound 0x" + this.ClothingSectionOffsets.Count.ToString("x2") + "clothing sections");
433 }
434
435 return true;
436 }
437
438 #endregion
439
440
441
442 #region IOffset Members
443 private int _Offset;
444 public int Offset
445 {
446 get { return _Offset; }
447 private set { _Offset = value; }
448 }
449 private int _Size;
450 public int Size
451 {
452 get { return _Size; }
453 private set { _Size = value; }
454 }
455 private List<int> _ClothingSectionOffsets;
456 public List<int> ClothingSectionOffsets
457 {
458 get { return _ClothingSectionOffsets; }
459 private set { _ClothingSectionOffsets = value; }
460 }
461 #endregion
462 }
463 #endregion
464
465
466 }
467 }

  ViewVC Help
Powered by ViewVC 1.1.22