file.rs 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. use std::io::{Seek, SeekFrom, Write};
  2. use binrw::{BinRead, BinResult, BinWrite, BinWriterExt, Endian, FilePtr64};
  3. use crate::{array_of::ArrayOf, layer::Layer, pen::PenHeader, types::Rgba};
  4. const FILE_MAGIC: &[u8; 16] = b"E\0Z\0C\0A\0D\0X\06\04\0";
  5. #[derive(BinRead, Debug)]
  6. #[br(magic = b"E\0Z\0C\0A\0D\0X\06\04\0")]
  7. pub struct EzCadHeader {
  8. _unknown_1: [u8; 0x150],
  9. pub thumbnail_offset: FilePtr64<Thumbnail>,
  10. pub pens_offset: FilePtr64<PenHeader>,
  11. _unknown_offset: FilePtr64<Unknown>,
  12. pub layers_offset: FilePtr64<ArrayOf<Layer>>,
  13. _unknown_2: [u8; 0x1A8],
  14. }
  15. // Manually implement BinWrite as FilePtr does not support serialization
  16. // See: https://github.com/jam1garner/binrw/issues/4
  17. impl BinWrite for EzCadHeader {
  18. type Args<'a> = ();
  19. fn write_options<W: Write + Seek>(
  20. &self,
  21. writer: &mut W,
  22. endian: Endian,
  23. args: Self::Args<'_>,
  24. ) -> BinResult<()> {
  25. FILE_MAGIC.write_options(writer, endian, args)?;
  26. self._unknown_1.write_options(writer, endian, args)?;
  27. // Save offset addresses and write placeholder (zeros) for now
  28. let thumbnail_save_offset: u64 = writer.stream_position().unwrap();
  29. 0u64.write_options(writer, endian, args)?;
  30. let pens_save_offset: u64 = writer.stream_position().unwrap();
  31. 0u64.write_options(writer, endian, args)?;
  32. let unknown_save_offset: u64 = writer.stream_position().unwrap();
  33. 0u64.write_options(writer, endian, args)?;
  34. let layers_save_offset: u64 = writer.stream_position().unwrap();
  35. 0u64.write_options(writer, endian, args)?;
  36. self._unknown_2.write_options(writer, endian, args)?;
  37. // Helper fn to write current address to given offset without modifying cursor position
  38. let write_offset = |writer: &mut W, offset: u64| -> BinResult<()> {
  39. let current_offset: u64 = writer.stream_position().unwrap();
  40. writer.seek(SeekFrom::Start(offset)).unwrap();
  41. writer.write_type(&current_offset, endian)?;
  42. writer.seek(SeekFrom::Start(current_offset)).unwrap();
  43. Ok(())
  44. };
  45. // Write thumbnail contents
  46. write_offset(writer, thumbnail_save_offset)?;
  47. self.thumbnail_offset.write_options(writer, endian, args)?;
  48. // Write unknown contents
  49. write_offset(writer, unknown_save_offset)?;
  50. self._unknown_offset.write_options(writer, endian, args)?;
  51. // Write pens
  52. write_offset(writer, pens_save_offset)?;
  53. self.pens_offset.write_options(writer, endian, args)?;
  54. // Write layers
  55. write_offset(writer, layers_save_offset)?;
  56. self.layers_offset.write_options(writer, endian, args)
  57. }
  58. }
  59. #[derive(BinRead, BinWrite, Debug)]
  60. pub struct Thumbnail {
  61. _zeros_1: u32,
  62. pub dimension_x: u32,
  63. pub dimension_y: u32,
  64. _unknown_1: u32, // 0x320?
  65. _unknown_2: u32, // 0x200001?
  66. _zeros_2: [u32; 3],
  67. #[br(count = dimension_x * dimension_y)]
  68. pub pixels: Vec<Rgba>, // Takes a few ms longer than Vec<u32>
  69. }
  70. #[derive(BinRead, BinWrite, Debug)]
  71. pub struct Unknown {
  72. _zeros: u32,
  73. }