use std::io::Read; unsafe extern "C" { fn newbuf() -> *mut std::ffi::c_void; fn resetbuf(s: *mut std::ffi::c_void); fn DisasmPPC(address: u32, code: u32, s: *mut std::ffi::c_void) -> bool; fn buf2str(s: *mut std::ffi::c_void, data: *mut *const u8) -> usize; } struct StringBuf { buf: *mut std::ffi::c_void, } impl StringBuf { fn new() -> Self { Self { buf: unsafe { newbuf() }, } } fn reset(&mut self) { unsafe { resetbuf(self.buf) } } fn as_str(&self) -> &str { let mut bs: *const u8 = std::ptr::null(); let len = unsafe { buf2str(self.buf, &mut bs) }; assert!(!bs.is_null()); let slc = unsafe { std::slice::from_raw_parts(bs, len) }; let s = unsafe { std::str::from_utf8_unchecked(slc) }; s } } fn xenia_dis(address: u32, code: u32, buf: &mut StringBuf) -> bool { unsafe { DisasmPPC(address, code, buf.buf) } } pub fn main() { let mut args = std::env::args(); args.next().expect("exists"); let hex0 = args.next().expect("byte 0"); if hex0.trim() == "-" { dis_stdin(); return; } let hex1 = args.next().expect("byte 1"); let hex2 = args.next().expect("byte 2"); let hex3 = args.next().expect("byte 3"); let bs: [u8; 4] = [ u8::from_str_radix(&hex0, 16).expect("byte 0 parses"), u8::from_str_radix(&hex1, 16).expect("byte 1 parses"), u8::from_str_radix(&hex2, 16).expect("byte 2 parses"), u8::from_str_radix(&hex3, 16).expect("byte 3 parses"), ]; dis_bytes(bs); } fn dis_stdin() { let mut buf = Vec::new(); std::io::stdin().read_to_end(&mut buf).expect("can read"); for i in 0..buf.len() / 4 { let bs: [u8; 4] = buf[i * 4..][..4].try_into().expect("four bytes"); dis_bytes(u32::from_le_bytes(bs).to_be_bytes()); } } fn dis_bytes(bs: [u8; 4]) { let word = u32::from_be_bytes(bs); let mut buf = StringBuf::new(); let ok = xenia_dis(0x00000004, word, &mut buf); if ok { println!("{}", buf.as_str()); } else { println!(".long 0x{:08x}", word); } }