// test_thumb public static void TestThumb() { Console.WriteLine("Emulate THUMB code"); using (var emulator = new ArmEmulator(ArmMode.Thumb)) { ulong addr = 0x10000; // sub sp, #0xc byte[] armcode = { 0x83, 0xb0 }; // Map 2mb of memory. emulator.Memory.Map(addr, 2 * 1024 * 1024, MemoryPermissions.All); emulator.Memory.Write(addr, armcode, (uint)armcode.Length); emulator.Registers.SP = 0x1234; emulator.Hooks.Block.Add(HookBlock, null); emulator.Hooks.Code.Add(HookCode, addr, addr, null); emulator.Start(addr | 1, addr + (ulong)armcode.Length); Console.WriteLine(">>> Emulation done. Below is the CPU context"); Console.WriteLine($">>> SP = 0x{emulator.Registers.SP.ToString("x2")}"); } }
// test_arm public static void TestArm() { Console.WriteLine("Emulate ARM code"); using (var emulator = new ArmEmulator(ArmMode.Arm)) { ulong addr = 0x10000; // mov r0, #0x37; sub r1, r2, r3 byte[] armcode = { 0x37, 0x00, 0xa0, 0xe3, 0x03, 0x10, 0x42, 0xe0 }; // Map 2mb of memory. emulator.Memory.Map(addr, 2 * 1024 * 1024, MemoryPermissions.All); emulator.Memory.Write(addr, armcode, (ulong)armcode.Length); emulator.Registers.R0 = 0x1234; emulator.Registers.R2 = 0x6789; emulator.Registers.R3 = 0x3333; emulator.Hooks.Block.Add(HookBlock, null); emulator.Hooks.Code.Add(HookCode, addr, addr, null); emulator.Start(addr, addr + (ulong)armcode.Length); Console.WriteLine(">>> Emulation done. Below is the CPU context"); Console.WriteLine($">>> R0 = 0x{emulator.Registers.R0.ToString("x2")}"); Console.WriteLine($">>> R1 = 0x{emulator.Registers.R1.ToString("x2")}"); } }
public static void Main(string[] args) { Console.WriteLine("Unicorn version - " + Version.Current); using (var emulator = new MipsEmulator(MipsMode.b32 | MipsMode.BigEndian)) { ulong addr = 0x10000; byte[] mipscode = { 0x34, 0x21, 0x34, 0x56 }; emulator.Memory.Map(addr, 2 * 1024 * 1024, MemoryPermissions.All); emulator.Memory.Write(addr, mipscode, mipscode.Length); emulator.Registers._1 = 0x6789; emulator.Hooks.Code.Add(CodeHook, null); emulator.Start(addr, addr + (ulong)mipscode.Length); Console.WriteLine("{0}", emulator.Registers._1); } using (var emulator = new ArmEmulator(ArmMode.Arm)) { ulong addr = 0x10000; // mov r0, #0x37; sub r1, r2, r3 byte[] armcode = { 0x37, 0x00, 0xa0, 0xe3, 0x03, 0x10, 0x42, 0xe0 }; // Map 2mb of memory. emulator.Memory.Map(addr, 2 * 1024 * 1024, MemoryPermissions.All); emulator.Memory.Write(addr, armcode, armcode.Length); emulator.Registers.R0 = 0x1234; emulator.Registers.R2 = 0x6789; emulator.Registers.R3 = 0x3333; emulator.Hooks.Block.Add((emu, address, size, userToken) => { Console.WriteLine($">>> Tracing basic block at 0x{address.ToString("x2")}, block size = 0x{size.ToString("x2")}"); }, null); emulator.Hooks.Code.Add((emu, address, size, userToken) => { Console.WriteLine($">>> Tracing instruction at 0x{address.ToString("x2")}, instruction size = 0x{size.ToString("x2")}"); }, null); emulator.Start(addr, addr + (ulong)armcode.Length); Console.WriteLine(">>> Emulation done. Below is the CPU context"); Console.WriteLine($">>> R0 = 0x{emulator.Registers.R0.ToString("x2")}"); Console.WriteLine($">>> R1 = 0x{emulator.Registers.R1.ToString("x2")}"); } /* using (var emulator = new X86Emulator(X86Mode.b32)) { ulong addr = 0x1000000; byte[] x86code = { 0x41, // INC ECX 0x4a // DEC EDX }; var ecx = 0x1234; var edx = 0x7890; // Map 2mb of memory. emulator.Memory.Map(addr, 2 * 1024 * 1024, MemoryPermissions.All); var handle = emulator.Hooks.Code.Add(CodeHook, null); // Capture context. Console.WriteLine("-> Capturing context..."); using (var context = emulator.Context) { emulator.Registers.ECX = ecx; emulator.Registers.EDX = edx; emulator.Memory.Write(addr, x86code, x86code.Length); emulator.Start(addr, addr + (ulong)x86code.Length); Console.WriteLine($"ECX = {emulator.Registers.ECX}"); Console.WriteLine($"EDX = {emulator.Registers.EDX}"); Console.WriteLine("-> Restoring context..."); // Restore captured context. emulator.Context = context; } Console.WriteLine($"ECX = {emulator.Registers.ECX}"); Console.WriteLine($"EDX = {emulator.Registers.EDX}"); } */ Console.ReadLine(); }
private void emulate_Click(object sender, EventArgs e) { ArmMode arm_mode = ArmMode.Arm; if (thumb.Checked) { arm_mode = ArmMode.Thumb; } uint addr = (uint)ReadStartAddress.Value; if ((addr & 1) == 1) { arm_mode = ArmMode.Thumb; addr--; } if (addr >= GBAMemory.ROM_ADDR) { addr -= GBAMemory.ROM_ADDR; U.ForceUpdate(ReadStartAddress, addr); } if (addr >= (uint)Program.ROM.Data.Length) { return; } addr += GBAMemory.ROM_ADDR; EncodedData enc; // 即时汇编 if (arm_mode == ArmMode.Thumb) { using (Engine keystone = new Engine(Architecture.ARM, Mode.THUMB) { ThrowOnError = true }) { enc = keystone.Assemble(assembly.Text, addr); } } else { using (Engine keystone = new Engine(Architecture.ARM, Mode.ARM) { ThrowOnError = true }) { enc = keystone.Assemble(assembly.Text, addr); } } // 模拟运行 using (var emulator = new ArmEmulator(arm_mode)) { // load register value emulator.Registers.R0 = (long)r0.Value; emulator.Registers.R1 = (long)r1.Value; emulator.Registers.R2 = (long)r2.Value; emulator.Registers.R3 = (long)r3.Value; emulator.Registers.R4 = (long)r4.Value; emulator.Registers.R5 = (long)r5.Value; emulator.Registers.R6 = (long)r6.Value; emulator.Registers.R7 = (long)r7.Value; emulator.Registers.R8 = (long)r8.Value; emulator.Registers.R9 = (long)r9.Value; emulator.Registers.R10 = (long)r10.Value; emulator.Registers.R11 = (long)r11.Value; emulator.Registers.R12 = (long)r12.Value; emulator.Registers.SP = (long)r13.Value; emulator.Registers.LR = (long)r14.Value; //emulator.Registers.PC = (long)r15.Value; // load ROM if (whole_rom.Checked) { emulator.Memory.Map(GBAMemory.ROM_ADDR, Program.ROM.Data.Length, MemoryPermissions.Execute | MemoryPermissions.Read); emulator.Memory.Write(GBAMemory.ROM_ADDR, Program.ROM.Data, Program.ROM.Data.Length); } else { emulator.Memory.Map(addr, enc.Buffer.Length, MemoryPermissions.All); } // load assembly emulator.Memory.Write(addr, enc.Buffer, enc.Buffer.Length); // 加载GBA地址布局 if (memory.Checked) { // laod WRAM emulator.Memory.Map(GBAMemory.EWRAM_ADDR, GBAMemory.EWRAM_MAX_LENGTH, MemoryPermissions.All); emulator.Memory.Map(GBAMemory.IWRAM_ADDR, GBAMemory.IWRAM_MAX_LENGTH, MemoryPermissions.All); if (!String.IsNullOrEmpty(sgm.Text)) { if (File.Exists(sgm.Text)) { //TODO load data in .sgm to EWRAM and IWRAM } } // load SRAM emulator.Memory.Map(GBAMemory.SRAM_ADDR, GBAMemory.SRAM_MAX_LENGTH, MemoryPermissions.Write | MemoryPermissions.Read); if (!String.IsNullOrEmpty(sav.Text)) { if (File.Exists(sav.Text)) { FileInfo fi = new FileInfo(sav.Text); byte[] buff = new byte[Math.Min(GBAMemory.SRAM_MAX_LENGTH, fi.Length)]; FileStream fs = fi.OpenRead(); fs.Read(buff, 0, Math.Min(buff.Length, Convert.ToInt32(fs.Length))); fs.Close(); emulator.Memory.Write(GBAMemory.SRAM_ADDR, buff, buff.Length); } } // load BIOS emulator.Memory.Map(GBAMemory.BIOS_ADDR, GBAMemory.BIOS_MAX_LENGTH, MemoryPermissions.Execute); if (!String.IsNullOrEmpty(bios.Text)) { if (File.Exists(bios.Text)) { FileInfo fi = new FileInfo(bios.Text); byte[] buff = new byte[Math.Min(GBAMemory.BIOS_MAX_LENGTH, fi.Length)]; FileStream fs = fi.OpenRead(); fs.Read(buff, 0, Math.Min(buff.Length, Convert.ToInt32(fs.Length))); fs.Close(); emulator.Memory.Write(GBAMemory.BIOS_ADDR, buff, buff.Length); } else { bios.Clear(); } } // load IOREG // PageSize = 1KB, 不翻倍map内存的时候会报错 emulator.Memory.Map(GBAMemory.IOREG_ADDR, GBAMemory.IOREG_MAX_LENGTH * 2, MemoryPermissions.Read | MemoryPermissions.Write); if (!String.IsNullOrEmpty(ioreg.Text)) { if (File.Exists(ioreg.Text)) { FileInfo fi = new FileInfo(ioreg.Text); byte[] buff = new byte[Math.Min(GBAMemory.IOREG_MAX_LENGTH, fi.Length)]; FileStream fs = fi.OpenRead(); fs.Read(buff, 0, Math.Min(buff.Length, Convert.ToInt32(fs.Length))); fs.Close(); emulator.Memory.Write(GBAMemory.IOREG_ADDR, buff, buff.Length); } } // load PALRAM // PageSize = 1KB, 不翻倍map内存的时候会报错 emulator.Memory.Map(GBAMemory.PALRAM_ADDR, GBAMemory.PALRAM_MAX_LENGTH * 2, MemoryPermissions.Read | MemoryPermissions.Write); if (!String.IsNullOrEmpty(palram.Text)) { if (File.Exists(palram.Text)) { FileInfo fi = new FileInfo(palram.Text); byte[] buff = new byte[Math.Min(GBAMemory.PALRAM_MAX_LENGTH, fi.Length)]; FileStream fs = fi.OpenRead(); fs.Read(buff, 0, Math.Min(buff.Length, Convert.ToInt32(fs.Length))); fs.Close(); emulator.Memory.Write(GBAMemory.PALRAM_ADDR, buff, buff.Length); } } // load VRAM emulator.Memory.Map(GBAMemory.VRAM_ADDR, GBAMemory.VRAM_MAX_LENGTH, MemoryPermissions.Read | MemoryPermissions.Write); if (!String.IsNullOrEmpty(vram.Text)) { if (File.Exists(vram.Text)) { FileInfo fi = new FileInfo(vram.Text); byte[] buff = new byte[Math.Min(GBAMemory.VRAM_MAX_LENGTH, fi.Length)]; FileStream fs = fi.OpenRead(); fs.Read(buff, 0, Math.Min(buff.Length, Convert.ToInt32(fs.Length))); fs.Close(); emulator.Memory.Write(GBAMemory.VRAM_ADDR, buff, buff.Length); } } // load OAM // PageSize = 1KB, 不翻倍map内存的时候会报错 emulator.Memory.Map(GBAMemory.OAM_ADDR, GBAMemory.OAM_MAX_LENGTH * 2, MemoryPermissions.Read | MemoryPermissions.Write); if (!String.IsNullOrEmpty(oam.Text)) { if (File.Exists(oam.Text)) { FileInfo fi = new FileInfo(oam.Text); byte[] buff = new byte[Math.Min(GBAMemory.OAM_MAX_LENGTH, fi.Length)]; FileStream fs = fi.OpenRead(); fs.Read(buff, 0, Math.Min(buff.Length, Convert.ToInt32(fs.Length))); fs.Close(); emulator.Memory.Write(GBAMemory.OAM_ADDR, buff, buff.Length); } } // load address value list if (!String.IsNullOrEmpty(address_value.Text)) { foreach (string line in address_value.Lines) { if (String.IsNullOrWhiteSpace(line)) { string[] record = line.Split(':'); if (record.Length == 2) { ulong address = ulong.Parse(record[0], System.Globalization.NumberStyles.HexNumber); string[] byte_list = (record[1]).Split(); emulator.Memory.Write(address, Array.ConvertAll <string, byte>(byte_list, s => byte.Parse(s, System.Globalization.NumberStyles.HexNumber)), byte_list.Length); } } } } } // emulate emulator.Start(addr, addr + (ulong)enc.Buffer.Length, new TimeSpan(0, 0, Convert.ToInt32(timeout.Value)), Convert.ToInt32(code_num_limit.Value)); // show registers r0.Value = emulator.Registers.R0; r0.Update(); r1.Value = emulator.Registers.R1; r1.Update(); r2.Value = emulator.Registers.R2; r2.Update(); r3.Value = emulator.Registers.R3; r3.Update(); r4.Value = emulator.Registers.R4; r4.Update(); r5.Value = emulator.Registers.R5; r5.Update(); r6.Value = emulator.Registers.R6; r6.Update(); r7.Value = emulator.Registers.R7; r7.Update(); r8.Value = emulator.Registers.R8; r8.Update(); r9.Value = emulator.Registers.R9; r9.Update(); r10.Value = emulator.Registers.R10; r10.Update(); r11.Value = emulator.Registers.R11; r11.Update(); r12.Value = emulator.Registers.R12; r12.Update(); r13.Value = emulator.Registers.SP; r13.Update(); r14.Value = emulator.Registers.LR; r14.Update(); r15.Value = emulator.Registers.PC; r15.Update(); if (memory.Checked) { // dump binaries if (!String.IsNullOrEmpty(sav.Text)) { byte[] buff = new byte[GBAMemory.SRAM_MAX_LENGTH]; emulator.Memory.Read(GBAMemory.SRAM_ADDR, buff, buff.Length); FileStream fs = new FileStream(sav.Text, FileMode.Create); BinaryWriter bw = new BinaryWriter(fs); bw.Write(buff, 0, buff.Length); bw.Close(); fs.Close(); } if (!String.IsNullOrEmpty(sgm.Text)) { //TODO dump data in EWRAM and IWRAM to .sgm } if (!String.IsNullOrEmpty(ioreg.Text)) { byte[] buff = new byte[GBAMemory.IOREG_MAX_LENGTH]; emulator.Memory.Read(GBAMemory.IOREG_ADDR, buff, buff.Length); FileStream fs = new FileStream(ioreg.Text, FileMode.Create); BinaryWriter bw = new BinaryWriter(fs); bw.Write(buff, 0, buff.Length); bw.Close(); fs.Close(); } if (!String.IsNullOrEmpty(palram.Text)) { byte[] buff = new byte[GBAMemory.PALRAM_MAX_LENGTH]; emulator.Memory.Read(GBAMemory.PALRAM_ADDR, buff, buff.Length); FileStream fs = new FileStream(palram.Text, FileMode.Create); BinaryWriter bw = new BinaryWriter(fs); bw.Write(buff, 0, buff.Length); bw.Close(); fs.Close(); } if (!String.IsNullOrEmpty(vram.Text)) { byte[] buff = new byte[GBAMemory.VRAM_MAX_LENGTH]; emulator.Memory.Read(GBAMemory.VRAM_ADDR, buff, buff.Length); FileStream fs = new FileStream(vram.Text, FileMode.Create); BinaryWriter bw = new BinaryWriter(fs); bw.Write(buff, 0, buff.Length); bw.Close(); fs.Close(); } if (!String.IsNullOrEmpty(oam.Text)) { byte[] buff = new byte[GBAMemory.OAM_MAX_LENGTH]; emulator.Memory.Read(GBAMemory.OAM_ADDR, buff, buff.Length); FileStream fs = new FileStream(oam.Text, FileMode.Create); BinaryWriter bw = new BinaryWriter(fs); bw.Write(buff, 0, buff.Length); bw.Close(); fs.Close(); } } } }