def _parse_peripherals(metadata: Metadata, peripherals: Collection[str]): for peripheral_char in peripherals: if peripheral_char == 'M': #3 buttons if I'm not mistaken mouse = input_metadata.Mouse() mouse.buttons = 3 metadata.input_info.add_option(mouse) elif peripheral_char == 'V': #Is this just the SMS paddle? metadata.input_info.add_option(input_metadata.Paddle()) elif peripheral_char == 'A': xe_1_ap = input_metadata.NormalController() xe_1_ap.face_buttons = 10 xe_1_ap.shoulder_buttons = 4 xe_1_ap.analog_sticks = 2 #The second one only has one axis, though metadata.input_info.add_option(xe_1_ap) elif peripheral_char == 'G': menacer = input_metadata.LightGun() menacer.buttons = 2 #Also pause button metadata.input_info.add_option(menacer) elif peripheral_char == 'K': xband_keyboard = input_metadata.Keyboard() xband_keyboard.keys = 68 #I think I counted that right... I was just looking at the picture metadata.input_info.add_option(xband_keyboard) elif peripheral_char == 'J': metadata.input_info.add_option(standard_gamepad) elif peripheral_char == '6': six_button_gamepad = input_metadata.NormalController() six_button_gamepad.face_buttons = 6 six_button_gamepad.dpads = 1 metadata.input_info.add_option(six_button_gamepad) metadata.specific_info['Uses 6-Button Controller?'] = True elif peripheral_char == '0': sms_gamepad = input_metadata.NormalController() sms_gamepad.face_buttons = 2 sms_gamepad.dpads = 1 metadata.input_info.add_option(sms_gamepad) elif peripheral_char == 'L': #Activator metadata.input_info.add_option(input_metadata.MotionControls()) elif peripheral_char in {'4', 'O'}: #Team Play and J-Cart respectively #num_players = 4 pass elif peripheral_char == 'C': metadata.specific_info['Uses CD?'] = True
def add_info_from_software_list(metadata: 'Metadata', software: 'Software'): software.add_standard_metadata(metadata) compatibility = software.compatibility if compatibility: if 'XL' in compatibility or 'XL/XE' in compatibility: metadata.specific_info['Machine'] = 'XL' elif 'XE' in compatibility: metadata.specific_info['Machine'] = 'XE' if 'OSb' in compatibility: metadata.specific_info['Requires OS B?'] = True peripheral = software.get_part_feature('peripheral') joystick = input_metadata.NormalController() joystick.dpads = 1 joystick.face_buttons = 2 keyboard = input_metadata.Keyboard() keyboard.keys = 57 #From looking at photos so I may have lost count; XL/XE might have more keys if peripheral == 'cx77_touch': #Tablet metadata.input_info.add_option(input_metadata.Touchscreen()) elif peripheral == 'cx75_pen': #Light pen metadata.input_info.add_option(input_metadata.LightGun()) elif peripheral == 'koala_pad,koala_pen': #Combination tablet/light pen metadata.input_info.add_option( [input_metadata.LightGun(), input_metadata.Touchscreen()]) elif peripheral == 'trackball': metadata.input_info.add_option(controllers.cx22_trackball) elif peripheral == 'lightgun': #XEGS only metadata.input_info.add_option(controllers.xegs_gun) else: #trackfld = Track & Field controller but is that just a spicy joystick? metadata.input_info.add_option([joystick, keyboard]) metadata.specific_info['Peripheral'] = peripheral requirement = software.get_shared_feature('requirement') if requirement == 'a800:basicb': metadata.specific_info['Requires BASIC?'] = True #Also: a800:msbasic2, a800:basxe41, a800:writerd, a800:spectra2 (none of those are games, the first two are just language extensions, the latter is noted as not being supported anyway, therefore meh) usage = software.get_info('usage') if usage == 'Plays music only in PAL': metadata.specific_info['TV Type'] = TVSystem.PAL elif usage == 'BASIC must be enabled.': metadata.specific_info['Requires BASIC?'] = True else: metadata.add_notes(usage)
def add_atari_5200_software_info(software: 'Software', metadata: 'Metadata'): software.add_standard_metadata(metadata) uses_trackball = software.get_part_feature('peripheral') == 'trackball' metadata.save_type = SaveType.Nothing #Probably #This doesn't really matter anyway, because MAME doesn't let you select controller type by slot device yet; and none of the other 5200 emulators are cool metadata.specific_info['Uses Trackball?'] = uses_trackball if uses_trackball: metadata.input_info.add_option(input_metadata.Trackball()) else: normal_controller = input_metadata.NormalController() normal_controller.face_buttons = 2 #1, 2, (Pause, Reset, Start) I think? I think it works the same way for trackballs normal_controller.analog_sticks = 1 metadata.input_info.add_option(normal_controller)
def add_sg1000_software_info(software: 'Software', metadata: 'Metadata'): metadata.save_type = SaveType.Nothing #Until proven otherwise software.add_standard_metadata(metadata) uses_tablet = software.get_part_feature('peripheral') == 'tablet' #There doesn't seem to be a way to know if software is a SC-3000 cart, unless I just say whichever one has the .sc extension. So I'll do that if uses_tablet: #A drawing tablet, but that's more or less a touchscreen #No buttons here? metadata.input_info.add_option(input_metadata.Touchscreen()) else: normal_controller = input_metadata.NormalController() normal_controller.face_buttons = 2 normal_controller.dpads = 1 metadata.input_info.add_option(normal_controller)
def add_microtan_65_software_info(software: 'Software', metadata: 'Metadata'): software.add_standard_metadata(metadata) usage = software.get_info('usage') if usage == 'Requires Joystick': joystick = input_metadata.NormalController() #1 start button joystick.dpads = 1 joystick.face_buttons = 2 metadata.input_info.add_option(joystick) elif usage == 'Requires Hex Keypad': hex_keypad = input_metadata.Keypad() hex_keypad.keys = 20 metadata.input_info.add_option(hex_keypad) elif usage in { 'Requires ASCII Keyboard', 'Requires ASCII Keyboard: A=Up, Z=Down, <=Left, >=Right' }: keyboard = input_metadata.Keyboard() keyboard.keys = 62 metadata.input_info.add_option(keyboard) else: metadata.add_notes(usage)
def add_n64_custom_info(game: 'ROMGame'): entire_rom = cast(FileROM, game.rom).read() magic = entire_rom[:4] is_byteswapped = False if magic == b'\x80\x37\x12\x40': game.metadata.specific_info['ROM Format'] = 'Z64' elif magic == b'\x37\x80\x40\x12': is_byteswapped = True game.metadata.specific_info['ROM Format'] = 'V64' else: game.metadata.specific_info['ROM Format'] = 'Unknown' return header = entire_rom[:64] if is_byteswapped: header = byteswap(header) parse_n64_header(game.metadata, header) normal_controller = input_metadata.NormalController() normal_controller.face_buttons = 6 #A, B, 4 * C normal_controller.shoulder_buttons = 3 #L, R, and I guess Z will have to be counted as a shoulder button normal_controller.analog_sticks = 1 normal_controller.dpads = 1 game.metadata.input_info.add_option(normal_controller) database = _get_mupen64plus_database() if database: rom_md5 = hashlib.md5(entire_rom).hexdigest().upper() database_entry = database.get(rom_md5) if database_entry: add_info_from_database_entry(game.metadata, database_entry) software = game.get_software_list_entry() if software: add_generic_software_info(software, game.metadata)
def add_game_boy_custom_info(game: 'ROMGame'): builtin_gamepad = input_metadata.NormalController() builtin_gamepad.dpads = 1 builtin_gamepad.face_buttons = 2 #A B game.metadata.input_info.add_option(builtin_gamepad) rom = cast(FileROM, game.rom) header = rom.read(seek_to=0x100, amount=0x50) _parse_gameboy_header(game.metadata, header) if _game_boy_config and _game_boy_config.options.get('set_gbc_as_different_platform'): if game.rom.extension == 'gbc' or game.metadata.specific_info.get('Is Colour?') == GameBoyColourFlag.Required: game.metadata.platform = 'Game Boy Color' if game.rom.extension == 'gbx': _parse_gbx_footer(rom, game.metadata) if game.rom.extension == 'gbx': software = find_in_software_lists(game.related_software_lists, matcher_args_for_bytes(rom.read(amount=rom.size - 64))) else: software = game.get_software_list_entry() if software: _add_game_boy_software_info(software, game.metadata)
def _add_ds_input_info(metadata: 'Metadata'): builtin_buttons = input_metadata.NormalController() builtin_buttons.dpads = 1 builtin_buttons.face_buttons = 4 #I forgot why we're not counting Start and Select but I guess that's a thing builtin_buttons.shoulder_buttons = 2 builtin_gamepad = input_metadata.CombinedController( [builtin_buttons, input_metadata.Touchscreen()]) bluetooth_keyboard = input_metadata.Keyboard() bluetooth_keyboard.keys = 64 #If I counted correctly from the image... if metadata.product_code: if metadata.product_code.startswith('UZP'): #For now, we'll detect stuff by product code... this is Learn with Pokemon Typing Adventure, and it's different because the Bluetooth adapter is in the cartridge itself metadata.specific_info['Uses Keyboard?'] = True #Keyboard is technically optional, as I understand it, so I guess it's a separate option metadata.input_info.add_option(bluetooth_keyboard) if metadata.platform == 'DSi': #Since the DSi has no GBA slot, there's nothing to put funny expansion devices into. #Hmmm... would I be able to make that assumption with DSi-enhanced games? metadata.input_info.add_option(builtin_gamepad) return #Rumble is detected from GameTDB #Certain games use other input_info that I haven't automagically detected: #Slide Adventure MAGKID: Slidey thing (effectively a mouse) #Easy Piano: Play & Compose: Piano (dunno much about it) #Guitar Hero: On Tour series: Guitar grip (4 buttons) #Arkanoid DS: Paddle (also usable by some other Taito games) (might be just optional?) #Tony Hawk's Motion: Gyroscope #Various homebrew: DS Motion Pack #But for now let's just do the standard controls, and hence cause code duplication metadata.input_info.add_option(builtin_gamepad)
def add_colecovision_software_info(software: 'Software', metadata: 'Metadata'): #Can get year, publisher unreliably from the title screen info in the ROM; please do not do that peripheral: ColecoController = ColecoController.Normal peripheral_required = False software.add_standard_metadata(metadata) usage = software.get_info('usage') if usage == 'Supports Super Action Controllers': peripheral = ColecoController.SuperActionController elif usage == 'Requires Super Action Controllers': peripheral = ColecoController.SuperActionController peripheral_required = True elif usage == 'Supports roller controller': peripheral = ColecoController.RollerController elif usage == 'Requires roller controller': peripheral = ColecoController.RollerController peripheral_required = True elif usage == 'Supports driving controller': peripheral = ColecoController.DrivingController elif usage == 'Requires driving controller': peripheral = ColecoController.DrivingController peripheral_required = True else: metadata.add_notes(usage) normal_controller_part = input_metadata.NormalController() normal_controller_part.face_buttons = 2 normal_controller_part.dpads = 1 normal_controller_keypad = input_metadata.Keypad() normal_controller_keypad.keys = 12 normal_controller = input_metadata.CombinedController( [normal_controller_part, normal_controller_keypad]) super_action_controller_buttons = input_metadata.NormalController() super_action_controller_buttons.face_buttons = 4 #Not really on the face, they're on the hand grip part, but still super_action_controller_buttons.dpads = 1 super_action_controller_speed_roller = input_metadata.Dial( ) #Kind of, it's like a one-dimensional trackball from what I can tell super_action_controller_keypad = input_metadata.Keypad() super_action_controller_keypad.keys = 12 super_action_controller = input_metadata.CombinedController([ super_action_controller_buttons, super_action_controller_speed_roller, super_action_controller_keypad ]) roller_controller = input_metadata.Trackball() #Not sure how many buttons? driving_controller = input_metadata.SteeringWheel() #Gas pedal is on + off so I guess it counts as one button metadata.specific_info['Peripheral'] = peripheral if peripheral == ColecoController.Normal: metadata.input_info.add_option(normal_controller) else: if peripheral == ColecoController.DrivingController: metadata.input_info.add_option(driving_controller) elif peripheral == ColecoController.RollerController: metadata.input_info.add_option(roller_controller) elif peripheral == ColecoController.SuperActionController: metadata.input_info.add_option(super_action_controller) if not peripheral_required: metadata.input_info.add_option(normal_controller)
def add_nes_software_list_metadata(software: 'Software', metadata: Metadata): software.add_standard_metadata(metadata) nes_peripheral = None #FIXME: Acktually, you can have multiple feature = peripherals #See also: SMB / Duck Hunt / World Class Track Meet multicart, with both zapper and powerpad #Actually, how does that even work in real life? Are the controllers hotplugged? Different ports? peripheral = software.get_part_feature('peripheral') if peripheral == 'zapper': nes_peripheral = NESPeripheral.Zapper zapper = input_metadata.LightGun() zapper.buttons = 1 metadata.input_info.add_option(zapper) elif peripheral == 'vaus': nes_peripheral = NESPeripheral.ArkanoidPaddle vaus = input_metadata.Paddle() vaus.buttons = 1 metadata.input_info.add_option(vaus) #Can still use standard controller metadata.input_info.add_option(_standard_controller) elif peripheral in {'powerpad', 'ftrainer', 'fffitness'}: nes_peripheral = NESPeripheral.PowerPad power_pad = input_metadata.NormalController() power_pad.face_buttons = 12 #"face" metadata.input_info.add_option(power_pad) elif peripheral == 'powerglove': nes_peripheral = NESPeripheral.PowerGlove #Hmm... apparently it functions as a standard NES controller, but there are 2 games specifically designed for glove usage? So it must do something extra I guess power_glove = input_metadata.MotionControls() #game.metadata.input_info.buttons = 11 #Standard A + B + 9 program buttons metadata.input_info.add_option(power_glove) elif peripheral == 'rob': nes_peripheral = NESPeripheral.ROB #I'll leave input info alone, because I'm not sure how I would classify ROB metadata.input_info.add_option(_standard_controller) elif peripheral == 'fc_keyboard': nes_peripheral = NESPeripheral.FamicomKeyboard famicom_keyboard = input_metadata.Keyboard() famicom_keyboard.keys = 72 metadata.input_info.add_option(famicom_keyboard) elif peripheral == 'subor_keyboard': nes_peripheral = NESPeripheral.SuborKeyboard subor_keyboard = input_metadata.Keyboard() subor_keyboard.keys = 96 metadata.input_info.add_option(subor_keyboard) elif peripheral == 'mpiano': nes_peripheral = NESPeripheral.Piano #Apparently, it's actually just a MIDI keyboard, hence the MAME driver adds MIDI in/out ports miracle_piano = input_metadata.Custom('88-key piano') #game.metadata.input_info.buttons = 88 metadata.input_info.add_option(miracle_piano) else: metadata.input_info.add_option(_standard_controller) #Well, it wouldn't be a controller... not sure how this one works exactly metadata.specific_info['Uses 3D Glasses?'] = peripheral == '3dglasses' if peripheral == 'turbofile': #Thing that goes into Famicom controller expansion port and saves stuff metadata.save_type = SaveType.MemoryCard #There's a "battlebox" which Armadillo (Japan) uses? #Barcode World (Japan) uses "barcode" #Peripheral = 4p_adapter: 4 players #Gimmi a Break stuff: "partytap"? #Hyper Olympic (Japan): "hypershot" #Ide Yousuke Meijin no Jissen Mahjong (Jpn, Rev. A): "mjcontroller" (mahjong controller?) #RacerMate Challenge 2: "racermate" #Top Rider (Japan): "toprider" metadata.add_notes(software.infos.get('usage')) #This only works on a Famicom with Mahjong Controller attached #This only is only supported by Famicom [sic?] if nes_peripheral: metadata.specific_info['Peripheral'] = nes_peripheral
find_in_software_lists_with_custom_matcher, get_crc32_for_software_list) from meowlauncher.games.roms.rom import FileROM from meowlauncher.metadata import Date, Metadata from meowlauncher.platform_types import NESPeripheral from meowlauncher.util.region_info import TVSystem from meowlauncher.util.utils import decode_bcd, load_dict if TYPE_CHECKING: from meowlauncher.games.mame_common.software_list import (Software, SoftwarePart) from meowlauncher.games.roms.rom_game import ROMGame _nes_config = platform_configs.get('NES') _nintendo_licensee_codes = load_dict(None, 'nintendo_licensee_codes') _standard_controller = input_metadata.NormalController() _standard_controller.dpads = 1 _standard_controller.face_buttons = 2 #A B _ines_mappers = { #TODO: This should be a dataclass, instead of storing both Mapper (name) and Mapper Number in the game info #6, 8, 17 are some kind of copier thing #29 is for homebrew but doesn't really have a name #31 is for homebrew musicdisks specifically #51, 53, 55, 126, 162, 197, 204, 213, 214, 217, 236, 244, 251 are unknown/undocumented pirate mappers #63, 103, 108, 117, 120, 170, 179, 216 are even more unknown #160 is unknown (well, undocumented) Sachen mapper; 56, 142, 175 are undocumented Kaiser mappers; 198, 223, 249 are undocumented Waixing mappers #98, 102, 109, 110, 122, 124, 127, 128, 129, 130, 131, 161, 239, 247 are unassigned supposedly (I bet someone's assigned them by now) #12, 14, 45, 74, 106, 114, 115, 116, 165, 182, 191, 192, 194, 195, 196, 205, 238, 245 are pirate MMC3 clones (interestingly 196 seems to be used for hacks where the protagonist is now Mario) #150 is some invalid Sachen thing apparently #151 is invalid, but used for VRC1 on VS System
from meowlauncher import input_metadata #Stuff that goes in the Atari joystick port, shared across most Atari systems joystick = input_metadata.NormalController() joystick.dpads = 1 joystick.face_buttons = 1 boostergrip = input_metadata.NormalController() boostergrip.dpads = 1 boostergrip.face_buttons = 3 paddle = input_metadata.Paddle() #Note that this is 2 paddles per port paddle.buttons = 2 keypad = input_metadata.Keypad() keypad.keys = 12 compumate = input_metadata.Keyboard() compumate.keys = 42 mindlink = input_metadata.Biological() driving_controller = input_metadata.SteeringWheel() atari_st_mouse = input_metadata.Mouse() atari_st_mouse.buttons = 2 xegs_gun = input_metadata.LightGun() xegs_gun.buttons = 1
from meowlauncher.games.roms.rom_game import ROMGame from meowlauncher.metadata import Metadata _licensee_codes = load_dict(None, 'sega_licensee_codes') class SaturnPeripheral(Enum): StandardController = auto() AnalogController = auto() #Or "3D Control Pad" if you prefer LightGun = auto() Keyboard = auto() Mouse = auto() Wheel = auto() _standard_controller = input_metadata.NormalController() _standard_controller.face_buttons = 6 # A B C X Y Z #yeah I had to count them because I have 0 brain cells sorry _standard_controller.shoulder_buttons = 2 #L R _standard_controller.dpads = 1 _analog_controller = input_metadata.NormalController() _analog_controller.face_buttons = 6 # A B C X Y Z _analog_controller.analog_triggers = 2 _analog_controller.analog_sticks = 1 _analog_controller.dpads = 1 _mission_stick_main_part = input_metadata.NormalController() _mission_stick_main_part.analog_sticks = 1 _mission_stick_main_part.face_buttons = 10 #The usual + L and R are located there instead of what would be considered a shoulder button, plus 2 extra on the stick _throttle_wheel = input_metadata.Dial() _mission_stick = input_metadata.CombinedController(
def add_sms_gg_software_list_info(software: 'Software', metadata: 'Metadata'): software.add_standard_metadata(metadata) usage = software.infos.get('usage') if usage == 'Only runs with PAL/50Hz drivers, e.g. smspal': metadata.specific_info['TV Type'] = TVSystem.PAL elif usage in {'Input works only with drivers of Japanese region, e.g. sms1kr,smsj', 'Only runs with certain drivers, e.g. smsj - others show SOFTWARE ERROR'}: metadata.specific_info['Japanese Only?'] = True elif usage == 'Video mode is correct only on SMS 2 drivers, e.g. smspal': metadata.specific_info['SMS2 Only?'] = True elif usage == 'Video only works correctly on drivers with SMS1 VDP, e.g. smsj': metadata.specific_info['SMS1 Only?'] = True else: metadata.add_notes(usage) #Other usage strings: #To play in 3-D on SMS1, hold buttons 1 and 2 while powering up the system. metadata.save_type = SaveType.Cart if software.get_part_feature('battery') == 'yes' else SaveType.Nothing slot = software.get_part_feature('slot') if slot == 'codemasters': metadata.specific_info['Mapper'] = 'Codemasters' elif slot == 'eeprom': metadata.specific_info['Mapper'] = 'EEPROM' #Is this really describable as a "mapper"? metadata.save_type = SaveType.Cart elif slot == '4pak': metadata.specific_info['Mapper'] = '4 Pak' elif slot == 'hicom': metadata.specific_info['Mapper'] = 'Hi-Com' elif slot == 'korean': metadata.specific_info['Mapper'] = 'Korean' elif slot == 'korean_nb': metadata.specific_info['Mapper'] = 'Korean Unbanked' elif slot == 'zemina': metadata.specific_info['Mapper'] = 'Zemina' elif slot == 'janggun': metadata.specific_info['Mapper'] = 'Janggun' elif slot == 'nemesis': metadata.specific_info['Mapper'] = 'Nemesis' elif slot == 'seojin': metadata.specific_info['Mapper'] = 'Seo Jin' if metadata.platform == 'Master System': builtin_gamepad = input_metadata.NormalController() builtin_gamepad.dpads = 1 builtin_gamepad.face_buttons = 2 controller_1 = software.get_shared_feature('ctrl1_default') #ctrl2_default is only ever equal to ctrl1_default when it is present, so ignore it for our purposes #Note that this doesn't actually tell us about games that _support_ given peripherals, just what games need them peripheral = SMSPeripheral.StandardController #All of these peripherals have 2 buttons as well? if controller_1 == 'graphic': peripheral = SMSPeripheral.Tablet metadata.input_info.add_option(input_metadata.Touchscreen()) elif controller_1 == 'lphaser': peripheral = SMSPeripheral.Lightgun light_phaser = input_metadata.LightGun() light_phaser.buttons = 1 metadata.input_info.add_option(light_phaser) elif controller_1 == 'paddle': peripheral = SMSPeripheral.Paddle paddle = input_metadata.Paddle() paddle.buttons = 2 metadata.input_info.add_option(paddle) elif controller_1 == 'sportspad': peripheral = SMSPeripheral.SportsPad sports_pad = input_metadata.Trackball() sports_pad.buttons = 2 metadata.input_info.add_option(sports_pad) else: #Not sure if this is an option for games that use lightgun/paddle/etc? I'll assume it's not metadata.input_info.add_option(builtin_gamepad) metadata.specific_info['Peripheral'] = peripheral
from meowlauncher import input_metadata controller = input_metadata.NormalController() controller.dpads = 1 controller.face_buttons = 4 #also Select + Start controller.shoulder_buttons = 2 mouse = input_metadata.Mouse() mouse.buttons = 2 gun = input_metadata.LightGun() #pew pew gun.buttons = 2 #Also pause and turbo pachinko = input_metadata.Paddle() pachinko.buttons = 1 #Other controllers: Miracle Piano (same as NES?) #Stuff not available as MAME slot device: That horse racing numpad thingo #Barcode Battler goes in the controller slot but from what I can tell it's not really a controller?
def add_input_info(game: 'MAMEGame') -> None: game.metadata.input_info.set_inited() if game.machine.input_element is None: #Seems like this doesn't actually happen if main_config.debug: print('Oi m8', game.machine.basename, '/', game.machine.name, 'has no input') return controller = input_metadata.CombinedController() has_normal_input = False has_added_vii_motion_controls = False normal_input = input_metadata.NormalController() has_control_elements = False for control in game.machine.input_element.iterfind('control'): has_control_elements = True buttons = int(control.attrib.get('buttons', 0)) if control.attrib.get('player', '1') != '1': #I care not for these "other people" and "social interaction" concepts #Anyway, this would only matter for stuff where player 2 has a different control scheme like Lucky & Wild, and... not sure what I'm gonna do about that, because we wanna avoid doubling up on input types where number of players > 1, and then that seems to be correct anyway continue #Still kinda feel like this is messy but ehhh #Input metadata will probably never be perfect, MAME -listxml outputs things for a different purpose really, it just be like that sometimes #I wonder if I'd be better off making some kind of controls.ini file myself input_type = control.attrib['type'] if input_type == 'only_buttons': has_normal_input = True normal_input.face_buttons += buttons elif input_type == 'joy': has_normal_input = True normal_input.face_buttons += buttons normal_input.dpads += 1 elif input_type == 'doublejoy': has_normal_input = True normal_input.face_buttons += buttons normal_input.dpads += 2 elif input_type == 'triplejoy': has_normal_input = True normal_input.face_buttons += buttons normal_input.dpads += 3 elif input_type == 'paddle': if game.metadata.genre == 'Driving': #Yeah this looks weird and hardcody and dodgy but am I wrong if buttons > 0: has_normal_input = True normal_input.face_buttons += buttons controller.components.append(input_metadata.SteeringWheel()) elif game.machine.basename == 'vii': #Uses 3 "paddle" inputs to represent 3-axis motion and I guess I'll have to deal with that if not has_added_vii_motion_controls: controller.components.append(input_metadata.MotionControls()) has_added_vii_motion_controls = True else: paddle = input_metadata.Paddle() paddle.buttons = buttons controller.components.append(paddle) elif input_type == 'stick': has_normal_input = True normal_input.analog_sticks += 1 normal_input.face_buttons += buttons elif input_type == 'pedal': if buttons > 0: has_normal_input = True normal_input.face_buttons += buttons pedal = input_metadata.Pedal() controller.components.append(pedal) elif input_type == 'lightgun': #TODO: See if we can be clever and detect if this is actually a touchscreen, like platform = handheld or something light_gun = input_metadata.LightGun() light_gun.buttons = buttons controller.components.append(light_gun) elif input_type == 'positional': #What _is_ a positional exactly positional = input_metadata.Positional() controller.components.append(positional) elif input_type == 'dial': dial = input_metadata.Dial() dial.buttons = buttons controller.components.append(dial) elif input_type == 'trackball': trackball = input_metadata.Trackball() trackball.buttons = buttons controller.components.append(trackball) elif input_type == 'mouse': mouse = input_metadata.Mouse() mouse.buttons = buttons controller.components.append(mouse) elif input_type == 'keypad': keypad = input_metadata.Keypad() keypad.keys = buttons controller.components.append(keypad) elif input_type == 'keyboard': keyboard = input_metadata.Keyboard() keyboard.keys = buttons controller.components.append(keyboard) elif input_type == 'mahjong': mahjong = input_metadata.Mahjong() mahjong.buttons = buttons controller.components.append(mahjong) elif input_type == 'hanafuda': hanafuda = input_metadata.Hanafuda() hanafuda.buttons = buttons controller.components.append(hanafuda) elif input_type == 'gambling': gambling = input_metadata.Gambling() gambling.buttons = buttons controller.components.append(gambling) else: if buttons: description = 'Custom input device with {0}'.format(pluralize(buttons, 'button')) else: description = 'Custom input device' controller.components.append(input_metadata.Custom(description)) if has_normal_input: controller.components.append(normal_input) if not has_control_elements: #Sometimes you get some games with 1 or more players, but no control type defined. This usually happens with #pinball games and weird stuff like a clock, but also some genuine games like Crazy Fight that are more or less #playable just fine, so we'll leave them in if game.machine.number_of_players > 0: game.metadata.input_info.add_option(input_metadata.Custom('Unknown input device')) return game.metadata.input_info.add_option(controller)