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() {
|
fn main() {
|
||||||
let args : Vec<String> = std::env::args().collect();
|
let args : Vec<String> = std::env::args().collect();
|
||||||
|
@ -13,6 +13,10 @@ fn main() {
|
||||||
return;
|
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) {
|
if let Err(e) = apply_code(args[1].as_str(), &codes) {
|
||||||
println!("apply code error: {}", e.to_string());
|
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 file = fs::File::open(code_file).expect("cannot open patch_code");
|
||||||
let reader = BufReader::new(file);
|
let reader = BufReader::new(file);
|
||||||
let mut codes = Vec::new();
|
let mut codes = Vec::new();
|
||||||
let mut lines = 0u32;
|
let mut lines = 1u32;
|
||||||
for line in reader.lines() {
|
for line in reader.lines() {
|
||||||
if let Ok(l) = line {
|
if let Ok(l) = line {
|
||||||
let r_str = l.as_str();
|
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()));
|
codes.push((lines, val2.unwrap()));
|
||||||
}
|
}
|
||||||
} // else skip
|
} // else skip
|
||||||
|
lines += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(codes)
|
Ok(codes)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify_code(codes : Vec<(u32, u32)>) -> Result<(), String> {
|
fn verify_code(codes : &Vec<(u32, u32)>) -> Result<(), String> {
|
||||||
let pos = 0usize;
|
let mut pos = 0usize;
|
||||||
while pos < codes.len() {
|
let max_len = codes.len();
|
||||||
let first_code = codes[pos].1;
|
|
||||||
let op_code = first_code >> 28;
|
|
||||||
let mut search_code = false;
|
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) as u8;
|
||||||
match op_code {
|
match op_code {
|
||||||
0x0 | 0x1 |0x2 => {
|
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
|
||||||
}
|
}
|
||||||
pos += 1;
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_code(patch_file : &str, codes : &Vec<(u32, u32)>) -> io::Result<()> {
|
fn apply_code(patch_file : &str, codes : &Vec<(u32, u32)>) -> Result<(), String> {
|
||||||
let data = fs::read(patch_file)?;
|
let fn_map_err = |e : io::Error| format!("apply code error: {}", e.to_string());
|
||||||
let mut write_file = fs::OpenOptions::new().write(true).truncate(true).open(patch_file)?;
|
let mut data = fs::read(patch_file).map_err(fn_map_err)?;
|
||||||
write_file.write(data.as_slice())?;
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue