Skip to content

Commit

Permalink
Make PagingTracer check bit 5 of the output to port 0x7ffd
Browse files Browse the repository at this point in the history
  • Loading branch information
skoolkid committed Sep 3, 2023
1 parent d55cb5c commit 0f8f905
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 40 deletions.
2 changes: 1 addition & 1 deletion skoolkit/pagingtracer.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def write_port(self, registers, port, value):
if port % 2 == 0:
self.border = value % 8
self.outfe = value
elif port & 0x8002 == 0:
elif port & 0x8002 == 0 and self.out7ffd & 32 == 0:
memory = self.simulator.memory
if isinstance(memory, Memory):
memory.out7ffd(value)
Expand Down
54 changes: 52 additions & 2 deletions tests/slow_test_sim_load.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,16 @@

def mock_write_snapshot(ram, namespace, z80):
global snapshot, options
snapshot = [0] * 16384 + ram
options = namespace
if len(ram) == 8:
page = 0
for spec in options.state:
if spec.startswith('7ffd='):
page = int(spec[5:]) % 8
break
snapshot = [0] * 16384 + ram[5] + ram[2] + ram[page]
else:
snapshot = [0] * 16384 + ram

def get_loader(addr, bits=(0xB0, 0xCB)):
rom = list(read_bin_file(ROM48, 0x0605))
Expand Down Expand Up @@ -75,11 +83,13 @@ def _format_output(self, text):
out_lines.append(line.rstrip())
return out_lines

def _test_sim_load(self, args, exp_data, exp_reg, exp_output):
def _test_sim_load(self, args, exp_data, exp_reg, exp_output, exp_state=None):
output, error = self.run_tap2sna(args)
for data, addr in exp_data:
self.assertEqual(data, snapshot[addr:addr + len(data)])
self.assertLessEqual(exp_reg, set(options.reg))
if exp_state:
self.assertLessEqual(exp_state, set(options.state))
out_lines = self._format_output(output)
self.assertEqual(exp_output, out_lines)
self.assertEqual(error, '')
Expand Down Expand Up @@ -1085,3 +1095,43 @@ def test_trace_with_load_command(self):
self.assertEqual(trace_lines[3], '$0005 JP $11CB')
self.assertEqual(trace_lines[765494], '$0605 POP AF')
self.assertEqual(trace_lines[773699], '$34BB RET')

@patch.object(tap2sna, '_write_snapshot', mock_write_snapshot)
def test_bit_5_of_output_to_port_0x7ffd(self):
code = [
0xF3, # $8000 DI
0x21, 0x00, 0xC0, # $8001 LD HL,$C000
0x74, # $8004 LD (HL),H ; POKE 49152,192
0x01, 0xFD, 0x7F, # $8005 LD BC,$7FFD
0x3E, 0x20, # $8008 LD A,$20 ; Bit 5 set: disable paging
0xED, 0x79, # $800A OUT (C),A ; and ignore further output.
0x3E, 0x07, # $800C LD A,$07
0xED, 0x79, # $800E OUT (C),A ; This OUT should be ignored.
]
code_start = 32768
start = code_start + len(code)
basic_data = self._get_basic_data(code_start)
blocks = [
create_tap_header_block("simloadbas", 10, len(basic_data), 0),
create_tap_data_block(basic_data),
create_tap_header_block("simloadbyt", code_start, len(code)),
create_tap_data_block(code),
]
tapfile = self._write_tap(blocks)

exp_data = (
(basic_data, 23755),
(code, code_start),
([192], 49152)
)
exp_reg = {f'PC={start}'}
exp_output = [
'Program: simloadbas',
'Fast loading data block: 23755,20',
'Bytes: simloadbyt',
f'Fast loading data block: 32768,{len(code)}',
'Tape finished',
f'Simulation stopped (PC at start address): PC={start}'
]
exp_state = {'7ffd=32'}
self._test_sim_load(f'--start {start} -c machine=128 {tapfile} out.z80', exp_data, exp_reg, exp_output, exp_state)
96 changes: 59 additions & 37 deletions tests/test_trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,21 @@ def mock_config(name):
return {k: v[0] for k, v in COMMANDS[name].items()}

def mock_write_snapshot(fname, ram, registers, state):
global z80fname, snapshot, banks, z80reg, z80state
z80fname = fname
snapshot = [0] * 16384
global s_fname, s_memory, s_banks, s_reg, s_state
s_fname = fname
if len(ram) == 8:
banks = ram
s_banks = ram
page = 0
for spec in state:
if spec.startswith('7ffd='):
page = int(spec[5:]) % 8
break
snapshot += ram[5] + ram[2] + ram[page]
s_memory = [0] * 16384 + ram[5] + ram[2] + ram[page]
else:
banks = None
snapshot = [0] * 16384 + ram
z80reg = registers
z80state = state
s_banks = None
s_memory = [0] * 16384 + ram
s_reg = registers
s_state = state

class TestSimulator(simulator.Simulator):
def __init__(self, memory, registers=None, state=None, config=None):
Expand Down Expand Up @@ -644,7 +643,7 @@ def test_interrupt_with_djnz(self):
z80file = self.write_z80_file(None, ram, registers=registers)
output, error = self.run_trace(f'-S {stop} -v {z80file} {outfile}')
self.assertEqual(error, '')
self.assertEqual(snapshot[0xc001], 2) # DJNZ interrupted when B=2
self.assertEqual(s_memory[0xc001], 2) # DJNZ interrupted when B=2

@patch.object(trace, 'write_snapshot', mock_write_snapshot)
def test_interrupt_with_ldir(self):
Expand All @@ -669,7 +668,7 @@ def test_interrupt_with_ldir(self):
z80file = self.write_z80_file(None, ram, registers=registers)
output, error = self.run_trace(f'-S {stop} -v {z80file} {outfile}')
self.assertEqual(error, '')
self.assertEqual(snapshot[0xc000], 2) # LDIR interrupted when BC=2
self.assertEqual(s_memory[0xc000], 2) # LDIR interrupted when BC=2

@patch.object(trace, 'write_snapshot', mock_write_snapshot)
def test_interrupt_with_lddr(self):
Expand All @@ -694,7 +693,7 @@ def test_interrupt_with_lddr(self):
z80file = self.write_z80_file(None, ram, registers=registers)
output, error = self.run_trace(f'-S {stop} -v {z80file} {outfile}')
self.assertEqual(error, '')
self.assertEqual(snapshot[0xc000], 2) # LDDR interrupted when BC=2
self.assertEqual(s_memory[0xc000], 2) # LDDR interrupted when BC=2

def test_option_audio(self):
data = [
Expand Down Expand Up @@ -1602,11 +1601,11 @@ def test_128k_bank_5(self):
Wrote {outfile}
"""
self.assertEqual(dedent(exp_output).strip(), output.rstrip())
self.assertEqual(z80fname, outfile)
self.assertEqual(snapshot[0x4000], 5)
self.assertEqual(banks[5][0], 5)
self.assertEqual(snapshot[0xC000], 5)
self.assertEqual(banks[0][0], 0)
self.assertEqual(s_fname, outfile)
self.assertEqual(s_memory[0x4000], 5)
self.assertEqual(s_banks[5][0], 5)
self.assertEqual(s_memory[0xC000], 5)
self.assertEqual(s_banks[0][0], 0)

@patch.object(trace, 'write_snapshot', mock_write_snapshot)
def test_128k_bank_2(self):
Expand All @@ -1629,11 +1628,11 @@ def test_128k_bank_2(self):
Wrote {outfile}
"""
self.assertEqual(dedent(exp_output).strip(), output.rstrip())
self.assertEqual(z80fname, outfile)
self.assertEqual(snapshot[0x8000], 2)
self.assertEqual(banks[2][0], 2)
self.assertEqual(snapshot[0xC000], 2)
self.assertEqual(banks[0][0], 0)
self.assertEqual(s_fname, outfile)
self.assertEqual(s_memory[0x8000], 2)
self.assertEqual(s_banks[2][0], 2)
self.assertEqual(s_memory[0xC000], 2)
self.assertEqual(s_banks[0][0], 0)

def test_invalid_register_value(self):
binfile = self.write_bin_file([201], suffix='.bin')
Expand Down Expand Up @@ -1695,10 +1694,10 @@ def test_write_z80_48k(self):
)
exp_state = ['border=1', 'fe=1', 'iff=0', 'im=2', 'tstates=166']
self.assertEqual(dedent(exp_output).strip(), output.rstrip())
self.assertEqual(z80fname, outfile)
self.assertEqual(data, snapshot[start:stop])
self.assertEqual(exp_reg, z80reg)
self.assertEqual(exp_state, z80state)
self.assertEqual(s_fname, outfile)
self.assertEqual(data, s_memory[start:stop])
self.assertEqual(exp_reg, s_reg)
self.assertEqual(exp_state, s_state)

@patch.object(trace, 'write_snapshot', mock_write_snapshot)
def test_write_z80_128k(self):
Expand Down Expand Up @@ -1759,11 +1758,11 @@ def test_write_z80_128k(self):
exp_state = [f'ay[{n}]=0' for n in range(16)]
exp_state.extend(('7ffd=1', 'fffd=0', 'border=1', 'fe=1', 'iff=0', 'im=2', 'tstates=178'))
self.assertEqual(dedent(exp_output).strip(), output.rstrip())
self.assertEqual(z80fname, outfile)
self.assertEqual(code, snapshot[start:stop])
self.assertTrue(all(b == 1 for b in snapshot[0xC000:0x10000]))
self.assertEqual(exp_reg, z80reg)
self.assertEqual(exp_state, z80state)
self.assertEqual(s_fname, outfile)
self.assertEqual(code, s_memory[start:stop])
self.assertTrue(all(b == 1 for b in s_memory[0xC000:0x10000]))
self.assertEqual(exp_reg, s_reg)
self.assertEqual(exp_state, s_state)

@patch.object(trace, 'write_snapshot', mock_write_snapshot)
def test_ay_tracing_from_z80(self):
Expand Down Expand Up @@ -1792,9 +1791,9 @@ def test_ay_tracing_from_z80(self):
output, error = self.run_trace(f'-s {start} -S {stop} {z80file} out.z80')
exp_state = [f'ay[{n}]={v + 1}' for n, v in enumerate(ay[1:])]
exp_state.append('fffd=0')
self.assertEqual(snapshot[0xff10], ay[1 + ay[0]]) # Input: current AY register value
self.assertEqual(ay[1:], snapshot[0xff00:0xff10]) # Input: all AY register values
self.assertLessEqual(set(exp_state), set(z80state)) # Output: AY state
self.assertEqual(s_memory[0xff10], ay[1 + ay[0]]) # Input: current AY register value
self.assertEqual(ay[1:], s_memory[0xff00:0xff10]) # Input: all AY register values
self.assertLessEqual(set(exp_state), set(s_state)) # Output: AY state

@patch.object(trace, 'write_snapshot', mock_write_snapshot)
def test_ay_tracing_from_szx(self):
Expand Down Expand Up @@ -1823,6 +1822,29 @@ def test_ay_tracing_from_szx(self):
output, error = self.run_trace(f'-s {start} -S {stop} {szxfile} out.z80')
exp_state = [f'ay[{n}]={v + 1}' for n, v in enumerate(ay[1:])]
exp_state.append('fffd=0')
self.assertEqual(snapshot[0xff10], ay[1 + ay[0]]) # Input: current AY register value
self.assertEqual(ay[1:], snapshot[0xff00:0xff10]) # Input: all AY register values
self.assertLessEqual(set(exp_state), set(z80state)) # Output: AY state
self.assertEqual(s_memory[0xff10], ay[1 + ay[0]]) # Input: current AY register value
self.assertEqual(ay[1:], s_memory[0xff00:0xff10]) # Input: all AY register values
self.assertLessEqual(set(exp_state), set(s_state)) # Output: AY state

@patch.object(trace, 'write_snapshot', mock_write_snapshot)
def test_bit_5_of_output_to_port_0x7ffd(self):
code = (
0xF3, # $8000 DI
0x01, 0xFD, 0x7F, # $8001 LD BC,$7FFD
0x3E, 0x20, # $8004 LD A,$20 ; Bit 5 set: disable paging
0xED, 0x79, # $8006 OUT (C),A ; and ignore further output.
0x3E, 0x07, # $8008 LD A,$07
0xED, 0x79, # $800A OUT (C),A ; This OUT should be ignored.
)
ram = [0] * 49152
start = 32768
ram[start - 0x4000:start - 0x4000 + len(code)] = code
ram[32768] = 255 # POKE 49152,255
stop = start + len(code)
z80file = self.write_z80(ram, machine_id=4)[1]
stop = start + len(code)
self.run_trace(f'-s {start} -S {stop} {z80file} out.z80')
out7ffd = [s[5:] for s in s_state if s.startswith('7ffd=')]
self.assertEqual(len(out7ffd), 1)
self.assertEqual(out7ffd[0], '32')
self.assertEqual(s_memory[49152], 255)

0 comments on commit 0f8f905

Please sign in to comment.