Skip to main content

ds_rom/rom/raw/
overlay_table.rs

1use std::{borrow::Cow, fmt::Display};
2
3use super::{HmacSha1Signature, Overlay};
4use crate::crypto::hmac_sha1::HmacSha1;
5
6/// An overlay table, used for both ARM9 and ARM7 overlays. This is the raw struct, see the plain one [here](crate::rom::OverlayTable).
7pub struct OverlayTable<'a> {
8    overlays: Cow<'a, [Overlay]>,
9    signature: Option<HmacSha1Signature>,
10}
11
12impl<'a> OverlayTable<'a> {
13    /// Creates a new overlay table.
14    pub fn new<O>(overlays: O, signature: Option<HmacSha1Signature>) -> Self
15    where
16        O: Into<Cow<'a, [Overlay]>>,
17    {
18        Self { overlays: overlays.into(), signature }
19    }
20
21    /// Returns the overlays in the table.
22    pub fn overlays(&'a self) -> &'a [Overlay] {
23        self.overlays.as_ref()
24    }
25
26    /// Computes the HMAC-SHA1 signature of this overlay table using the given HMAC-SHA1 instance.
27    pub fn compute_signature(&self, hmac_sha1: &HmacSha1) -> HmacSha1Signature {
28        let bytes = bytemuck::cast_slice(&self.overlays);
29        HmacSha1Signature::from_hmac_sha1(hmac_sha1, bytes)
30    }
31
32    /// Verifies the HMAC-SHA1 signature of this overlay table using the given HMAC-SHA1 instance.
33    pub fn verify_signature(&self, hmac_sha1: &HmacSha1) -> bool {
34        let Some(signature) = self.signature() else {
35            return true;
36        };
37
38        let computed_signature = self.compute_signature(hmac_sha1);
39        computed_signature == signature
40    }
41
42    /// Returns the HMAC-SHA1 signature of the overlay table, if it exists.
43    pub fn signature(&self) -> Option<HmacSha1Signature> {
44        self.signature
45    }
46
47    /// Returns `true` if this overlay table has an HMAC-SHA1 signature.
48    pub fn is_signed(&self) -> bool {
49        self.signature.is_some()
50    }
51
52    /// Returns the raw bytes of the overlay table.
53    pub fn as_bytes(&self) -> &[u8] {
54        bytemuck::cast_slice(self.overlays.as_ref())
55    }
56
57    /// Returns a [`DisplayOverlayTable`] which implements [`Display`].
58    pub fn display(&'a self, indent: usize) -> DisplayOverlayTable<'a> {
59        DisplayOverlayTable { overlay_table: self, indent }
60    }
61}
62
63/// Can be used to display values in [`OverlayTable`].
64pub struct DisplayOverlayTable<'a> {
65    overlay_table: &'a OverlayTable<'a>,
66    indent: usize,
67}
68
69impl Display for DisplayOverlayTable<'_> {
70    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71        let i = " ".repeat(self.indent);
72        let overlay_table = &self.overlay_table;
73        let overlays = overlay_table.overlays();
74        let signature = overlay_table.signature().map_or("None".to_string(), |s| s.to_string());
75
76        writeln!(f, "{i}Overlay Table:")?;
77        writeln!(f, "{i}Signature: {}", signature)?;
78        writeln!(f, "{i}Overlays:")?;
79
80        for overlay in overlays {
81            writeln!(f, "{}", overlay.display(self.indent + 2))?;
82        }
83
84        Ok(())
85    }
86}