1
0
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:
2024-09-14 10:53:58 +02:00
parent 7b40974779
commit 3b597e34ee
6 changed files with 166 additions and 43 deletions

View File

@@ -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.

View File

@@ -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

View File

@@ -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):

View File

@@ -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"""

View File

@@ -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

View File

@@ -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')