Skip to content

Commit

Permalink
add support for mame 0.243
Browse files Browse the repository at this point in the history
  • Loading branch information
FredYeye committed May 7, 2022
1 parent 833235c commit 08f9542
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 53 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Capturing data from bsnes works well, mame is getting there.

## Currently supported emulators:
bsnes v115
mame 0.242
mame 0.242 - 0.243

## Currently supported games:
Gradius III (snes / arcade)
Expand Down
61 changes: 51 additions & 10 deletions src/game_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,57 @@ pub enum Emulator
Mame,
}

impl Emulator
{
pub fn get_mame_version(module_size: u32) -> u16
{
match module_size
{
0x129FB000 => 242,
0x12A82000 => 243,
_ => 0, //unsupported version
}
}

pub fn get_mame_name_offset(version: u16) -> u32
{
match version
{
242 => 0x11EC4450,
243 => 0x11F3C970,
_ => todo!("unsupported mame version"),
}
}

pub fn mame_game_offset(version: u16, games: Games) -> Vec<u64>
{
match version
{
242 =>
{
match games
{
Games::GhoulsArcade => vec![0x11B72B48, 0x08, 0x10, 0x28, 0x38, 0x60, 0x18, 0x80, 0x18],
Games::Gradius3Arcade => vec![0x11B72B48, 0x38, 0x150, 0x8, 0x10],
_ => unreachable!(),
}
}

243 =>
{
match games
{
Games::GhoulsArcade => vec![0x11BF4390, 0x8, 0x10, 0x38, 0x40, 0x80, 0x18, 0x80, 0x18],
Games::Gradius3Arcade => vec![0x11BF4390, 0x28, 0x150, 0x8, 0x10],
_ => unreachable!(),
}
}

_ => todo!("unsupported mame version"),
}
}
}

pub struct GameData
{
pub id: Games,
Expand Down Expand Up @@ -52,16 +103,6 @@ impl Games
}
}

pub fn mame_game_offset(&self) -> Vec<u64>
{
match self
{
Games::GhoulsArcade => vec![0x11B72B48, 0x08, 0x10, 0x28, 0x38, 0x60, 0x18, 0x80, 0x18],
Games::Gradius3Arcade => vec![0x11B72B48, 0x38, 0x150, 0x8, 0x10],
_ => unreachable!(),
}
}

pub fn game_info(&self) -> GameData
{
match self
Expand Down
103 changes: 61 additions & 42 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,37 +210,22 @@ fn find_game(gui_state: &mut GuiState)

if let Some((emu, handle)) = emu_info
{
let mut raw_str = [0; 22];
let base = match emu
{
game_data::Emulator::Bsnes => 0xB151E8 as *const c_void,
game_data::Emulator::Mame =>
{
let name_offset = vec![0x11B72B48];
let offset = get_mame_offset(&handle, name_offset);
(offset + 0xD8) as *const c_void
}
};

unsafe
{
let p_raw_str = raw_str.as_mut_ptr() as *mut _ as *mut c_void;
let mut count = 0;
ReadProcessMemory(handle, base, p_raw_str, raw_str.len() - 1, &mut count);
}
let mut first_module = HINSTANCE::default();
let mut lpcb_needed = 0;
unsafe{ K32EnumProcessModules(handle, &mut first_module, std::mem::size_of::<HINSTANCE>() as u32, &mut lpcb_needed); }

let terminator = raw_str.into_iter().position(|x| x == 0).unwrap();
let mut info = MODULEINFO::default();
unsafe{ K32GetModuleInformation(handle, first_module, &mut info, std::mem::size_of::<MODULEINFO>() as u32); }

let game_name = match std::str::from_utf8(&raw_str[0 .. terminator])
if emu == game_data::Emulator::Mame
{
Ok(name) => match emu
if game_data::Emulator::get_mame_version(info.SizeOfImage) == 0
{
game_data::Emulator::Bsnes => game_data::Games::bsnes_game_name(name),
game_data::Emulator::Mame => game_data::Games::mame_game_name(name),
return; //unsupported mame version. kinda bootleg way to do this
}
}

Err(e) => panic!("failed to get convert game name to string: {e}"),
};
let game_name = get_game_name(&handle, &info, &emu);

match game_name
{
Expand All @@ -251,7 +236,12 @@ fn find_game(gui_state: &mut GuiState)
gui_state.offset = match emu
{
game_data::Emulator::Bsnes => 0xB16D7C,
game_data::Emulator::Mame => get_mame_offset(&handle, game.mame_game_offset()),
game_data::Emulator::Mame =>
{
let version = game_data::Emulator::get_mame_version(info.SizeOfImage);
let offset_list = game_data::Emulator::mame_game_offset(version, game);
get_mame_offset(&handle, info.lpBaseOfDll as u64, offset_list)
}
};
}

Expand All @@ -263,31 +253,40 @@ fn find_game(gui_state: &mut GuiState)
}
}

