diff --git a/src/main.rs b/src/main.rs index 03a89e4..d603601 100644 --- a/src/main.rs +++ b/src/main.rs @@ -95,7 +95,8 @@ fn verify_code(codes : &Vec<(u32, u32)>) -> Result<(), String> { 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; + let mut code_len = (search_bytes - 1) / 4 + 2; + code_len += code_len % 2; if pos + code_len > max_len { return Err(format!("wrong code at line {}: unexpected end", line)); } @@ -137,7 +138,7 @@ fn apply_code(patch_file : &str, codes : &Vec<(u32, u32)>) -> Result<(), String> let mut pos = 0usize; let max_code_len = codes.len(); let max_data_len = data.len(); - let mut search_addr : Option<(bool, u32)> = None; + let mut search_addr : Option = None; let mut code_len = 0; loop { pos += code_len; @@ -151,14 +152,14 @@ fn apply_code(patch_file : &str, codes : &Vec<(u32, u32)>) -> Result<(), String> 0x0 => { code_len = 2; let val = codes[pos + 1].1 as u8; - let addr = if let Some(saddr) = search_addr.take() { - if saddr.0 == false { + let addr = if (first_code & 0xf000000) == 0x8000000 { + if search_addr == None { continue; } - (codes[pos].1 & 0xffffff) + saddr.1 + (first_code & 0xffffff) as usize + search_addr.unwrap() } else { - codes[pos].1 & 0xfffffff - } as usize; + (first_code & 0xfffffff) as usize + }; if addr >= max_data_len { return Err(format!("apply code error at line {}: address overflow", line)); } @@ -167,14 +168,14 @@ fn apply_code(patch_file : &str, codes : &Vec<(u32, u32)>) -> Result<(), String> 0x1 => { code_len = 2; let val = codes[pos + 1].1 as u16; - let addr = if let Some(saddr) = search_addr.take() { - if saddr.0 == false { + let addr = if (first_code & 0xf000000) == 0x8000000 { + if search_addr == None { continue; } - (codes[pos].1 & 0xffffff) + saddr.1 + (first_code & 0xffffff) as usize + search_addr.unwrap() } else { - codes[pos].1 & 0xfffffff - } as usize; + (first_code & 0xfffffff) as usize + }; if addr + 1 >= max_data_len { return Err(format!("apply code error at line {}: address overflow", line)); } @@ -184,14 +185,14 @@ fn apply_code(patch_file : &str, codes : &Vec<(u32, u32)>) -> Result<(), String> 0x2 => { code_len = 2; let val = codes[pos + 1].1; - let addr = if let Some(saddr) = search_addr.take() { - if saddr.0 == false { + let addr = if (first_code & 0xf000000) == 0x8000000 { + if search_addr == None { continue; } - (codes[pos].1 & 0xffffff) + saddr.1 + (first_code & 0xffffff) as usize + search_addr.unwrap() } else { - codes[pos].1 & 0xfffffff - } as usize; + (first_code & 0xfffffff) as usize + }; if addr + 3 >= max_data_len { return Err(format!("apply code error at line {}: address overflow", line)); } @@ -203,24 +204,17 @@ fn apply_code(patch_file : &str, codes : &Vec<(u32, u32)>) -> Result<(), String> 0x4 => { code_len = 4; let mut val = codes[pos + 1].1; - let mut addr = if let Some(saddr) = search_addr.take() { - if saddr.0 == false { - continue; - } - (codes[pos].1 & 0xffffff) + saddr.1 - } else { - codes[pos].1 & 0xfffffff - } as usize; + let mut addr = (first_code & 0xffffff) 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 first_code & 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 { + } else if first_code & 0xf000000 == 0x2000000 { if addr + 1 >= max_data_len { return Err(format!("apply code error at line {}: address overflow", line)); } @@ -244,17 +238,19 @@ fn apply_code(patch_file : &str, codes : &Vec<(u32, u32)>) -> Result<(), String> return Err(format!("apply code error at line {}: not supported", line)); } 0x8 => { - // let count = (codes[pos].1 & 0xfff0000) >> 16; - // let search_bytes = (first_code & 0xffff) as usize; - // code_len = ((search_bytes - 1) / 4 + 1) * 2; - // let mut bytes = 0; - // let mut search = Vec::with_capacity(search_bytes); - // while bytes < search_bytes { - // let offset = pos + 1 + (bytes / 4); - // let shift = (3 - (bytes % 4)) * 8; - // search.push(((codes[offset].1 >> shift) & 0xff) as u8); - // bytes += 1; - // } + let count = (codes[pos].1 & 0xfff0000) >> 16; + let search_bytes = (first_code & 0xffff) as usize; + code_len = (search_bytes - 1) / 4 + 2; + code_len += code_len % 2; + let mut bytes = 0; + let mut search = Vec::with_capacity(search_bytes); + while bytes < search_bytes { + let offset = pos + 1 + (bytes / 4); + let shift = (3 - (bytes % 4)) * 8; + search.push(((codes[offset].1 >> shift) & 0xff) as u8); + bytes += 1; + } + search_addr = search_data(count, &data, &search); } 0xa => { let mut addr = (codes[pos].1 & 0xfffffff) as usize; @@ -280,3 +276,15 @@ fn apply_code(patch_file : &str, codes : &Vec<(u32, u32)>) -> Result<(), String> write_file.write(data.as_slice()).map_err(fn_map_err)?; Ok(()) } + +fn search_data(mut count : u32, data : &Vec, search : &Vec) -> Option { + for (position, window) in data.windows(search.len()).enumerate() { + if window == search { + count -= 1; + if count == 0 { + return Some(position); + } + } + } + None +}