Skip to content

Commit

Permalink
fixed wii
Browse files Browse the repository at this point in the history
  • Loading branch information
kipcode66 committed Jul 29, 2024
1 parent f20627d commit 8d4dfb0
Show file tree
Hide file tree
Showing 10 changed files with 441 additions and 148 deletions.
44 changes: 24 additions & 20 deletions geckolib/src/iso/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crate::vfs::{self, Directory, GeckoFS};
use crate::UPDATER;
use crate::{framework_map, linker, warn};

use super::disc::{DiscType, WiiDisc};
use super::{disc::DiscType, read::DiscReader};

mod fs_source;

Expand All @@ -42,7 +42,7 @@ pub struct IsoBuilder<R1, R2, W> {
config: Config,
fs: FSSource<R1>,
gfs: GeckoFS<R2>,
disc_info: Option<WiiDisc>,
reader: DiscReader<R2>,
writer: W,
}

Expand All @@ -51,25 +51,25 @@ impl<RConfig, RDisc, W> IsoBuilder<RConfig, RDisc, W> {
config: Config,
zip: ZipArchive<RConfig>,
gfs: GeckoFS<RDisc>,
disc_info: Option<WiiDisc>,
reader: DiscReader<RDisc>,
writer: W,
) -> Self {
Self::internal_new(config, FSSource::Zip(Box::new(zip)), gfs, disc_info, writer)
Self::internal_new(config, FSSource::Zip(Box::new(zip)), gfs, reader, writer)
}

#[cfg(not(target_os = "unknown"))]
pub fn new_with_fs<P: AsRef<Path>>(
config: Config,
path: P,
gfs: GeckoFS<RDisc>,
disc_info: Option<WiiDisc>,
reader: DiscReader<RDisc>,
writer: W,
) -> Self {
Self::internal_new(
config,
FSSource::FS(path.as_ref().to_path_buf()),
gfs,
disc_info,
reader,
writer,
)
}
Expand All @@ -78,14 +78,14 @@ impl<RConfig, RDisc, W> IsoBuilder<RConfig, RDisc, W> {
config: Config,
fs: FSSource<RConfig>,
gfs: GeckoFS<RDisc>,
disc_info: Option<WiiDisc>,
reader: DiscReader<RDisc>,
writer: W,
) -> Self {
Self {
config,
fs,
gfs,
disc_info,
reader,
writer,
}
}
Expand Down Expand Up @@ -185,7 +185,6 @@ where
updater.set_message("Loading game...".into())?;
}

let wii_disc_info = self.disc_info.clone();
let disc = &mut self.gfs;

#[cfg(feature = "progress")]
Expand Down Expand Up @@ -318,7 +317,7 @@ where
)?;
}

if wii_disc_info.is_none() {
if self.reader.get_type() == DiscType::Gamecube {
#[cfg(feature = "progress")]
if let Ok(mut updater) = UPDATER.lock() {
updater.set_message("".into())?;
Expand Down Expand Up @@ -372,17 +371,16 @@ where

// Finalize disc and write it back into a file

let out: DiscWriter<W> = { DiscWriter::new(self.writer.clone(), wii_disc_info) };
if let DiscWriter::Wii(wii_out) = out.clone() {
std::pin::pin!(wii_out).init().await?;
}
let out: DiscWriter<W> = DiscWriter::from_reader(self.writer.clone(), &self.reader);
std::pin::pin!(out.clone()).init().await?;
// let out = DiscWriter::Gamecube(self.writer.clone());

let mut out = std::pin::pin!(out);
let is_wii = out.get_type() == DiscType::Wii;
disc.serialize(&mut out, is_wii).await?;
disc.serialize(&mut out).await?;

#[cfg(feature = "progress")]
if let Ok(mut updater) = UPDATER.lock() {
updater.set_title("Finished".into())?;
updater.finish()?;
}

Expand Down Expand Up @@ -482,8 +480,8 @@ impl Builder for PatchBuilder {

#[cfg(feature = "progress")]
if let Ok(mut updater) = UPDATER.lock() {
updater.set_title("Storing replacement files...".into())?;
updater.set_message("".into())?;
updater.set_title("Storing replacement files...".into())?;
}

let mut new_map = HashMap::new();
Expand All @@ -497,8 +495,8 @@ impl Builder for PatchBuilder {

#[cfg(feature = "progress")]
if let Ok(mut updater) = UPDATER.lock() {
updater.set_title("Storing libraries...".into())?;
updater.set_message("".into())?;
updater.set_title("Storing libraries...".into())?;
}

if let Some(link) = &mut config.link {
Expand Down Expand Up @@ -543,8 +541,8 @@ impl Builder for PatchBuilder {

#[cfg(feature = "progress")]
if let Ok(mut updater) = UPDATER.lock() {
updater.set_title("Storing banner...".into())?;
updater.set_message("".into())?;
updater.set_title("Storing banner...".into())?;
}

write_file_to_zip(&mut zip, "banner.dat", &read(path).await?)?;
Expand All @@ -554,8 +552,8 @@ impl Builder for PatchBuilder {

#[cfg(feature = "progress")]
if let Ok(mut updater) = UPDATER.lock() {
updater.set_title("Storing patch index...".into())?;
updater.set_message("".into())?;
updater.set_title("Storing patch index...".into())?;
}

config.src.iso = PathBuf::new();
Expand All @@ -568,6 +566,12 @@ impl Builder for PatchBuilder {

zip.finish()?;

#[cfg(feature = "progress")]
if let Ok(mut updater) = UPDATER.lock() {
updater.set_title("Finished".into())?;
updater.finish()?;
}

Ok(())
}
}
96 changes: 75 additions & 21 deletions geckolib/src/iso/disc.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use std::error::Error;
use std::io::SeekFrom;
use std::mem::offset_of;
use std::pin::Pin;

use async_std::io::prelude::SeekExt;
use async_std::io::ReadExt;
use eyre::Result;
use num::Unsigned;

use crate::crypto::aes_decrypt_inplace;
Expand All @@ -17,6 +18,37 @@ use byteorder::{ByteOrder, BE};
use sha1_smol::Sha1;
use std::convert::TryFrom;

#[derive(Debug)]
pub enum DiscError {
NoGamePartition,
EncryptionError(WiiCryptoError),
Io(std::io::Error),
}

impl Error for DiscError {}

impl std::fmt::Display for DiscError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
DiscError::NoGamePartition => write!(f, "There is no game parition in this disc"),
DiscError::EncryptionError(e) => write!(f, "Encryption error: {}", e),
DiscError::Io(e) => write!(f, "IO error: {}", e),
}
}
}

impl From<WiiCryptoError> for DiscError {
fn from(e: WiiCryptoError) -> Self {
DiscError::EncryptionError(e)
}
}

impl From<std::io::Error> for DiscError {
fn from(e: std::io::Error) -> Self {
DiscError::Io(e)
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum DiscType {
Gamecube = 0,
Expand All @@ -37,8 +69,8 @@ pub struct WiiDiscHeader {
pub wii_magic: u32,
pub gc_magic: u32,
pub game_title: [u8; 64],
pub disable_hash_verif: u8,
pub disable_disc_encrypt: u8,
pub disable_hash_verif: bool,
pub disable_disc_encrypt: bool,
pub padding: [u8; 0x39e],
}

Expand Down Expand Up @@ -88,8 +120,8 @@ pub fn disc_get_header(raw: &[u8]) -> WiiDiscHeader {
wii_magic: BE::read_u32(&raw[0x18..0x1C]),
gc_magic: BE::read_u32(&raw[0x1C..0x20]),
game_title,
disable_hash_verif: raw[0x60],
disable_disc_encrypt: raw[0x61],
disable_hash_verif: raw[0x60] != 0,
disable_disc_encrypt: raw[0x61] != 0,
padding,
}
}
Expand All @@ -109,8 +141,8 @@ pub fn disc_set_header(buffer: &mut [u8], dh: &WiiDiscHeader) {
BE::write_u32(&mut buffer[0x18..], dh.wii_magic);
BE::write_u32(&mut buffer[0x1C..], dh.gc_magic);
buffer[0x20..0x60].copy_from_slice(&dh.game_title[..]);
buffer[0x60] = dh.disable_hash_verif;
buffer[0x61] = dh.disable_disc_encrypt;
buffer[0x60] = dh.disable_hash_verif as u8;
buffer[0x61] = dh.disable_disc_encrypt as u8;
buffer[0x62..0x400].copy_from_slice(&dh.padding);
}

Expand All @@ -128,9 +160,30 @@ pub struct WiiDiscRegionAgeRating {
kr: u8,
}

#[derive(Debug, Clone, Copy, Default)]
pub enum WiiDiscRegions {
#[default]
NTSCJ,
NTSCU,
PAL,
KOR,
}

impl From<u32> for WiiDiscRegions {
fn from(r: u32) -> Self {
match r {
0 => WiiDiscRegions::NTSCJ,
1 => WiiDiscRegions::NTSCU,
2 => WiiDiscRegions::PAL,
3 => WiiDiscRegions::KOR,
_ => WiiDiscRegions::default(),
}
}
}

#[derive(Debug, Clone, Copy, Default)]
pub struct WiiDiscRegion {
pub region: u32,
pub region: WiiDiscRegions,
pub age_rating: WiiDiscRegionAgeRating,
}

Expand All @@ -141,7 +194,7 @@ impl Unpackable for WiiDiscRegion {
impl WiiDiscRegion {
pub fn parse(raw: &[u8]) -> Self {
Self {
region: BE::read_u32(&raw[..4]),
region: BE::read_u32(&raw[..4]).into(),
age_rating: WiiDiscRegionAgeRating {
jp: raw[0x10],
us: raw[0x11],
Expand All @@ -158,7 +211,7 @@ impl WiiDiscRegion {
}

pub fn compose_into(&self, buf: &mut [u8]) {
BE::write_u32(&mut buf[..4], self.region);
buf[..4].copy_from_slice((self.region as u32).to_be_bytes().as_ref());
buf[0x10] = self.age_rating.jp;
buf[0x11] = self.age_rating.us;
buf[0x12] = self.age_rating.unknown1;
Expand Down Expand Up @@ -186,7 +239,7 @@ pub struct PartInfo {

pub async fn disc_get_part_info_async<R: AsyncRead + AsyncSeek>(
reader: &mut Pin<&mut R>,
) -> Result<PartInfo> {
) -> Result<PartInfo, DiscError> {
crate::debug!("Parsing partition info (async)");
let mut entries: Vec<PartInfoEntry> = Vec::new();
let mut buf: [u8; 8] = [0u8; 8];
Expand Down Expand Up @@ -294,7 +347,7 @@ pub struct Ticket {
pub time_limit: u32,
pub fake_sign: [u8; 0x58],
}
assert_eq_size!(Ticket, [u8; Ticket::BLOCK_SIZE]);
assert_eq_size!(Ticket, [u8; <Ticket as Unpackable>::BLOCK_SIZE]);
declare_tryfrom!(Ticket);

impl Unpackable for Ticket {
Expand All @@ -303,18 +356,18 @@ impl Unpackable for Ticket {

impl Ticket {
pub fn fake_sign(&mut self) -> Result<(), eyre::Report> {
let mut tik_buf = [0u8; Ticket::BLOCK_SIZE];
let mut tik_buf = [0u8; <Ticket as Unpackable>::BLOCK_SIZE];
self.sig.sig.fill(0);
self.sig.sig_padding.fill(0);
self.fake_sign.fill(0);
tik_buf[..Ticket::BLOCK_SIZE].copy_from_slice(&<[u8; Ticket::BLOCK_SIZE]>::from(&*self));
tik_buf[..<Ticket as Unpackable>::BLOCK_SIZE].copy_from_slice(&<[u8; <Ticket as Unpackable>::BLOCK_SIZE]>::from(&*self));
// start brute force
crate::trace!("Ticket fake signing; starting brute force...");
let mut val = 0u32;
let mut hash_0;
let mut sha1 = Sha1::new();
loop {
BE::write_u32(&mut tik_buf[0x248..][..4], val);
BE::write_u32(&mut tik_buf[offset_of!(Self, time_limit)/* 0x248 */..][..size_of_val(&self.time_limit)], val);
sha1.reset();
sha1.update(&tik_buf[0x140..]);
hash_0 = sha1.digest().bytes()[0];
Expand All @@ -338,8 +391,8 @@ impl Ticket {
}
}

impl From<&[u8; Ticket::BLOCK_SIZE]> for Ticket {
fn from(buf: &[u8; Ticket::BLOCK_SIZE]) -> Self {
impl From<&[u8; <Ticket as Unpackable>::BLOCK_SIZE]> for Ticket {
fn from(buf: &[u8; <Ticket as Unpackable>::BLOCK_SIZE]) -> Self {
let mut sig = [0_u8; 0x100];
let mut sig_padding = [0_u8; 0x3C];
let mut sig_issuer = [0_u8; 0x40];
Expand Down Expand Up @@ -389,9 +442,9 @@ impl From<&[u8; Ticket::BLOCK_SIZE]> for Ticket {
}
}

impl From<&Ticket> for [u8; Ticket::BLOCK_SIZE] {
impl From<&Ticket> for [u8; <Ticket as Unpackable>::BLOCK_SIZE] {
fn from(t: &Ticket) -> Self {
let mut buf = [0_u8; Ticket::BLOCK_SIZE];
let mut buf = [0_u8; <Ticket as Unpackable>::BLOCK_SIZE];

BE::write_u32(&mut buf[0x00..], t.sig.sig_type);
buf[0x04..0x104].copy_from_slice(&t.sig.sig[..]);
Expand Down Expand Up @@ -421,11 +474,12 @@ impl From<&Ticket> for [u8; Ticket::BLOCK_SIZE] {

impl Default for Ticket {
fn default() -> Self {
Ticket::from(&[0_u8; Ticket::BLOCK_SIZE])
Ticket::from(&[0_u8; <Ticket as Unpackable>::BLOCK_SIZE])
}
}

#[derive(Debug, Clone, Copy, Default)]
#[repr(C)]
pub struct PartHeader {
pub ticket: Ticket,
pub tmd_size: usize,
Expand Down Expand Up @@ -460,7 +514,7 @@ impl From<&[u8; PartHeader::BLOCK_SIZE]> for PartHeader {
impl From<&PartHeader> for [u8; PartHeader::BLOCK_SIZE] {
fn from(ph: &PartHeader) -> Self {
let mut buf = [0_u8; PartHeader::BLOCK_SIZE];
buf[..0x2A4].copy_from_slice(&<[u8; Ticket::BLOCK_SIZE]>::from(&ph.ticket));
buf[..0x2A4].copy_from_slice(&<[u8; <Ticket as Unpackable>::BLOCK_SIZE]>::from(&ph.ticket));
BE::write_u32(&mut buf[0x2A4..], ph.tmd_size as u32);
BE::write_u32(&mut buf[0x2A8..], (ph.tmd_offset >> 2) as u32);
BE::write_u32(&mut buf[0x2AC..], ph.cert_size as u32);
Expand Down
Loading

0 comments on commit 8d4dfb0

Please sign in to comment.