fn get_mame_offset(handle: &HANDLE, offset_list: Vec<u64>) -> u64
fn get_game_name(handle: &HANDLE, info: &MODULEINFO, emu: &game_data::Emulator) -> Option<game_data::Games>
{
//sleep because getting the offset while mame is loading the game can fail
std::thread::sleep(std::time::Duration::from_secs(2));
let mut raw_str = [0; 22];

unsafe
let game_name_offset = match emu
{
let mut first_module = HINSTANCE::default();
let mut lpcb_needed = 0;
K32EnumProcessModules(handle, &mut first_module, std::mem::size_of::<HINSTANCE>() as u32, &mut lpcb_needed);
game_data::Emulator::Bsnes => 0xB151E8 as *const c_void,
game_data::Emulator::Mame =>
{
let version = game_data::Emulator::get_mame_version(info.SizeOfImage);
let name_offset = game_data::Emulator::get_mame_name_offset(version);

let mut info = MODULEINFO::default();
K32GetModuleInformation(handle, first_module, &mut info, std::mem::size_of::<MODULEINFO>() as u32);
(info.lpBaseOfDll as u64 + name_offset as u64) as *const c_void
}
};

unsafe
{
let p_raw_str = raw_str.as_mut_ptr() as *mut _ as *mut c_void;
let mut count = 0;
ReadProcessMemory(handle, game_name_offset, p_raw_str, raw_str.len() - 1, &mut count);
}

let mut address = info.lpBaseOfDll as u64;
let terminator = raw_str.into_iter().position(|x| x == 0).unwrap();

for offset in offset_list
match std::str::from_utf8(&raw_str[0 .. terminator])
{
Ok(name) => match emu
{
let base = (address + offset) as *const c_void;
let p_address = &mut address as *mut _ as *mut c_void;
let mut count = 0;
ReadProcessMemory(handle, base, p_address, 8, &mut count);
game_data::Emulator::Bsnes => game_data::Games::bsnes_game_name(name),
game_data::Emulator::Mame => game_data::Games::mame_game_name(name),
}

address
Err(_) => None,
}
}

Expand All @@ -300,6 +299,26 @@ fn enum_processes() -> ([u32; 384], u32)
(pid_list, pid_size / 4)
}

fn get_mame_offset(handle: &HANDLE, dll_base: u64, offset_list: Vec<u64>) -> u64
{
std::thread::sleep(std::time::Duration::from_secs(2)); //sleep because getting the offset while mame is loading the game can fail

unsafe
{
let mut address = dll_base;

for offset in offset_list
{
let base = (address + offset) as *const c_void;
let p_address = &mut address as *mut _ as *mut c_void;
let mut count = 0;
ReadProcessMemory(handle, base, p_address, 8, &mut count);
}

address
}
}

fn update(gui_state: &mut GuiState)
{
if gui_state.memory_read_timer > 0
Expand Down

0 comments on commit 08f9542

Please sign in to comment.