Skip to content

Commit

Permalink
Merge pull request #1 from imaandrew/wii
Browse files Browse the repository at this point in the history
  • Loading branch information
imaandrew authored Jul 2, 2023
2 parents db474f1 + 6ed2909 commit 4cce529
Show file tree
Hide file tree
Showing 9 changed files with 1,699 additions and 84 deletions.
8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,12 @@ crate-type = ["cdylib", "rlib"]

[dependencies]
adler32 = "1.2.0"
aes = "0.8.3"
cbc = { version = "0.1.2", features = ["alloc"] }
console_error_panic_hook = "0.1.7"
hex = "0.4.3"
serde = { version = "1.0.164", features = ["derive"] }
serde-wasm-bindgen = "0.5.0"
sha-1 = "0.10.1"
thiserror = "1.0.40"
wasm-bindgen = "0.2.87"
67 changes: 53 additions & 14 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,63 @@
use serde::{Deserialize, Serialize};
use std::panic;
use wasm_bindgen::prelude::*;
use wii::{
romc::Romc,
u8::{U8Error, U8Packer, U8Unpacker},
wad::{Encoder, Parser, WadError},
};
extern crate console_error_panic_hook;

impl From<U8Error> for String {
fn from(value: U8Error) -> Self {
format!("u8 error: {}", value)
}
}

impl From<WadError> for String {
fn from(value: WadError) -> Self {
format!("wad packer/unpacker error: {}", value)
}
}

pub mod n64;
pub mod wii;

#[wasm_bindgen]
pub fn n64_decode(rom: Vec<u8>, patch: Vec<u8>) -> Result<Vec<u8>, String> {
let mut x = n64::decode::VCDiffDecoder::new(patch, rom);
Ok(x.decode().map(|v| v.to_vec())?)
pub fn n64_decode(rom: Vec<u8>, patch: &[u8]) -> Result<Vec<u8>, String> {
let mut x = n64::decode::VCDiffDecoder::new(patch, &rom);
x.decode().map_err(|e| format!("n64 error: {}", e))
}

#[cfg(test)]
mod tests {
// Note this useful idiom: importing names from outer (for mod tests) scope.
use super::*;
#[derive(Serialize, Deserialize)]
pub struct WiiInjectSettings {
pub wad: Vec<u8>,
pub xdelta_patch: Vec<u8>,
pub gzi_patch: Vec<u8>,
pub channel_id: String,
pub title: String,
}

#[test]
fn test_n64_decode() {
let rom = std::fs::read("tests/rom.z64").unwrap();
let patch = std::fs::read("tests/patch.xdelta").unwrap();
let out = std::fs::read("tests/out.z64").unwrap();
#[wasm_bindgen]
pub fn wii_inject(s: JsValue) -> Result<Vec<u8>, String> {
panic::set_hook(Box::new(console_error_panic_hook::hook));
let s: WiiInjectSettings = serde_wasm_bindgen::from_value(s).map_err(|_| "Invalid settings")?;
let mut wad_parser = Parser::new(&s.wad);
let mut wad = wad_parser.decode()?;
let mut u8_unpack = U8Unpacker::new(&wad.contents[5]);
let mut content5 = u8_unpack.unpack()?;
let rom = content5.find_entry("./romc")?;
let mut romc_decode = Romc::new();
let decoded_rom = romc_decode.decode(rom.get_file_contents()?);
let patched_rom = n64_decode(decoded_rom, &s.xdelta_patch)?;
let mut romc_encode = Romc::new();
let encoded_rom = romc_encode.encode(&patched_rom);
rom.set_file_contents(encoded_rom)?;
let mut u8_pack = U8Packer::new();
let content5 = u8_pack.pack(content5);
wad.contents[5] = content5;
wad.parse_gzi_patch(&s.gzi_patch)?;

assert_eq!(n64_decode(rom, patch).unwrap(), out);
}
let mut wad_encoder = Encoder::new(&mut wad);
Ok(wad_encoder.encode()?)
}
27 changes: 20 additions & 7 deletions src/n64/cache.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{read_byte, read_int};
use super::{read_byte, read_int, VCDiffDecoderError};

pub struct AddrCache {
near: Vec<u32>,
Expand Down Expand Up @@ -28,19 +28,32 @@ impl AddrCache {
self.same[addr as usize % cap] = addr;
}

pub fn addr_decode(&mut self, here: u32, mode: u32, index: &mut usize, addr: &[u8]) -> u32 {
pub fn addr_decode(
&mut self,
here: u32,
mode: u32,
index: &mut usize,
addr: &[u8],
) -> Result<u32, VCDiffDecoderError> {
let addr = if mode == 0 {
read_int(addr, index)
read_int(addr, index)?
} else if mode == 1 {
here - read_int(addr, index)
here - read_int(addr, index)?
} else if mode >= 2 && mode as usize - 2 < self.near.capacity() {
self.near[(mode - 2) as usize] + read_int(addr, index)
self.near[(mode - 2) as usize] + read_int(addr, index)?
} else {
let m = mode as usize - 2 - self.near.capacity();
self.same[m * 256 + read_byte(addr, index) as usize]
self.same
.get(m * 256 + read_byte(addr, index)? as usize)
.ok_or(VCDiffDecoderError::IndexOutOfBounds(
1,
*index - 1,
self.same.len(),
))
.copied()?
};

self.cache_update(addr);
addr
Ok(addr)
}
}
Loading

0 comments on commit 4cce529

Please sign in to comment.