1pub fn mirror_to_next_power_of_two(rom: &mut Vec<u8>) { 2 if rom.is_empty() { 3 log::error!("Cannot mirror empty ROM"); 4 return; 5 } 6 7 let ones_count = rom.len().count_ones(); 8 if ones_count == 1 { 9 // ROM size is already a power of two 10 return; 11 } 12 13 let trailing_zeroes = rom.len().trailing_zeros(); 14 let source_len = 1 << trailing_zeroes; 15 let source_mask = source_len - 1; 16 17 let remaining_rom_len = rom.len() & !source_len; 18 let copy_len = (1 << (remaining_rom_len.trailing_zeros())) - source_len; 19 20 log::debug!( 21 "ROM len is {}; duplicating last {source_len} bytes of ROM to last {copy_len} bytes", 22 rom.len() 23 ); 24 25 let base_addr = rom.len() & !source_len; 26 for i in 0..copy_len { 27 rom.push(rom[base_addr + (i & source_mask)]); 28 } 29 30 // Recurse in case there are more than 2 ROM chips (e.g. fan translated version of Daikaijuu 31 // Monogatari II which is 5.5MB) 32 mirror_to_next_power_of_two(rom); 33} 34 35#[cfg(test)] 36mod tests { 37 use super::*; 38 use std::array; 39 40 fn new_vec<const LEN: usize>() -> Vec<u8> { 41 Vec::from(array::from_fn::<u8, LEN, _>(|i| i as u8)) 42 } 43 44 #[test] 45 fn mirror_empty_rom() { 46 let mut rom = vec![]; 47 mirror_to_next_power_of_two(&mut rom); 48 assert_eq!(rom, vec![]); 49 } 50 51 #[test] 52 fn mirror_power_of_two() { 53 let mut rom = new_vec::<8>(); 54 mirror_to_next_power_of_two(&mut rom); 55 assert_eq!(rom, vec![0, 1, 2, 3, 4, 5, 6, 7]); 56 } 57 58 #[test] 59 fn mirror_6_to_8() { 60 let mut rom = new_vec::<6>(); 61 mirror_to_next_power_of_two(&mut rom); 62 assert_eq!(rom, vec![0, 1, 2, 3, 4, 5, 4, 5]); 63 } 64 65 #[test] 66 fn mirror_5_to_8() { 67 let mut rom = new_vec::<5>(); 68 mirror_to_next_power_of_two(&mut rom); 69 assert_eq!(rom, vec![0, 1, 2, 3, 4, 4, 4, 4]); 70 } 71 72 #[test] 73 fn mirror_11_to_16() { 74 let mut rom = new_vec::<11>(); 75 mirror_to_next_power_of_two(&mut rom); 76 assert_eq!(rom, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 8, 9, 10, 10]); 77 } 78}