1use crate::GcmError;
2use core::mem::size_of;
3use binread::{BinRead, BinReaderExt, io::{self, SeekFrom}, helpers::read_bytes};
4
5#[cfg(feature = "no_std")]
6use crate::std::vec::Vec;
7
8const SECTION_COUNT: usize = 18;
9
10#[derive(BinRead, Debug)]
13pub struct DolHeader {
14 pub section_offsets: [u32; SECTION_COUNT],
15 pub section_addresses: [u32; SECTION_COUNT],
16 pub section_lengths: [u32; SECTION_COUNT],
17
18 pub bss_address: u32,
19 pub bss_length: u32,
20
21 pub entrypoint: u32,
22}
23
24impl DolHeader {
25 const SIZE: usize = (SECTION_COUNT * size_of::<u32>() * 3) + (size_of::<u32>() * 3);
26
27 pub fn calculate_file_size(&self) -> usize {
28 self.section_offsets
29 .iter()
30 .zip(self.section_lengths.iter())
31 .map(|(start, len)| (start + len) as usize)
32 .max()
33 .unwrap()
34 }
35}
36
37#[derive(BinRead)]
47pub struct DolFile {
48 pub header: DolHeader,
49
50 #[br(seek_before = SeekFrom::Current(-(DolHeader::SIZE as i64)))]
51 #[br(count = header.calculate_file_size())]
52 #[br(parse_with = read_bytes)]
53 pub raw_data: Vec<u8>,
54}
55
56impl DolFile {
57 pub fn from_reader<R>(reader: &mut R) -> Result<Self, GcmError>
59 where R: io::Read + io::Seek,
60 {
61 Ok(reader.read_be()?)
62 }
63}
64
65#[cfg(not(feature = "no_std"))]
66use std::path::Path;
67
68#[cfg(not(feature = "no_std"))]
69impl DolFile {
70 pub fn open<P>(path: P) -> Result<Self, GcmError>
72 where P: AsRef<Path>,
73 {
74 let mut reader = std::io::BufReader::new(std::fs::File::open(path)?);
75 Ok(reader.read_be()?)
76 }
77}
78
79use core::fmt;
80
81impl fmt::Debug for DolFile {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 f.debug_struct("DolFile")
84 .field("header", &self.header)
85 .finish()
86 }
87}