Ejemplo n.º 1
0
class Xqemu(object):
	def __init__(self):
		self._p = QtCore.QProcess()
		self._qmp = None

	@staticmethod
	def generateControllerArg(settings):
		def genArg(settings, name, port):
			arg = {'Not connected': '',
			 'Keyboard': 'usb-xbox-gamepad',
			 'Gamepad #0': 'usb-xbox-gamepad-sdl,index=0',
			 'Gamepad #1': 'usb-xbox-gamepad-sdl,index=1',
			 'Gamepad #2': 'usb-xbox-gamepad-sdl,index=2',
			 'Gamepad #3': 'usb-xbox-gamepad-sdl,index=3'}.get(settings.settings[name], '')
			if arg is not '':
				return ['-device', 'usb-hub,port=' + str(port), '-device'] + [arg + ',port=' + str(port) + ".1"]
			return []

		args = []
		for controller in zip([3, 4, 1, 2], ['controller_one', 'controller_two', 'controller_three', 'controller_four']):
			args += genArg(settings, controller[1], controller[0])
		return args

	@staticmethod
	def generateXmuArg(settings, skipPathChecks):
		def check_path(path):
			if not skipPathChecks:
				if not os.path.exists(path) or os.path.isdir(path):
					raise Exception('File %s could not be found!' % path)

		def escape_path(path):
			return path.replace(',', ',,')

		def genArg(settings, name, port):
			port_arr = ['controller_three', 'controller_four', 'controller_one', 'controller_two']
			if settings.settings[name] is not '' and settings.settings[port_arr[int(port[:1]) - 1]] != 'Not connected':
				check_path(settings.settings[name])
				return ['-drive', 'if=none,id=' + name + ',file=' + escape_path(settings.settings[name]),
						'-device', 'usb-storage,drive=' + name + ',port=' + port]
			return []

		args = []
		for xmu in zip([1, 2, 3, 4], [3, 4, 1, 2]):
			args += genArg(settings, 'xmu_' + str(xmu[0]) + 'a_path', str(xmu[1]) + '.2')
			args += genArg(settings, 'xmu_' + str(xmu[0]) + 'b_path', str(xmu[1]) + '.3')
		return args

	@staticmethod
	def generateLaunchCmd(settings, skipPathChecks=False):
		def check_path(path):
			if not skipPathChecks:
				if not os.path.exists(path) or os.path.isdir(path):
					raise Exception('File %s could not be found!' % path)

		def escape_path(path):
			return path.replace(',', ',,')

		xqemu_path = settings.settings['xqemu_path']
		check_path(xqemu_path)
		mcpx_path = settings.settings['mcpx_path']
		check_path(mcpx_path)
		mcpx_path_arg = escape_path(mcpx_path)
		flash_path = settings.settings['flash_path']
		check_path(flash_path)
		flash_path_arg = escape_path(flash_path)
		hdd_path = settings.settings['hdd_path']
		check_path(hdd_path)
		hdd_path_arg = escape_path(hdd_path)
		short_anim_arg = ',short_animation' if settings.settings['short_anim'] else ''
		hdd_lock_arg = ',locked' if settings.settings['hdd_locked'] else ''
		sys_memory = settings.settings['sys_memory'].split(' ')[0]+'M'
		accel_arg = ',accel=kvm:hax:whpx,kernel_irqchip=off' if settings.settings['use_accelerator'] else ''
		dvd_path_arg = ''
		if settings.settings['dvd_present']:
			check_path(settings.settings['dvd_path'])
			dvd_path_arg = ',file=' + escape_path(settings.settings['dvd_path'])

		extra_args = [x for x in settings.settings['extra_args'].split(' ') if x is not '']

		# Build qemu launch cmd
		cmd = [xqemu_path,
		       '-cpu','pentium3',
		       '-machine','xbox%(accel_arg)s,bootrom=%(mcpx_path_arg)s%(short_anim_arg)s' % locals(),
		       '-m', '%(sys_memory)s' % locals(),
		       '-bios', '%(flash_path_arg)s' % locals(),
		       '-drive','file=%(hdd_path_arg)s,index=0,media=disk%(hdd_lock_arg)s' % locals(),
		       '-drive','index=1,media=cdrom%(dvd_path_arg)s' % locals(),
		       '-qmp','tcp:localhost:4444,server,nowait',
		       '-display','sdl']

		cmd += Xqemu.generateControllerArg(settings)
		cmd += Xqemu.generateXmuArg(settings, skipPathChecks)

		if settings.settings['gdb_enabled']:
			cmd.append('-gdb')
			cmd.append('tcp::' + settings.settings['gdb_port'])
			if settings.settings['gdb_wait']:
				cmd.append('-S')

		cmd += extra_args

		return cmd

	@staticmethod
	def launchCmdToString(cmd):
		# Attempt to interpret the constructed command line
		cmd_escaped = []
		for cmd_part in cmd:
			if ' ' in cmd_part:
				cmd_escaped += ['"%s"' % cmd_part.replace('"', '\\"')]
			else:
				cmd_escaped += [cmd_part]

		return ' '.join(cmd_escaped)

	def start(self, settings):
		cmd = self.generateLaunchCmd(settings)
		cmd_string = self.launchCmdToString(cmd)

		print('Running: %s' % cmd_string)

		self._p.start(cmd_string)
		i = 0
		while True:
			print('Trying to connect %d' % i)
			if i > 0: time.sleep(1)
			try:
				self._qmp = QEMUMonitorProtocol(('localhost', 4444))
				self._qmp.connect()
			except Exception as e:
				# If XQEMU quits, we abort the loop
				if self._p.waitForFinished(1):
					return

				if i > 4:
					raise
				else:
					i += 1
					continue
			break

	def stop(self):
		if self.isRunning:
			self._p.terminate()

	def run_cmd(self, cmd):
		if type(cmd) is str:
			cmd = {
			    "execute": cmd, 
			    "arguments": {}
			}
		resp = self._qmp.cmd_obj(cmd)
		if resp is None:
			raise Exception('Disconnected!')
		return resp

	def pause(self):
		return self.run_cmd('stop')

	def cont(self):
		return self.run_cmd('cont')

	def restart(self):
		return self.run_cmd('system_reset')

	def screenshot(self):
		cmd = {
		    "execute": "screendump", 
		    "arguments": {
		        "filename": "screenshot.ppm"
		    }
		}
		return self.run_cmd(cmd)

	def isPaused(self):
		resp = self.run_cmd('query-status')
		return resp['return']['status'] == 'paused'

	@property
	def isRunning(self):
		return self._p is not None and self._p.state() == QtCore.QProcess.Running
