mirror of
https://github.com/gryf/fs-uae-wrapper.git
synced 2025-12-18 20:10:26 +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
|
- cd32
|
||||||
- archive
|
- archive
|
||||||
- savestate
|
- savestate
|
||||||
|
- whdload
|
||||||
|
|
||||||
plain
|
plain
|
||||||
-----
|
-----
|
||||||
@@ -323,6 +324,10 @@ Options used:
|
|||||||
* ``wrapper_whdload_base`` (required) path to the whdload base system. Usually
|
* ``wrapper_whdload_base`` (required) path to the whdload base system. Usually
|
||||||
it's minimal system containing at least whdload executables in C, and config
|
it's minimal system containing at least whdload executables in C, and config
|
||||||
in S. Read on below for further details.
|
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
|
* ``wrapper_archive`` (optional) path to the whdload archive, defaults to same
|
||||||
name as configuration file with some detected archive extension. Note, that
|
name as configuration file with some detected archive extension. Note, that
|
||||||
name is case sensitive
|
name is case sensitive
|
||||||
@@ -336,19 +341,69 @@ internet).
|
|||||||
Base image
|
Base image
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
|
||||||
To make it work, first the minimal system archive need to be prepared. There
|
To make it work, first the absolute minimal image need to contain following
|
||||||
are few dependences to be included in such small system:
|
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
|
- `WHDLoad`_ 18.9
|
||||||
- `uaequit`_
|
|
||||||
- `SetPatch`_ 43.6
|
- `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
|
- `kgiconload`_ - tool for reading icon and executing *default tool* with
|
||||||
optionally defined tool types as parameters (in this case: WHDLoad)
|
optionally defined tool types as parameters (in this case: WHDLoad)
|
||||||
- `SKick`_ optionally - for kickstart relocations. Also images of corresponding
|
- `SKick`_ optionally - for kickstart relocations. Also images of corresponding
|
||||||
kickstart ROM images will be needed.
|
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:
|
Now, the tree for the minimal image could look like that:
|
||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
@@ -369,7 +424,9 @@ Now, the tree for the minimal image could look like that:
|
|||||||
└── WHDLoad.prefs
|
└── WHDLoad.prefs
|
||||||
|
|
||||||
to use relocation tables you'll need to place ``Kickstarts`` drawer into Devs
|
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::
|
.. 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
|
/tmp/base.tgz .``, ``tar jcf /tmp/base.tar.bz2 .``. It should work with all
|
||||||
mentioned at the beginning of this document archivers.
|
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
|
``S/whdload-startup`` is executed, which will be created by fs-uae-warpper
|
||||||
before execution by fs-uae.
|
before execution by fs-uae.
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ class Base(object):
|
|||||||
"""execute fs-uae"""
|
"""execute fs-uae"""
|
||||||
curdir = os.path.abspath('.')
|
curdir = os.path.abspath('.')
|
||||||
os.chdir(self.dir)
|
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)
|
os.chdir(curdir)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ from fs_uae_wrapper import path
|
|||||||
|
|
||||||
class Archive(object):
|
class Archive(object):
|
||||||
"""Base class for archive support"""
|
"""Base class for archive support"""
|
||||||
ADD = ['a']
|
ADD = ('a',)
|
||||||
EXTRACT = ['x']
|
EXTRACT = ('x',)
|
||||||
ARCH = 'false'
|
ARCH = 'false'
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -27,8 +27,8 @@ class Archive(object):
|
|||||||
files = files if files else ['.']
|
files = files if files else ['.']
|
||||||
logging.debug("Calling `%s %s %s %s'.", self._compress,
|
logging.debug("Calling `%s %s %s %s'.", self._compress,
|
||||||
" ".join(self.ADD), arch_name, " ".join(files))
|
" ".join(self.ADD), arch_name, " ".join(files))
|
||||||
result = subprocess.call([self._compress] + self.ADD + [arch_name]
|
result = subprocess.call([self._compress, *self.ADD, arch_name,
|
||||||
+ files)
|
*files])
|
||||||
if result != 0:
|
if result != 0:
|
||||||
logging.error("Unable to create archive `%s'.", arch_name)
|
logging.error("Unable to create archive `%s'.", arch_name)
|
||||||
return False
|
return False
|
||||||
@@ -44,8 +44,7 @@ class Archive(object):
|
|||||||
|
|
||||||
logging.debug("Calling `%s %s %s'.", self._compress,
|
logging.debug("Calling `%s %s %s'.", self._compress,
|
||||||
" ".join(self.ADD), arch_name)
|
" ".join(self.ADD), arch_name)
|
||||||
result = subprocess.call([self._decompress] + self.EXTRACT +
|
result = subprocess.call([self._decompress, *self.EXTRACT, arch_name])
|
||||||
[arch_name])
|
|
||||||
if result != 0:
|
if result != 0:
|
||||||
logging.error("Unable to extract archive `%s'.", arch_name)
|
logging.error("Unable to extract archive `%s'.", arch_name)
|
||||||
return False
|
return False
|
||||||
@@ -53,16 +52,16 @@ class Archive(object):
|
|||||||
|
|
||||||
|
|
||||||
class TarArchive(Archive):
|
class TarArchive(Archive):
|
||||||
ADD = ['cf']
|
ADD = ('cf',)
|
||||||
EXTRACT = ['xf']
|
EXTRACT = ('xf',)
|
||||||
ARCH = 'tar'
|
ARCH = 'tar'
|
||||||
|
|
||||||
def create(self, arch_name, files=None):
|
def create(self, arch_name, files=None):
|
||||||
files = files if files else sorted(os.listdir('.'))
|
files = files if files else sorted(os.listdir('.'))
|
||||||
logging.debug("Calling `%s %s %s %s'.", self._compress,
|
logging.debug("Calling `%s %s %s %s'.", self._compress,
|
||||||
" ".join(self.ADD), arch_name, " ".join(files))
|
" ".join(self.ADD), arch_name, " ".join(files))
|
||||||
result = subprocess.call([self._compress] + self.ADD + [arch_name] +
|
result = subprocess.call([self._compress, *self.ADD, arch_name,
|
||||||
files)
|
*files])
|
||||||
if result != 0:
|
if result != 0:
|
||||||
logging.error("Unable to create archive `%s'.", arch_name)
|
logging.error("Unable to create archive `%s'.", arch_name)
|
||||||
return False
|
return False
|
||||||
@@ -70,15 +69,15 @@ class TarArchive(Archive):
|
|||||||
|
|
||||||
|
|
||||||
class TarGzipArchive(TarArchive):
|
class TarGzipArchive(TarArchive):
|
||||||
ADD = ['zcf']
|
ADD = ('zcf',)
|
||||||
|
|
||||||
|
|
||||||
class TarBzip2Archive(TarArchive):
|
class TarBzip2Archive(TarArchive):
|
||||||
ADD = ['jcf']
|
ADD = ('jcf',)
|
||||||
|
|
||||||
|
|
||||||
class TarXzArchive(TarArchive):
|
class TarXzArchive(TarArchive):
|
||||||
ADD = ['Jcf']
|
ADD = ('Jcf',)
|
||||||
|
|
||||||
|
|
||||||
class LhaArchive(Archive):
|
class LhaArchive(Archive):
|
||||||
@@ -86,8 +85,8 @@ class LhaArchive(Archive):
|
|||||||
|
|
||||||
|
|
||||||
class ZipArchive(Archive):
|
class ZipArchive(Archive):
|
||||||
ADD = ['a', '-tzip']
|
ADD = ('a', '-tzip')
|
||||||
ARCH = ['7z', 'zip']
|
ARCH = ('7z', 'zip')
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(ZipArchive, self).__init__()
|
super(ZipArchive, self).__init__()
|
||||||
@@ -102,7 +101,7 @@ class SevenZArchive(Archive):
|
|||||||
|
|
||||||
|
|
||||||
class LzxArchive(Archive):
|
class LzxArchive(Archive):
|
||||||
EXTRACT = ['-x']
|
EXTRACT = ('-x',)
|
||||||
ARCH = 'unlzx'
|
ARCH = 'unlzx'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -113,7 +112,7 @@ class LzxArchive(Archive):
|
|||||||
|
|
||||||
|
|
||||||
class RarArchive(Archive):
|
class RarArchive(Archive):
|
||||||
ARCH = ['rar', 'unrar']
|
ARCH = ('rar', 'unrar')
|
||||||
|
|
||||||
def create(self, arch_name, files=None):
|
def create(self, arch_name, files=None):
|
||||||
files = files if files else sorted(os.listdir('.'))
|
files = files if files else sorted(os.listdir('.'))
|
||||||
@@ -124,8 +123,8 @@ class RarArchive(Archive):
|
|||||||
|
|
||||||
logging.debug("Calling `%s %s %s %s'.", self._compress,
|
logging.debug("Calling `%s %s %s %s'.", self._compress,
|
||||||
" ".join(self.ADD), arch_name, " ".join(files))
|
" ".join(self.ADD), arch_name, " ".join(files))
|
||||||
result = subprocess.call([self._compress] + self.ADD + [arch_name] +
|
result = subprocess.call([self._compress, *self.ADD, arch_name,
|
||||||
files)
|
*files])
|
||||||
if result != 0:
|
if result != 0:
|
||||||
logging.error("Unable to create archive `%s'.", arch_name)
|
logging.error("Unable to create archive `%s'.", arch_name)
|
||||||
return False
|
return False
|
||||||
@@ -134,7 +133,7 @@ class RarArchive(Archive):
|
|||||||
|
|
||||||
class Archivers(object):
|
class Archivers(object):
|
||||||
"""Archivers class"""
|
"""Archivers class"""
|
||||||
archivers = [{'arch': TarArchive, 'name': 'tar', 'ext': ['tar']},
|
archivers = ({'arch': TarArchive, 'name': 'tar', 'ext': ['tar']},
|
||||||
{'arch': TarGzipArchive, 'name': 'tgz',
|
{'arch': TarGzipArchive, 'name': 'tgz',
|
||||||
'ext': ['tar.gz', 'tgz']},
|
'ext': ['tar.gz', 'tgz']},
|
||||||
{'arch': TarBzip2Archive, 'name': 'tar.bz2',
|
{'arch': TarBzip2Archive, 'name': 'tar.bz2',
|
||||||
@@ -144,7 +143,7 @@ class Archivers(object):
|
|||||||
{'arch': SevenZArchive, 'name': '7z', 'ext': ['7z']},
|
{'arch': SevenZArchive, 'name': '7z', 'ext': ['7z']},
|
||||||
{'arch': ZipArchive, 'name': 'zip', 'ext': ['zip']},
|
{'arch': ZipArchive, 'name': 'zip', 'ext': ['zip']},
|
||||||
{'arch': LhaArchive, 'name': 'lha', 'ext': ['lha', 'lzh']},
|
{'arch': LhaArchive, 'name': 'lha', 'ext': ['lha', 'lzh']},
|
||||||
{'arch': LzxArchive, 'name': 'lzx', 'ext': ['lzx']}]
|
{'arch': LzxArchive, 'name': 'lzx', 'ext': ['lzx']})
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get(cls, extension):
|
def get(cls, extension):
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ class Wrapper(base.Base):
|
|||||||
|
|
||||||
def _run_emulator(self):
|
def _run_emulator(self):
|
||||||
"""execute fs-uae"""
|
"""execute fs-uae"""
|
||||||
utils.run_command(['fs-uae'] + [self.conf_file] +
|
utils.run_command(['fs-uae', self.conf_file,
|
||||||
self.fsuae_options.list())
|
*self.fsuae_options.list()])
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
"""Do the cleanup. Here - just do nothing"""
|
"""Do the cleanup. Here - just do nothing"""
|
||||||
|
|||||||
@@ -80,12 +80,20 @@ class Wrapper(base.ArchiveBase):
|
|||||||
# find slave name
|
# find slave name
|
||||||
slave_fname = None
|
slave_fname = None
|
||||||
slave_path = 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:
|
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
|
slave_path, slave_fname = os.path.normpath(root), fname
|
||||||
break
|
|
||||||
if slave_fname is None:
|
if slave_fname is None:
|
||||||
logging.error("Cannot find .slave file in archive.")
|
logging.error("Cannot find .slave file in archive.")
|
||||||
return False
|
return False
|
||||||
@@ -103,10 +111,26 @@ class Wrapper(base.ArchiveBase):
|
|||||||
"archive.", slave_fname)
|
"archive.", slave_fname)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Write startup file
|
# find proper way to handle slave
|
||||||
with open("S/whdload-startup", "w") as fobj:
|
# 1. check if there are user provided params
|
||||||
fobj.write(f"cd {slave_path}\n")
|
contents = f"cd {slave_path}\n"
|
||||||
fobj.write(f"C:kgiconload {icon_fname}\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)
|
os.chdir(curdir)
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -176,15 +176,58 @@ class TestWHDLoad(TestCase):
|
|||||||
wrapper = whdload.Wrapper('Config.fs-uae', utils.CmdOption(), {})
|
wrapper = whdload.Wrapper('Config.fs-uae', utils.CmdOption(), {})
|
||||||
self.assertFalse(wrapper._find_slave())
|
self.assertFalse(wrapper._find_slave())
|
||||||
|
|
||||||
@mock.patch('builtins.open')
|
|
||||||
@mock.patch('os.listdir')
|
@mock.patch('os.listdir')
|
||||||
@mock.patch('os.walk')
|
@mock.patch('os.walk')
|
||||||
@mock.patch('os.chdir')
|
@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')
|
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)]
|
('./game', (), contents)]
|
||||||
listdir.return_value = contents
|
listdir.return_value = contents
|
||||||
wrapper = whdload.Wrapper('Config.fs-uae', utils.CmdOption(), {})
|
wrapper = whdload.Wrapper('Config.fs-uae', utils.CmdOption(), {})
|
||||||
self.assertTrue(wrapper._find_slave())
|
with mock.patch('builtins.open', _open):
|
||||||
bopen.assert_called_once()
|
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