def add_pet_custom_info(game: 'ROMGame'): software = game.get_software_list_entry() if software: add_generic_software_info(software, game.metadata) #Usage strings in pet_rom: #Requires BASIC 2 (works on pet2001n). Enter 'SYS 37000' to run #SYS38000 keyboard = input_metadata.Keyboard() keyboard.keys = 74 game.metadata.input_info.add_option(keyboard) #Don't know about joysticks and I know of no software that uses them for tag in game.filename_tags: #(2001, 3008, 3016, 3032, 3032B, 4016, 4032, 4032B, 8032, 8096, 8296, SuperPET) if (tag[0] == '(' and tag[-1] == ')') or (tag[0] == '[' and tag[-1] == ']'): tag = tag[1:-1] for model in ('3008', '3016', '3032', '3032B', '4016', '4032', '4032B', '8032', '8096', '8296', 'SuperPET'): if tag in (model, 'CBM %s' % model, 'CBM%s' % model, 'PET %s' % model, 'PET%s' % model): game.metadata.specific_info['Machine'] = model continue if tag in {'PET 2001', 'PET2001', 'CBM 2001', 'CBM2001'}: #We don't search for just "(2001)" in case that's used to denote the year game.metadata.specific_info['Machine'] = '2001' continue for ram in (8, 16, 32, 96, 128): if tag.lower() in ('%dk ram' % ram, '%dkb ram' % ram): game.metadata.specific_info['Minimum RAM'] = ram continue
def add_metadata(self) -> None: self.metadata.input_info.add_option( [input_metadata.Mouse(), input_metadata.Keyboard()] ) #Can use gamepad if you enable it, but I guess to add that as input_info I'd have to know exactly how many buttons and sticks etc it uses self.metadata.save_type = SaveType.Internal #Saves to your own dang computer so I guess that counts self.metadata.categories = ('Games', ) #Safe to assume this by default if self.options.get('gameid') == 'agi-fanmade': self.metadata.categories = ('Homebrew', ) #genre/subgenre is _probably_ always point and click adventure, but maybe not? (Plumbers is arguably a visual novel (don't @ me), and there's something about some casino card games in the list of supported games) #Would be nice to set things like developer/publisher/year but can't really do that unfortunately #Let series and series_index be detected by series_detect engine_id = self.options.get('engineid') self.metadata.specific_info['Engine'] = self._engine_list_to_use().get( engine_id) extra = self.options.get('extra') if extra: self.metadata.specific_info[ 'Version'] = extra #Hmm, I guess that'd be how we should use this properly… if 'demo' in extra.lower(): #Keeping the category names consistent with everything else here, though people might like to call it "Demos" or whatever instead and technically there's no reason why we can't do that and this should be an option and I will put this ramble here to remind myself to make it an option eventually self.metadata.categories = ('Trials', ) if main_config.use_original_platform: platform = self.options.get('platform') if platform: self.metadata.platform = format_platform(platform) if platform == 'amiga' and extra == 'CD32': self.metadata.platform = 'Amiga CD32' language_code = self.options.get('language') if language_code: if language_code == 'br': language = get_language_by_short_code('Pt-Br') elif language_code == 'se': #…That's the region code for Sweden, not the language code for Swedish, so that's odd but that's how it ends up being language = get_language_by_short_code('Sv') else: language = get_language_by_short_code(language_code, case_insensitive=True) if language: self.metadata.languages = [language] path: Optional[str] = self.options.get('path') if path: if os.path.isdir(path): icon = look_for_icon_in_folder(Path(path)) if icon: self.metadata.images['Icon'] = icon else: if main_config.debug: print('Aaaa!', self.name, self.game_id, path, 'does not exist') else: if main_config.debug: print('Wait what?', self.name, self.game_id, 'has no path')
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_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_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_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
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 cx22_trackball = input_metadata.Trackball() cx22_trackball.buttons = 1 #Physically 2, but functionally 1 (they are there to be ambidextrous)
_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': metadata.input_info.add_option(_analog_controller) metadata.specific_info['Uses 3D Control Pad?'] = True elif peripheral == 'A':
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)