update
This commit is contained in:
parent
3a11402914
commit
f31608749c
|
@ -0,0 +1,7 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "sepatch"
|
||||
version = "0.1.0"
|
219
src/main.rs
219
src/main.rs
|
@ -1,4 +1,4 @@
|
|||
use std::{fs, io::{self, BufRead, BufReader, Write}, fmt::format};
|
||||
use std::{fs, io::{self, BufRead, BufReader, Write}};
|
||||
|
||||
fn main() {
|
||||
let args : Vec<String> = std::env::args().collect();
|
||||
|
@ -13,6 +13,10 @@ fn main() {
|
|||
return;
|
||||
}
|
||||
};
|
||||
if let Err(e) = verify_code(&codes) {
|
||||
println!("verify code error: {}", e.to_string());
|
||||
return;
|
||||
}
|
||||
if let Err(e) = apply_code(args[1].as_str(), &codes) {
|
||||
println!("apply code error: {}", e.to_string());
|
||||
}
|
||||
|
@ -22,7 +26,7 @@ fn read_codes(code_file : &str) -> io::Result<Vec<(u32, u32)>> {
|
|||
let file = fs::File::open(code_file).expect("cannot open patch_code");
|
||||
let reader = BufReader::new(file);
|
||||
let mut codes = Vec::new();
|
||||
let mut lines = 0u32;
|
||||
let mut lines = 1u32;
|
||||
for line in reader.lines() {
|
||||
if let Ok(l) = line {
|
||||
let r_str = l.as_str();
|
||||
|
@ -35,31 +39,218 @@ fn read_codes(code_file : &str) -> io::Result<Vec<(u32, u32)>> {
|
|||
codes.push((lines, val2.unwrap()));
|
||||
}
|
||||
} // else skip
|
||||
lines += 1;
|
||||
}
|
||||
}
|
||||
Ok(codes)
|
||||
}
|
||||
|
||||
fn verify_code(codes : Vec<(u32, u32)>) -> Result<(), String> {
|
||||
let pos = 0usize;
|
||||
while pos < codes.len() {
|
||||
fn verify_code(codes : &Vec<(u32, u32)>) -> Result<(), String> {
|
||||
let mut pos = 0usize;
|
||||
let max_len = codes.len();
|
||||
let mut search_code = false;
|
||||
while pos < max_len {
|
||||
let line = codes[pos].0;
|
||||
let first_code = codes[pos].1;
|
||||
let op_code = first_code >> 28;
|
||||
let mut search_code = false;
|
||||
let op_code = (first_code >> 28) as u8;
|
||||
match op_code {
|
||||
0x0 | 0x1 |0x2 => {
|
||||
return Err(format!("{}", 123));
|
||||
if search_code {
|
||||
if first_code & 0xf000000 != 0x8000000 {
|
||||
return Err(format!("wrong code at line {}: need search code after search", line));
|
||||
}
|
||||
search_code = false
|
||||
}
|
||||
if pos + 2 > max_len {
|
||||
return Err(format!("wrong code at line {}: unexpected end", line));
|
||||
}
|
||||
pos += 2;
|
||||
}
|
||||
0x4 => {
|
||||
if search_code {
|
||||
if first_code & 0xf000000 != 0x8000000 {
|
||||
return Err(format!("wrong code at line {}: need search code after search", line));
|
||||
}
|
||||
search_code = false
|
||||
}
|
||||
if pos + 4 > max_len {
|
||||
return Err(format!("wrong code at line {}: unexpected end", line));
|
||||
}
|
||||
pos += 4;
|
||||
}
|
||||
0x5 => {
|
||||
if search_code {
|
||||
return Err(format!("wrong code at line {}: need search code after search", line));
|
||||
}
|
||||
if pos + 4 > max_len {
|
||||
return Err(format!("wrong code at line {}: unexpected end", line));
|
||||
}
|
||||
pos += 4;
|
||||
}
|
||||
0x8 => {
|
||||
if search_code {
|
||||
return Err(format!("wrong code at line {}: need search code after search", line));
|
||||
}
|
||||
let search_bytes = (first_code & 0xffff) as usize;
|
||||
if search_bytes == 0 {
|
||||
return Err(format!("wrong code at line {}: search length should not be 0", line));
|
||||
}
|
||||
let code_len = ((search_bytes - 1) / 4 + 1) * 2;
|
||||
if pos + code_len > max_len {
|
||||
return Err(format!("wrong code at line {}: unexpected end", line));
|
||||
}
|
||||
search_code = true;
|
||||
pos += code_len;
|
||||
}
|
||||
0xa => {
|
||||
if search_code {
|
||||
return Err(format!("wrong code at line {}: need search code after search", line));
|
||||
}
|
||||
if pos + 1 >= max_len {
|
||||
return Err(format!("wrong code at line {}: unexpected end", line));
|
||||
}
|
||||
let write_bytes = codes[pos + 1].1 as usize;
|
||||
if write_bytes == 0 {
|
||||
return Err(format!("wrong code at line {}: write length should not be 0", line));
|
||||
}
|
||||
if write_bytes > 320 {
|
||||
return Err(format!("wrong code at line {}: write length should not exceed 320", line));
|
||||
}
|
||||
let code_len = ((write_bytes - 1) / 8 + 1) * 2 + 2;
|
||||
if pos + code_len > max_len {
|
||||
return Err(format!("wrong code at line {}: unexpected end", line));
|
||||
}
|
||||
pos += code_len;
|
||||
}
|
||||
_ => {
|
||||
return Err(format!("unknown code at line {}", line));
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
pos += 1;
|
||||
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn apply_code(patch_file : &str, codes : &Vec<(u32, u32)>) -> io::Result<()> {
|
||||
let data = fs::read(patch_file)?;
|
||||
let mut write_file = fs::OpenOptions::new().write(true).truncate(true).open(patch_file)?;
|
||||
write_file.write(data.as_slice())?;
|
||||
fn apply_code(patch_file : &str, codes : &Vec<(u32, u32)>) -> Result<(), String> {
|
||||
let fn_map_err = |e : io::Error| format!("apply code error: {}", e.to_string());
|
||||
let mut data = fs::read(patch_file).map_err(fn_map_err)?;
|
||||
let mut pos = 0usize;
|
||||
let max_code_len = codes.len();
|
||||
let max_data_len = data.len();
|
||||
let mut search_addr : Option<u32> = None;
|
||||
while pos < max_code_len {
|
||||
let line = codes[pos].0;
|
||||
let first_code = codes[pos].1;
|
||||
let op_code = (first_code >> 28) as u8;
|
||||
match op_code {
|
||||
0x0 => {
|
||||
let val = codes[pos + 1].1 as u8;
|
||||
let addr = if let Some(saddr) = search_addr {
|
||||
search_addr = None;
|
||||
(codes[pos].1 & 0xffffff) + saddr
|
||||
} else {
|
||||
codes[pos].1 & 0xfffffff
|
||||
} as usize;
|
||||
if addr >= max_data_len {
|
||||
return Err(format!("apply code error at line {}: address overflow", line));
|
||||
}
|
||||
data[addr] = val;
|
||||
pos += 2;
|
||||
}
|
||||
0x1 => {
|
||||
let val = codes[pos + 1].1 as u16;
|
||||
let addr = if let Some(saddr) = search_addr {
|
||||
search_addr = None;
|
||||
(codes[pos].1 & 0xffffff) + saddr
|
||||
} else {
|
||||
codes[pos].1 & 0xfffffff
|
||||
} as usize;
|
||||
if addr + 1 >= max_data_len {
|
||||
return Err(format!("apply code error at line {}: address overflow", line));
|
||||
}
|
||||
data[addr] = (val & 0xff) as u8;
|
||||
data[addr + 1] = ((val >> 8) & 0xff) as u8;
|
||||
pos += 2;
|
||||
}
|
||||
0x2 => {
|
||||
let val = codes[pos + 1].1;
|
||||
let addr = if let Some(saddr) = search_addr {
|
||||
search_addr = None;
|
||||
(codes[pos].1 & 0xffffff) + saddr
|
||||
} else {
|
||||
codes[pos].1 & 0xfffffff
|
||||
} as usize;
|
||||
if addr + 3 >= max_data_len {
|
||||
return Err(format!("apply code error at line {}: address overflow", line));
|
||||
}
|
||||
data[addr] = (val & 0xff) as u8;
|
||||
data[addr + 1] = ((val >> 8) & 0xff) as u8;
|
||||
data[addr + 2] = ((val >> 16) & 0xff) as u8;
|
||||
data[addr + 3] = ((val >> 24) & 0xff) as u8;
|
||||
pos += 2;
|
||||
}
|
||||
0x4 => {
|
||||
let mut val = codes[pos + 1].1;
|
||||
let mut addr = if let Some(saddr) = search_addr {
|
||||
search_addr = None;
|
||||
(codes[pos].1 & 0xffffff) + saddr
|
||||
} else {
|
||||
codes[pos].1 & 0xfffffff
|
||||
} as usize;
|
||||
let mut count = (codes[pos + 2].1 & 0xfff0000) >> 16;
|
||||
let addr_diff = codes[pos + 2].1 & 0xffff;
|
||||
let val_diff = codes[pos + 3].1;
|
||||
while count != 0 {
|
||||
if codes[pos].1 & 0xf000000 == 0x1000000 {
|
||||
if addr >= max_data_len {
|
||||
return Err(format!("apply code error at line {}: address overflow", line));
|
||||
}
|
||||
data[addr] = (val & 0xff) as u8;
|
||||
} else if codes[pos].1 & 0xf000000 == 0x2000000 {
|
||||
if addr + 1 >= max_data_len {
|
||||
return Err(format!("apply code error at line {}: address overflow", line));
|
||||
}
|
||||
data[addr] = (val & 0xff) as u8;
|
||||
data[addr + 1] = ((val >> 8) & 0xff) as u8;
|
||||
} else {
|
||||
if addr + 3 >= max_data_len {
|
||||
return Err(format!("apply code error at line {}: address overflow", line));
|
||||
}
|
||||
data[addr] = (val & 0xff) as u8;
|
||||
data[addr + 1] = ((val >> 8) & 0xff) as u8;
|
||||
data[addr + 2] = ((val >> 16) & 0xff) as u8;
|
||||
data[addr + 3] = ((val >> 24) & 0xff) as u8;
|
||||
}
|
||||
count -= 1;
|
||||
addr += addr_diff as usize;
|
||||
val += val_diff;
|
||||
}
|
||||
pos += 4;
|
||||
}
|
||||
0x5 | 0x8 => {
|
||||
return Err(format!("apply code error at line {}: not supported", line));
|
||||
}
|
||||
0xa => {
|
||||
let mut addr = (codes[pos].1 & 0xfffffff) as usize;
|
||||
let write_bytes = codes[pos + 1].1 as usize;
|
||||
if addr + write_bytes>= max_data_len {
|
||||
return Err(format!("apply code error at line {}: address overflow", line));
|
||||
}
|
||||
let mut bytes = 0;
|
||||
while bytes < write_bytes {
|
||||
let offset = pos + 2 + (bytes / 4);
|
||||
let shift = (3 - (bytes % 4)) * 8;
|
||||
data[addr] = ((codes[offset].1 >> shift) & 0xff) as u8;
|
||||
bytes += 1;
|
||||
addr += 1;
|
||||
}
|
||||
let code_len = ((write_bytes - 1) / 8 + 1) * 2 + 2;
|
||||
pos += code_len;
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
let mut write_file = fs::OpenOptions::new().write(true).truncate(true).open(patch_file).map_err(fn_map_err)?;
|
||||
write_file.write(data.as_slice()).map_err(fn_map_err)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue