Skip to content

Commit

Permalink
Add the PadLeft/PadRight configuration parameters for skool2bin.py
Browse files Browse the repository at this point in the history
  • Loading branch information
skoolkid committed Aug 19, 2024
1 parent 3ac7a75 commit 3e03451
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 9 deletions.
2 changes: 2 additions & 0 deletions skoolkit/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@
'skool2bin': {
'Banks': (0, 'banks'),
'Data': (0, 'data'),
'PadLeft': (65536, ''),
'PadRight': (0, ''),
'Verbose': (0, 'verbose'),
'Warnings': (1, 'warn')
},
Expand Down
18 changes: 14 additions & 4 deletions skoolkit/skool2bin.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ def __str__(self):
return '{0:05} {0:04X} {1} {2:13} {3}'.format(self.real_address, self.marker, self.operation, suffix).rstrip()

class BinWriter:
def __init__(self, skoolfile, asm_mode=0, fix_mode=0, banks=False, start=-1, end=65537, data=False, verbose=False, warn=False):
def __init__(self, skoolfile, asm_mode=0, fix_mode=0, banks=False, start=-1, end=65537,
data=False, verbose=False, warn=False, pad_left=65536, pad_right=0):
if fix_mode > 2:
asm_mode = 3
elif asm_mode > 2:
Expand All @@ -66,6 +67,8 @@ def __init__(self, skoolfile, asm_mode=0, fix_mode=0, banks=False, start=-1, end
self.end = end
self.verbose = verbose
self.warn = warn
self.pad_left = pad_left
self.pad_right = pad_right
self.weights = {
'isub': (0, int(asm_mode > 0)),
'ssub': (0, 2 * int(asm_mode > 1)),
Expand Down Expand Up @@ -269,15 +272,22 @@ def write(self, binfile):
end_address = min(self.end, self.end_address)
base_address = min(base_address, end_address)
data = self.snapshot[base_address:end_address]
if self.pad_left < base_address:
data = [0] * (base_address - self.pad_left) + data
base_address = self.pad_left
if self.pad_right > end_address:
data += [0] * (self.pad_right - end_address)
end_address = self.pad_right
with open_file(binfile, 'wb') as f:
f.write(bytearray(data))
if binfile == '-':
binfile = 'stdout'
info("Wrote {}: start={}, end={}, size={}".format(binfile, base_address, end_address, len(data)))

def run(skoolfile, binfile, options):
def run(skoolfile, binfile, options, config):
binwriter = BinWriter(skoolfile, options.asm_mode, options.fix_mode, options.banks, options.start,
options.end, options.data, options.verbose, options.warn)
options.end, options.data, options.verbose, options.warn,
config['PadLeft'], config['PadRight'])
binwriter.write(binfile)

def main(args):
Expand Down Expand Up @@ -339,4 +349,4 @@ def main(args):
binfile = 'program.bin'
else:
binfile = basename(skoolfile) + '.bin'
run(skoolfile, binfile, namespace)
run(skoolfile, binfile, namespace, config)
2 changes: 2 additions & 0 deletions sphinx/source/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Changelog
* Added the ``--ini`` and ``--show-config`` options to :ref:`skool2bin.py` (for
setting the value of a configuration parameter and for showing all
configuration parameter values)
* Added support to :ref:`skool2bin.py` for padding the output with zeroes (as
specified by the ``PadLeft`` and ``PadRight`` configuration parameters)
* Fixed how the 'ADC A,*', 'SBC A,*', 'ADC HL,rr' and 'SBC HL,rr' instructions
affect the half-carry flag
* Fixed how 'BIT n,(IX/Y+d)' affects bits 3 and 5 of the flags in the C version
Expand Down
7 changes: 6 additions & 1 deletion sphinx/source/commands.rst
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,10 @@ configuration parameters are:
128K file (``1``), or don't (``0``, the default)
* ``Data`` - process :ref:`defb`, :ref:`defs` and :ref:`defw` directives
(``1``), or don't (``0``, the default)
* ``PadLeft`` - address at which to start padding the output on the left with
zeroes; the default value is ``65536``, which produces no padding
* ``PadRight`` - address at which to stop padding the output on the right with
zeroes; the default value is ``0``, which produces no padding
* ``Verbose`` - show info on each converted instruction (``1``), or don't
(``0``, the default)
* ``Warnings`` - show warnings (``1``, the default), or suppress them (``0``)
Expand All @@ -545,7 +549,8 @@ Configuration parameters may also be set on the command line by using the
| Version | Changes |
+=========+===================================================================+
| 9.4 | Configuration is read from `skoolkit.ini` if present; added the |
| | ``--ini`` and ``--show-config`` options |
| | ``--ini`` and ``--show-config`` options; added support for |
| | padding the output with zeroes |
+---------+-------------------------------------------------------------------+
| 9.1 | Added the ``--banks`` option |
+---------+-------------------------------------------------------------------+
Expand Down
4 changes: 4 additions & 0 deletions sphinx/source/man/skool2bin.py.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ configuration parameters are:
(``1``), or don't (``0``, the default).
:Data: Process ``@defb``, ``@defs`` and ``@defw`` directives (``1``), or
don't (``0``, the default).
:PadLeft: Address at which to start padding the output on the left with
zeroes. The default value is ``65536``, which produces no padding.
:PadRight: Address at which to stop padding the output on the right with
zeroes. The default value is ``0``, which produces no padding.
:Verbose: Show info on each converted instruction (``1``), or don't (``0``,
the default).
:Warnings: Show warnings (``1``, the default), or suppress them (``0``).
Expand Down
85 changes: 81 additions & 4 deletions tests/test_skool2bin.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def mock_config(name):
return {k: v[0] for k, v in COMMANDS[name].items()}

class MockBinWriter:
def __init__(self, skoolfile, asm_mode, fix_mode, banks, start, end, data, verbose, warn):
def __init__(self, skoolfile, asm_mode, fix_mode, banks, start, end, data, verbose, warn, pad_left, pad_right):
global mock_bin_writer
mock_bin_writer = self
self.skoolfile = skoolfile
Expand All @@ -21,13 +21,16 @@ def __init__(self, skoolfile, asm_mode, fix_mode, banks, start, end, data, verbo
self.data = data
self.verbose = verbose
self.warn = warn
self.pad_left = pad_left
self.pad_right = pad_right
self.binfile = None

def write(self, binfile):
self.binfile = binfile

class Skool2BinTest(SkoolKitTestCase):
def _check_values(self, skoolfile, binfile, asm_mode=0, fix_mode=0, banks=False, data=False, verbose=False, warn=True, start=-1, end=65537):
def _check_values(self, skoolfile, binfile, asm_mode=0, fix_mode=0, banks=False, data=False,
verbose=False, warn=True, start=-1, end=65537, pad_left=65536, pad_right=0):
self.assertEqual(mock_bin_writer.skoolfile, skoolfile)
self.assertEqual(mock_bin_writer.binfile, binfile)
self.assertEqual(mock_bin_writer.asm_mode, asm_mode)
Expand All @@ -38,6 +41,8 @@ def _check_values(self, skoolfile, binfile, asm_mode=0, fix_mode=0, banks=False,
self.assertIs(mock_bin_writer.warn, warn)
self.assertEqual(mock_bin_writer.start, start)
self.assertEqual(mock_bin_writer.end, end)
self.assertEqual(mock_bin_writer.pad_left, pad_left)
self.assertEqual(mock_bin_writer.pad_right, pad_right)

def test_no_arguments(self):
output, error = self.run_skool2bin(catch_exit=2)
Expand Down Expand Up @@ -86,6 +91,46 @@ def test_output_filename(self):
self.assertEqual(len(error), 0)
self.assertEqual(mock_bin_writer.binfile, binfile)

@patch.object(skool2bin, 'get_config', mock_config)
@patch.object(skool2bin, 'BinWriter', MockBinWriter)
def test_config_PadLeft_set_on_command_line(self):
skoolfile = 'in.skool'
binfile = 'out.bin'
self.run_skool2bin(f'-I PadLeft=16384 {skoolfile} {binfile}')
self._check_values(skoolfile, binfile, pad_left=16384)

@patch.object(skool2bin, 'BinWriter', MockBinWriter)
def test_config_PadLeft_read_from_file(self):
ini = """
[skool2bin]
PadLeft=16384
"""
self.write_text_file(dedent(ini).strip(), 'skoolkit.ini')
skoolfile = 'in.skool'
binfile = 'out.bin'
self.run_skool2bin(f'{skoolfile} {binfile}')
self._check_values(skoolfile, binfile, pad_left=16384)

@patch.object(skool2bin, 'get_config', mock_config)
@patch.object(skool2bin, 'BinWriter', MockBinWriter)
def test_config_PadRight_set_on_command_line(self):
skoolfile = 'in.skool'
binfile = 'out.bin'
self.run_skool2bin(f'-I PadRight=65536 {skoolfile} {binfile}')
self._check_values(skoolfile, binfile, pad_right=65536)

@patch.object(skool2bin, 'BinWriter', MockBinWriter)
def test_config_PadLeft_read_from_file(self):
ini = """
[skool2bin]
PadRight=65536
"""
self.write_text_file(dedent(ini).strip(), 'skoolkit.ini')
skoolfile = 'in.skool'
binfile = 'out.bin'
self.run_skool2bin(f'{skoolfile} {binfile}')
self._check_values(skoolfile, binfile, pad_right=65536)

@patch.object(skool2bin, 'BinWriter', MockBinWriter)
def test_option_B(self):
skoolfile = 'test-B.skool'
Expand Down Expand Up @@ -201,6 +246,8 @@ def test_option_show_config(self):
[skool2bin]
Banks=0
Data=0
PadLeft=65536
PadRight=0
Verbose=0
Warnings=1
"""
Expand All @@ -211,6 +258,8 @@ def test_option_show_config_read_from_file(self):
[skool2bin]
Banks=1
Data=1
PadLeft=16384
PadRight=65536
Verbose=1
Warnings=0
"""
Expand All @@ -221,6 +270,8 @@ def test_option_show_config_read_from_file(self):
[skool2bin]
Banks=1
Data=1
PadLeft=16384
PadRight=65536
Verbose=1
Warnings=0
"""
Expand Down Expand Up @@ -277,7 +328,8 @@ def test_option_w(self):
self._check_values(skoolfile, exp_binfile, warn=False)

class BinWriterTestCase(SkoolKitTestCase):
def _test_write(self, skool, base_address, exp_data, *modes, banks=False, data=False, start=-1, end=65537, warn=True, exp_output='', exp_warnings=''):
def _test_write(self, skool, base_address, exp_data, *modes, banks=False, data=False, start=-1,
end=65537, warn=True, pad_left=65536, pad_right=0, exp_output='', exp_warnings=''):
if skool is None:
skoolfile = '-'
binfile = self.write_bin_file(suffix='.bin')
Expand All @@ -291,7 +343,8 @@ def _test_write(self, skool, base_address, exp_data, *modes, banks=False, data=F
asm_mode = {'isub': 1, 'ssub': 2, 'rsub': 3}[mode]
elif mode.endswith('fix'):
fix_mode = {'ofix': 1, 'bfix': 2, 'rfix': 3}[mode]
bin_writer = skool2bin.BinWriter(skoolfile, asm_mode, fix_mode, banks, start, end, data, bool(exp_output), warn)
bin_writer = skool2bin.BinWriter(skoolfile, asm_mode, fix_mode, banks, start, end, data,
bool(exp_output), warn, pad_left, pad_right)
bin_writer.write(binfile)
with open(binfile, 'rb') as f:
bdata = list(f.read())
Expand Down Expand Up @@ -740,6 +793,30 @@ def test_footer_is_ignored(self):
exp_data = [1, 2]
self._test_write(skool, 32768, exp_data)

def test_pad_left(self):
skool = """
; Data
b32770 DEFB 1,2
"""
exp_data = [0, 0, 1, 2]
self._test_write(skool, 32768, exp_data, pad_left=32768)

def test_pad_right(self):
skool = """
; Data
b32768 DEFB 3,4
"""
exp_data = [3, 4, 0, 0]
self._test_write(skool, 32768, exp_data, pad_right=32772)

def test_pad_left_and_right(self):
skool = """
; Data
b32769 DEFB 5,6
"""
exp_data = [0, 5, 6, 0]
self._test_write(skool, 32768, exp_data, pad_left=32768, pad_right=32772)

def test_verbose(self):
skool = """
; Routine
Expand Down

0 comments on commit 3e03451

Please sign in to comment.