summaryrefslogtreecommitdiffstatshomepage
path: root/src/zexall/zexall.cpp
blob: 826e9336b3fbfa4e70762c2c9cf5e481dcfc1d2f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// license:BSD-3-Clause
// copyright-holders:Jonathan Gevaryahu, Robbbert, Miodrag Milanovic
/******************************************************************************

  This is a simplified version of the zexall driver, merely as an example for a standalone
  emulator build. Video terminal and user interface is removed. For full notes and proper
  emulation driver, see src/drivers/zexall.cpp.

******************************************************************************/

#include "emu.h"
#include "cpu/z80/z80.h"
#include "zexall.h"
#include "interface.h"

class zexall_state : public driver_device
{
public:
	zexall_state(const machine_config &mconfig, device_type type, const char *tag)
		: driver_device(mconfig, type, tag),
		m_maincpu(*this, "maincpu"),
		m_main_ram(*this, "main_ram")
	{
	}

	DECLARE_READ8_MEMBER( output_ack_r );
	DECLARE_READ8_MEMBER( output_req_r );
	DECLARE_READ8_MEMBER( output_data_r );
	DECLARE_WRITE8_MEMBER( output_ack_w );
	DECLARE_WRITE8_MEMBER( output_req_w );
	DECLARE_WRITE8_MEMBER( output_data_w );

	void z80_mem(address_map &map);
private:
	required_device<cpu_device> m_maincpu;
	required_shared_ptr<uint8_t> m_main_ram;
	uint8_t m_out_data; // byte written to 0xFFFF
	uint8_t m_out_req; // byte written to 0xFFFE
	uint8_t m_out_req_last; // old value at 0xFFFE before the most recent write
	uint8_t m_out_ack; // byte written to 0xFFFC
	std::string terminate_string;

	virtual void machine_reset() override;
	void zexall(machine_config &config);
};


/******************************************************************************
 Machine Start/Reset
******************************************************************************/

void zexall_state::machine_reset()
{
	// zerofill
	m_out_ack = 0;
	m_out_req = 0;
	m_out_req_last = 0;
	m_out_data = 0;
	terminate_string = "";

	// program is self-modifying, so need to refresh it on each run
	memset(m_main_ram, 0xff, 0x10000);
	memcpy(m_main_ram, interface_binary, 0x51);
	memcpy(m_main_ram + 0x0100, zexall_binary, 0x2189);
}


/******************************************************************************
 I/O Handlers
******************************************************************************/

READ8_MEMBER( zexall_state::output_ack_r )
{
	// spit out the byte in out_byte if out_req is not equal to out_req_last
	if (m_out_req != m_out_req_last)
	{
		osd_printf_info("%c",m_out_data);
		if (m_out_data != 10 && m_out_data != 13)
			terminate_string += m_out_data;
		else
			terminate_string = "";

		if (terminate_string == "Tests complete")
			machine().schedule_exit();

		m_out_req_last = m_out_req;
		m_out_ack++;
	}
	return m_out_ack;
}

WRITE8_MEMBER( zexall_state::output_ack_w )
{
	m_out_ack = data;
}

READ8_MEMBER( zexall_state::output_req_r )
{
	return m_out_req;
}

WRITE8_MEMBER( zexall_state::output_req_w )
{
	m_out_req_last = m_out_req;
	m_out_req = data;
}

READ8_MEMBER( zexall_state::output_data_r )
{
	return m_out_data;
}

WRITE8_MEMBER( zexall_state::output_data_w )
{
	m_out_data = data;
}


/******************************************************************************
 Address Maps
******************************************************************************/

void zexall_state::z80_mem(address_map &map)
{
	map(0x0000, 0xffff).ram().share("main_ram");
	map(0xfffd, 0xfffd).rw(this, FUNC(zexall_state::output_ack_r), FUNC(zexall_state::output_ack_w));
	map(0xfffe, 0xfffe).rw(this, FUNC(zexall_state::output_req_r), FUNC(zexall_state::output_req_w));
	map(0xffff, 0xffff).rw(this, FUNC(zexall_state::output_data_r), FUNC(zexall_state::output_data_w));
}


/******************************************************************************
 Input Ports
******************************************************************************/

static INPUT_PORTS_START( zexall )
INPUT_PORTS_END


/******************************************************************************
 Machine Drivers
******************************************************************************/

MACHINE_CONFIG_START(zexall_state::zexall)
	/* basic machine hardware */
	MCFG_CPU_ADD("maincpu", Z80, XTAL(3'579'545))
	MCFG_CPU_PROGRAM_MAP(z80_mem)
MACHINE_CONFIG_END


/******************************************************************************
 ROM Definitions
******************************************************************************/

ROM_START(zexall)
	ROM_REGION(0x0, "maincpu", 0)
ROM_END


/******************************************************************************
 Drivers
******************************************************************************/

/*    YEAR  NAME      PARENT      COMPAT  MACHINE   INPUT   STATE         INIT    COMPANY                         FULLNAME                            FLAGS */
COMP( 2009, zexall,   0,          0,      zexall,   zexall, zexall_state, 0,      "Frank Cringle / Kevin Horton", "Zexall (FPGA Z80 test interface)", MACHINE_NO_SOUND_HW )