mirror of
https://github.com/gryf/fs-uae-wrapper.git
synced 2025-12-18 12:00:28 +01:00
Fix some lint errors and warnings
This commit is contained in:
71
README.rst
71
README.rst
@@ -137,6 +137,7 @@ Currently, couple of wrapper modules are available:
|
||||
- cd32
|
||||
- archive
|
||||
- savestate
|
||||
- whdload
|
||||
|
||||
plain
|
||||
-----
|
||||
@@ -323,6 +324,10 @@ Options used:
|
||||
* ``wrapper_whdload_base`` (required) path to the whdload base system. Usually
|
||||
it's minimal system containing at least whdload executables in C, and config
|
||||
in S. Read on below for further details.
|
||||
* ``wrapper_whdload_options`` (optional) this option will replace the line in
|
||||
``s:whdload-startup`` with specific ``whdload`` options for certain slave.
|
||||
For reference look at WHDLoad documentation and/or on ``s:WHDLoad.prefs``.
|
||||
Note, that ``Slave=`` option must not be used.
|
||||
* ``wrapper_archive`` (optional) path to the whdload archive, defaults to same
|
||||
name as configuration file with some detected archive extension. Note, that
|
||||
name is case sensitive
|
||||
@@ -336,19 +341,69 @@ internet).
|
||||
Base image
|
||||
~~~~~~~~~~
|
||||
|
||||
To make it work, first the minimal system archive need to be prepared. There
|
||||
are few dependences to be included in such small system:
|
||||
To make it work, first the absolute minimal image need to contain following
|
||||
structure:
|
||||
|
||||
.. code::
|
||||
.
|
||||
├── C
|
||||
│ ├── DIC
|
||||
│ ├── Execute
|
||||
│ ├── Patcher
|
||||
│ ├── RawDIC
|
||||
│ ├── SetPatch
|
||||
│ ├── WHDLoad
|
||||
│ └── WHDLoadCD32
|
||||
└── S
|
||||
├── startup-sequence
|
||||
└── WHDLoad.prefs
|
||||
|
||||
where the minimum dependences are:
|
||||
|
||||
- ``Excecute`` from your copy of Workbench
|
||||
- `WHDLoad`_ 18.9
|
||||
- `uaequit`_
|
||||
- `SetPatch`_ 43.6
|
||||
- ``Excecute``, ``Assign`` and whatever commands you'll be use in scripts from
|
||||
your copy of Workbench
|
||||
|
||||
and the ``S/startup-sequence`` should at east contain:
|
||||
|
||||
.. code::
|
||||
|
||||
setpatch QUIET
|
||||
|
||||
IF EXISTS S:whdload-startup
|
||||
Execute S:whdload-startup
|
||||
EndIF
|
||||
|
||||
To leverage more pleasant UX, additionally those bits should be installed (or -
|
||||
copied into base image filesystem):
|
||||
|
||||
- ``Assign`` and whatever commands you'll be use in scripts from your copy of
|
||||
- `uaequit`_ - this will allow to quit emulator, after quiting game
|
||||
Workbench
|
||||
- `kgiconload`_ - tool for reading icon and executing *default tool* with
|
||||
optionally defined tool types as parameters (in this case: WHDLoad)
|
||||
- `SKick`_ optionally - for kickstart relocations. Also images of corresponding
|
||||
kickstart ROM images will be needed.
|
||||
|
||||
|
||||
and then ``s/startup-sequence`` might looks a follows:
|
||||
|
||||
.. code::
|
||||
|
||||
Assign >NIL: ENV: RAM:
|
||||
Assign >NIL: T: RAM:
|
||||
|
||||
setpatch QUIET
|
||||
|
||||
IF EXISTS S:whdload-startup
|
||||
Execute S:whdload-startup
|
||||
EndIF
|
||||
|
||||
C:UAEquit
|
||||
|
||||
Creating base image archive
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Now, the tree for the minimal image could look like that:
|
||||
|
||||
.. code::
|
||||
@@ -369,7 +424,9 @@ Now, the tree for the minimal image could look like that:
|
||||
└── WHDLoad.prefs
|
||||
|
||||
to use relocation tables you'll need to place ``Kickstarts`` drawer into Devs
|
||||
drawer, so it'll looks like this:
|
||||
drawer. Also keep in mind, that corresponding kickstart rom images need to be
|
||||
placed there as well, otherwise it may or may not work. Structure looks like
|
||||
this:
|
||||
|
||||
.. code::
|
||||
.
|
||||
@@ -421,7 +478,7 @@ tar with different compressions: ``tar Jcf /tmp/base.tar.xz .``, ``tar zcf
|
||||
/tmp/base.tgz .``, ``tar jcf /tmp/base.tar.bz2 .``. It should work with all
|
||||
mentioned at the beginning of this document archivers.
|
||||
|
||||
Starting point is in ``S/startup-sequence`` file, where eventually
|
||||
Starting point is in ``S/startup-sequence`` file, where eventually
|
||||
``S/whdload-startup`` is executed, which will be created by fs-uae-warpper
|
||||
before execution by fs-uae.
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ class Base(object):
|
||||
"""execute fs-uae"""
|
||||
curdir = os.path.abspath('.')
|
||||
os.chdir(self.dir)
|
||||
utils.run_command(['fs-uae'] + self.fsuae_options.list())
|
||||
utils.run_command(['fs-uae', *self.fsuae_options.list()])
|
||||
os.chdir(curdir)
|
||||
return True
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ from fs_uae_wrapper import path
|
||||
|
||||
class Archive(object):
|
||||
"""Base class for archive support"""
|
||||
ADD = ['a']
|
||||
EXTRACT = ['x']
|
||||
ADD = ('a',)
|
||||
EXTRACT = ('x',)
|
||||
ARCH = 'false'
|
||||
|
||||
def __init__(self):
|
||||
@@ -27,8 +27,8 @@ class Archive(object):
|
||||
files = files if files else ['.']
|
||||
logging.debug("Calling `%s %s %s %s'.", self._compress,
|
||||
" ".join(self.ADD), arch_name, " ".join(files))
|
||||
result = subprocess.call([self._compress] + self.ADD + [arch_name]
|
||||
+ files)
|
||||
result = subprocess.call([self._compress, *self.ADD, arch_name,
|
||||
*files])
|
||||
if result != 0:
|
||||
logging.error("Unable to create archive `%s'.", arch_name)
|
||||
return False
|
||||
@@ -44,8 +44,7 @@ class Archive(object):
|
||||
|
||||
logging.debug("Calling `%s %s %s'.", self._compress,
|
||||
" ".join(self.ADD), arch_name)
|
||||
result = subprocess.call([self._decompress] + self.EXTRACT +
|
||||
[arch_name])
|
||||
result = subprocess.call([self._decompress, *self.EXTRACT, arch_name])
|
||||
if result != 0:
|
||||
logging.error("Unable to extract archive `%s'.", arch_name)
|
||||
return False
|
||||
@@ -53,16 +52,16 @@ class Archive(object):
|
||||
|
||||
|
||||
class TarArchive(Archive):
|
||||
ADD = ['cf']
|
||||
EXTRACT = ['xf']
|
||||
ADD = ('cf',)
|
||||
EXTRACT = ('xf',)
|
||||
ARCH = 'tar'
|
||||
|
||||
def create(self, arch_name, files=None):
|
||||
files = files if files else sorted(os.listdir('.'))
|
||||
logging.debug("Calling `%s %s %s %s'.", self._compress,
|
||||
" ".join(self.ADD), arch_name, " ".join(files))
|
||||
result = subprocess.call([self._compress] + self.ADD + [arch_name] +
|
||||
files)
|
||||
result = subprocess.call([self._compress, *self.ADD, arch_name,
|
||||
*files])
|
||||
if result != 0:
|
||||
logging.error("Unable to create archive `%s'.", arch_name)
|
||||
return False
|
||||
@@ -70,15 +69,15 @@ class TarArchive(Archive):
|
||||
|
||||
|
||||
class TarGzipArchive(TarArchive):
|
||||
ADD = ['zcf']
|
||||
ADD = ('zcf',)
|
||||
|
||||
|
||||
class TarBzip2Archive(TarArchive):
|
||||
ADD = ['jcf']
|
||||
ADD = ('jcf',)
|
||||
|
||||
|
||||
class TarXzArchive(TarArchive):
|
||||
ADD = ['Jcf']
|
||||
ADD = ('Jcf',)
|
||||
|
||||
|
||||
class LhaArchive(Archive):
|
||||
@@ -86,8 +85,8 @@ class LhaArchive(Archive):
|
||||
|
||||
|
||||
class ZipArchive(Archive):
|
||||
ADD = ['a', '-tzip']
|
||||
ARCH = ['7z', 'zip']
|
||||
ADD = ('a', '-tzip')
|
||||
ARCH = ('7z', 'zip')
|
||||
|
||||
def __init__(self):
|
||||
super(ZipArchive, self).__init__()
|
||||
@@ -102,7 +101,7 @@ class SevenZArchive(Archive):
|
||||
|
||||
|
||||
class LzxArchive(Archive):
|
||||
EXTRACT = ['-x']
|
||||
EXTRACT = ('-x',)
|
||||
ARCH = 'unlzx'
|
||||
|
||||
@classmethod
|
||||
@@ -113,7 +112,7 @@ class LzxArchive(Archive):
|
||||
|
||||
|
||||
class RarArchive(Archive):
|
||||
ARCH = ['rar', 'unrar']
|
||||
ARCH = ('rar', 'unrar')
|
||||
|
||||
def create(self, arch_name, files=None):
|
||||
files = files if files else sorted(os.listdir('.'))
|
||||
@@ -124,8 +123,8 @@ class RarArchive(Archive):
|
||||
|
||||
logging.debug("Calling `%s %s %s %s'.", self._compress,
|
||||
" ".join(self.ADD), arch_name, " ".join(files))
|
||||
result = subprocess.call([self._compress] + self.ADD + [arch_name] +
|
||||
files)
|
||||
result = subprocess.call([self._compress, *self.ADD, arch_name,
|
||||
*files])
|
||||
if result != 0:
|
||||
logging.error("Unable to create archive `%s'.", arch_name)
|
||||
return False
|
||||
@@ -134,7 +133,7 @@ class RarArchive(Archive):
|
||||
|
||||
class Archivers(object):
|
||||
"""Archivers class"""
|
||||
archivers = [{'arch': TarArchive, 'name': 'tar', 'ext': ['tar']},
|
||||
archivers = ({'arch': TarArchive, 'name': 'tar', 'ext': ['tar']},
|
||||
{'arch': TarGzipArchive, 'name': 'tgz',
|
||||
'ext': ['tar.gz', 'tgz']},
|
||||
{'arch': TarBzip2Archive, 'name': 'tar.bz2',
|
||||
@@ -144,7 +143,7 @@ class Archivers(object):
|
||||
{'arch': SevenZArchive, 'name': '7z', 'ext': ['7z']},
|
||||
{'arch': ZipArchive, 'name': 'zip', 'ext': ['zip']},
|
||||
{'arch': LhaArchive, 'name': 'lha', 'ext': ['lha', 'lzh']},
|
||||
{'arch': LzxArchive, 'name': 'lzx', 'ext': ['lzx']}]
|
||||
{'arch': LzxArchive, 'name': 'lzx', 'ext': ['lzx']})
|
||||
|
||||
@classmethod
|
||||
def get(cls, extension):
|
||||
|
||||
@@ -16,8 +16,8 @@ class Wrapper(base.Base):
|
||||
|
||||
def _run_emulator(self):
|
||||
"""execute fs-uae"""
|
||||
utils.run_command(['fs-uae'] + [self.conf_file] +
|
||||
self.fsuae_options.list())
|
||||
utils.run_command(['fs-uae', self.conf_file,
|
||||
*self.fsuae_options.list()])
|
||||
|
||||
def clean(self):
|
||||
"""Do the cleanup. Here - just do nothing"""
|
||||
|
||||
@@ -80,12 +80,20 @@ class Wrapper(base.ArchiveBase):
|
||||
# find slave name
|
||||
slave_fname = None
|
||||
slave_path = None
|
||||
case_insensitvie_map = {}
|
||||
|
||||
# build case insensitive map of paths and find the slave file
|
||||
for root, dirnames, fnames in os.walk('.'):
|
||||
for dirname in dirnames:
|
||||
full_path = os.path.normpath(os.path.join(root, dirname))
|
||||
case_insensitvie_map[full_path.lower()] = full_path
|
||||
|
||||
for root, dirs, fnames in os.walk('.'):
|
||||
for fname in fnames:
|
||||
if fname.lower().endswith('.slave'):
|
||||
full_path = os.path.normpath(os.path.join(root, fname))
|
||||
case_insensitvie_map[full_path.lower()] = full_path
|
||||
if not slave_fname and fname.lower().endswith('.slave'):
|
||||
slave_path, slave_fname = os.path.normpath(root), fname
|
||||
break
|
||||
|
||||
if slave_fname is None:
|
||||
logging.error("Cannot find .slave file in archive.")
|
||||
return False
|
||||
@@ -103,10 +111,26 @@ class Wrapper(base.ArchiveBase):
|
||||
"archive.", slave_fname)
|
||||
return False
|
||||
|
||||
# Write startup file
|
||||
with open("S/whdload-startup", "w") as fobj:
|
||||
fobj.write(f"cd {slave_path}\n")
|
||||
fobj.write(f"C:kgiconload {icon_fname}\n")
|
||||
# find proper way to handle slave
|
||||
# 1. check if there are user provided params
|
||||
contents = f"cd {slave_path}\n"
|
||||
if self.fsuae_options.get('wrapper_whdload_options'):
|
||||
contents = (f"{contents}"
|
||||
f"C:whdload "
|
||||
f"{self.fsuae_options['wrapper_whdload_options']} "
|
||||
f"Slave={slave_fname}\n")
|
||||
else:
|
||||
# no params, find if kgiconload is available
|
||||
if case_insensitvie_map.get('c/kgiconload'):
|
||||
contents = f"{contents}C:kgiconload {icon_fname}\n"
|
||||
else:
|
||||
# if not, just add common defaults
|
||||
contents = (f"{contents}C:whdload Preload "
|
||||
f"Slave={slave_fname}\n")
|
||||
|
||||
fname = os.path.join(case_insensitvie_map.get('s'), 'whdload-startup')
|
||||
with open(fname, "w") as fobj:
|
||||
fobj.write(contents)
|
||||
|
||||
os.chdir(curdir)
|
||||
return True
|
||||
|
||||
@@ -176,15 +176,58 @@ class TestWHDLoad(TestCase):
|
||||
wrapper = whdload.Wrapper('Config.fs-uae', utils.CmdOption(), {})
|
||||
self.assertFalse(wrapper._find_slave())
|
||||
|
||||
@mock.patch('builtins.open')
|
||||
@mock.patch('os.listdir')
|
||||
@mock.patch('os.walk')
|
||||
@mock.patch('os.chdir')
|
||||
def test_find_slave_success(self, chdir, walk, listdir, bopen):
|
||||
def test_find_slave_success(self, chdir, walk, listdir):
|
||||
contents = ('foo', 'bar', 'baz.slave', 'baz.info')
|
||||
walk.return_value = [(".", ('game'), ()),
|
||||
_open = mock.mock_open()
|
||||
walk.return_value = [(".", ('C', 'S', 'game'), ()),
|
||||
('./C', (), ('Assign', 'kgiconload')),
|
||||
('./S', (), ()),
|
||||
('./game', (), contents)]
|
||||
listdir.return_value = contents
|
||||
wrapper = whdload.Wrapper('Config.fs-uae', utils.CmdOption(), {})
|
||||
self.assertTrue(wrapper._find_slave())
|
||||
bopen.assert_called_once()
|
||||
with mock.patch('builtins.open', _open):
|
||||
self.assertTrue(wrapper._find_slave())
|
||||
handle = _open()
|
||||
handle.write.assert_called_once_with('cd game\n'
|
||||
'C:kgiconload baz.info\n')
|
||||
|
||||
@mock.patch('os.listdir')
|
||||
@mock.patch('os.walk')
|
||||
@mock.patch('os.chdir')
|
||||
def test_find_slave_minial(self, chdir, walk, listdir):
|
||||
contents = ('foo', 'bar', 'baz.slave', 'baz.info')
|
||||
_open = mock.mock_open()
|
||||
walk.return_value = [(".", ('C', 'S', 'game'), ()),
|
||||
('./C', (), ('Assign', 'WHDLoad')),
|
||||
('./S', (), ()),
|
||||
('./game', (), contents)]
|
||||
listdir.return_value = contents
|
||||
wrapper = whdload.Wrapper('Config.fs-uae', utils.CmdOption(), {})
|
||||
with mock.patch('builtins.open', _open):
|
||||
self.assertTrue(wrapper._find_slave())
|
||||
handle = _open()
|
||||
handle.write.assert_called_once_with('cd game\nC:whdload Preload '
|
||||
'Slave=baz.slave\n')
|
||||
|
||||
@mock.patch('os.listdir')
|
||||
@mock.patch('os.walk')
|
||||
@mock.patch('os.chdir')
|
||||
def test_find_custom_options(self, chdir, walk, listdir):
|
||||
contents = ('foo', 'bar', 'baz.slave', 'baz.info')
|
||||
_open = mock.mock_open()
|
||||
walk.return_value = [(".", ('C', 'S', 'game'), ()),
|
||||
('./C', (), ('Assign', 'WHDLoad')),
|
||||
('./S', (), ()),
|
||||
('./game', (), contents)]
|
||||
listdir.return_value = contents
|
||||
wrapper = whdload.Wrapper('Config.fs-uae', utils.CmdOption(), {})
|
||||
whdl_opts = 'Preload SplashDelay=0 MMU PAL'
|
||||
wrapper.fsuae_options['wrapper_whdload_options'] = whdl_opts
|
||||
with mock.patch('builtins.open', _open):
|
||||
self.assertTrue(wrapper._find_slave())
|
||||
handle = _open()
|
||||
handle.write.assert_called_once_with(f'cd game\nC:whdload {whdl_opts} '
|
||||
'Slave=baz.slave\n')
|
||||
|
||||
Reference in New Issue
Block a user