Ejemplo n.º 2
0
class Xqemu(object):
    def __init__(self):
        self._p = None
        self._qmp = None

    def start(self, settings):
        def check_path(path):
            if not os.path.exists(path) or os.path.isdir(path):
                raise Exception('File %s could not be found!' % path)

        xqemu_path = settings.settings['xqemu_path']
        check_path(xqemu_path)
        mcpx_path = settings.settings['mcpx_path']
        check_path(mcpx_path)
        flash_path = settings.settings['flash_path']
        check_path(flash_path)
        hdd_path = settings.settings['hdd_path']
        check_path(hdd_path)
        short_anim_arg = ',short_animation' if settings.settings[
            'short_anim'] else ''
        hdd_lock_arg = ',locked' if settings.settings['hdd_locked'] else ''

        dvd_path_arg = ''
        if settings.settings['dvd_present']:
            check_path(settings.settings['dvd_path'])
            dvd_path_arg = ',file=' + settings.settings['dvd_path']

        # Build qemu lunch cmd
        cmd = [
            xqemu_path, '-cpu', 'pentium3', '-machine',
            'xbox,bootrom=%(mcpx_path)s%(short_anim_arg)s' % locals(), '-m',
            '64', '-bios',
            '%(flash_path)s' % locals(), '-net', 'nic,model=nvnet', '-net',
            'user', '-drive',
            'file=%(hdd_path)s,index=0,media=disk%(hdd_lock_arg)s' % locals(),
            '-drive',
            'index=1,media=cdrom%(dvd_path_arg)s' % locals(), '-qmp',
            'tcp:localhost:4444,server,nowait'
        ]

        # Attempt to interpret the constructed command line
        cmd_escaped = []
        for cmd_part in cmd:
            if ' ' in cmd_part:
                cmd_escaped += ['"%s"' % cmd_part.replace('"', '\\"')]
            else:
                cmd_escaped += [cmd_part]
        print('Running: %s' % ' '.join(cmd_escaped))

        self._p = subprocess.Popen(cmd)
        i = 0
        while True:
            print('Trying to connect %d' % i)
            if i > 0: time.sleep(1)
            try:
                self._qmp = QEMUMonitorProtocol(('localhost', 4444))
                self._qmp.connect()
            except Exception as e:
                if i > 4:
                    raise
                else:
                    i += 1
                    continue
            break

    def stop(self):
        if self._p:
            self._p.terminate()
            self._p = None

    def run_cmd(self, cmd):
        if type(cmd) is str:
            cmd = {"execute": cmd, "arguments": {}}
        resp = self._qmp.cmd_obj(cmd)
        if resp is None:
            raise Exception('Disconnected!')
        return resp

    def pause(self):
        return self.run_cmd('stop')

    def cont(self):
        return self.run_cmd('cont')

    def restart(self):
        return self.run_cmd('system_reset')

    def screenshot(self):
        cmd = {
            "execute": "screendump",
            "arguments": {
                "filename": "screenshot.ppm"
            }
        }
        return self.run_cmd(cmd)

    def isPaused(self):
        resp = self.run_cmd('query-status')
        return resp['return']['status'] == 'paused'

    @property
    def isRunning(self):
        return self._p is not None  # FIXME: Check subproc state