1import hashlib 2import os 3from fsgs import Option 4from fsgs.drivers.mednafendriver import MednafenDriver 5from fsgs.platform import Platform 6from fsgs.platforms.loader import SimpleLoader 7 8 9class GameGearPlatform(Platform): 10 PLATFORM_NAME = "Game Gear" 11 12 def driver(self, fsgc): 13 return MednafenGameGearDriver(fsgc) 14 15 def loader(self, fsgc): 16 return GameGearLoader(fsgc) 17 18 19class GameGearLoader(SimpleLoader): 20 pass 21 22 23class MednafenGameGearDriver(MednafenDriver): 24 CONTROLLER = { 25 "type": "gamepad", 26 "description": "Built-in Controller", 27 "mapping_name": "gamegear", 28 } 29 30 PORTS = [{"description": "Controller", "types": [CONTROLLER]}] 31 32 def __init__(self, fsgc): 33 super().__init__(fsgc) 34 self.helper = GameGearHelper(self.options) 35 36 def prepare(self): 37 super().prepare() 38 self.set_mednafen_aspect(66, 50) 39 # We do aspect calculation separately. Must not be done twice. 40 # self.emulator.args.extend(["-snes.correct_aspect", "0"]) 41 rom_path = self.helper.prepare_rom(self) 42 self.emulator.args.append(rom_path) 43 44 def get_game_refresh_rate(self): 45 return 59.73 46 47 def mednafen_input_mapping(self, port): 48 return { 49 "A": "gb.input.builtin.gamepad.a", 50 "B": "gb.input.builtin.gamepad.b", 51 "UP": "gb.input.builtin.gamepad.up", 52 "DOWN": "gb.input.builtin.gamepad.down", 53 "LEFT": "gb.input.builtin.gamepad.left", 54 "RIGHT": "gb.input.builtin.gamepad.right", 55 "SELECT": "gb.input.builtin.gamepad.select", 56 "START": "gb.input.builtin.gamepad.start", 57 } 58 59 def mednafen_rom_extensions(self): 60 return [".gg"] 61 62 def mednafen_scanlines_setting(self): 63 return 0 64 65 def mednafen_special_filter(self): 66 return "nn2x" 67 68 def mednafen_system_prefix(self): 69 return "gg" 70 71 def game_video_par(self): 72 return (6.6 / 5.0) / (160 / 144) 73 74 def game_video_size(self): 75 return 160, 144 76 77 def get_game_file(self, config_key="cartridge_slot"): 78 return None 79 80 81class GameGearHelper: 82 def __init__(self, options): 83 self.options = options 84 85 def prepare_rom(self, driver): 86 file_uri = self.options[Option.CARTRIDGE_SLOT] 87 input_stream = driver.fsgc.file.open(file_uri) 88 _, ext = os.path.splitext(file_uri) 89 return self.prepare_rom_with_stream(driver, input_stream, ext) 90 91 def prepare_rom_with_stream(self, driver, input_stream, ext): 92 sha1_obj = hashlib.sha1() 93 path = driver.temp_file("rom" + ext).path 94 with open(path, "wb") as f: 95 while True: 96 data = input_stream.read(65536) 97 if not data: 98 break 99 f.write(data) 100 sha1_obj.update(data) 101 new_path = os.path.join( 102 os.path.dirname(path), sha1_obj.hexdigest()[:8].upper() + ext 103 ) 104 os.rename(path, new_path) 105 return new_path 106