# Architecture
> A good ARCHITECTURE.md file helps developers understand how and where to make changes, whether they are new to a
> project or not.
## Layout
```
src/
├── lib.rs - crate root, re-exports module APIs
├── main.rs - binary entry point (CLI)
├── generate.rs - payload construction pipeline
├── mac.rs - Wii MAC parsing/validation
├── oui.rs - OUI MAC list
├── region.rs - Region code enum + parsing
└── bundle.rs - HackMii installer auto-loader
```
---
## Modules
### `lib`
Re-exports.
---
### `generate`
The meat and potatoes, creates the payload.
The big function is `make_payload()`, accompanied by `make_payload_now()`.
- `make_payload(&WiiMAC, &Region, bool, DateTime<Utc>) -> Option<HashMap<String, Vec<u8>>>`
- Creates a payload for region, with MAC, including or excluding BootMii, for some timestamp.
- `make_payload_now(&WiiMAC, &Region, bool) -> Option<HashMap<String, Vec<u8>>>`
- Creates a payload for region, with MAC, including or excluding BootMii, for *the current time*.
- Inline-able; just calls `make_payload` with `Utc::now()`.
The process is:
- Get the MAC's SHA-1 digest (`WiiMAC::sha1_digest()`).
- `pack_blob()` with digest, timestamp as Unix, template for region.
- Determine path of blob in SD card.
- If including bundle, copy contents of it over.
- Return map of `SD card path => file contents`.
---
### `mac`
A Wii's MAC address is used to create payloads that this Wii is able to read.
A Wii will only read messages "addressed to it".
The struct `WiiMAC` represents and validates a Wii's MAC address.
Cannot create it directly, use `TryFrom` for `(u8; 6)` or `FromStr`.
A MAC address is like `aa:bb:cc:dd:ee:ff`, as in `00:17:ab:5a:6e:f5`;
the second MAC address here *is valid* and can be/is used for testing.
A Wii MAC must start with any prefix in the OUI list.
If a Wii MAC is exactly `00:17:ab:99:99:99`, it is from an emulator and is rejected (cannot homebrew an emulator).
---
### `oui`
The OUI list is a list of MAC prefixes.
In this case, the OUI list is a list of Nintendo-assigned MAC prefixes.
Therefore, any MAC whose prefix is not on this list cannot belong to a Wii.
The OUI list has not changed in decades and is thus, hard-coded.
It is stored in `oui::oui_list()`, which is a function that lazily initializes the `HashSet<String>`.
It is not possible to store the set as a `const` or `static` because `HashSet::new` is not a `const fn`.
Therefore, it must be done in a OnceLock, which is initialized only when the function is called, and only once during.
---
### `region`
The Wii's system software comes in 4 variants:
- **U**nited States
- **E**urope
- **J**apan
- **K**orea
The first letter (bolded) is affixed to the version, as in *4.3U*.
When generating a LetterBomb, the region determines *which* payload template to use.
The enum `Region` holds these 4 variants.
Can use `FromStr` to create from strings like `"U" "E" "J" "K"`.
`Display` is region's character; `Region::U.to_string() == "U"`.
---
### `bundle`
The "bundle" is the HackMii installer.
**Because of licensing restrictions, letterbomb cannot re-package or re-distribute this bundle.
There is no way to avoid this restriction.**
Therefore, it will download the installer and extract it, on-the-fly, without saving it.
The whole contents of the installer ZIP are used and placed in the output directory.
You cannot re-distribute the HackMii installer, even once saved to the output directory.
It is for your use only.
The bundle is loaded via `bundle::bundle()` and in the same manner as `oui::oui_list()`.
---
### `main`
CLI front-end. Uses [Clap](https://crates.io/crates/clap).
Pass arguments in order of `mac region outputdir`.
Prints summary of how many bytes were written, and where to.
Any errors are lifted into an `anyhow::Result`.