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 _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_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
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 cx22_trackball = input_metadata.Trackball() cx22_trackball.buttons = 1 #Physically 2, but functionally 1 (they are there to be ambidextrous) #No, but also yes megadrive_pad = input_metadata.NormalController() megadrive_pad.face_buttons = 3 megadrive_pad.dpads = 1
_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( [_mission_stick_main_part, _throttle_wheel]) _virtua_gun = input_metadata.LightGun() _virtua_gun.buttons = 1 #Also start and I dunno if offscreen shot would count as a button _keyboard = input_metadata.Keyboard() _keyboard.keys = 101 #Japan keyboard has 89 keys... bleh, it doesn't seem to say which keyboard it refers to _mouse = input_metadata.Mouse() _mouse.buttons = 3 def _parse_peripherals(metadata: 'Metadata', peripherals: str): for peripheral in peripherals: if peripheral == 'J': metadata.input_info.add_option(_standard_controller) elif peripheral == 'E':
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)