summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/a2bus/softcard3.cpp
blob: 1b3d24e809f00bb0729b60394f8d8ab9cbcb2c0d (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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
// license:BSD-3-Clause
// copyright-holders:Rob Justice, R. Belmont
/*********************************************************************

    softcard3.cpp

    Implementation of the Microsoft SoftCard /// Z-80 card

    Best guess at the moment based on disassembly of the boot disk
    and some manual checks with the real hardware

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

#include "emu.h"
#include "softcard3.h"
#include "cpu/z80/z80.h"

/***************************************************************************
    PARAMETERS
***************************************************************************/

//**************************************************************************
//  GLOBAL VARIABLES
//**************************************************************************

DEFINE_DEVICE_TYPE(A2BUS_SOFTCARD3, a2bus_softcard3_device, "softcard3", "Microsoft SoftCard ///")

void a2bus_softcard3_device::z80_mem(address_map &map)
{
	map(0x0000, 0xffff).rw(FUNC(a2bus_softcard3_device::dma_r), FUNC(a2bus_softcard3_device::dma_w));
}

ROM_START( softcard3 )
	ROM_REGION(0x100, "mapping_prom", 0)
	ROM_LOAD("softcard3.rom", 0x0000, 0x0100, CRC(9d4433b2) SHA1(aff45dd8850641b4616b61750c104e7ee45a99a4))
ROM_END

void a2bus_softcard3_device::z80_io(address_map &map)
{
	map(0x00, 0x00).w(FUNC(a2bus_softcard3_device::z80_io_w));
}

/***************************************************************************
    FUNCTION PROTOTYPES
***************************************************************************/

//-------------------------------------------------
//  device_add_mconfig - add device configuration
//-------------------------------------------------

void a2bus_softcard3_device::device_add_mconfig(machine_config &config)
{
	Z80(config, m_z80, 1021800*2);   // Z80 runs at 2M based on comment in the manual
	m_z80->set_addrmap(AS_PROGRAM, &a2bus_softcard3_device::z80_mem);
	m_z80->set_addrmap(AS_IO, &a2bus_softcard3_device::z80_io);
	TIMER(config, "timer").configure_generic(FUNC(a2bus_softcard3_device::timercallback));
}

//**************************************************************************
//  LIVE DEVICE
//**************************************************************************

a2bus_softcard3_device::a2bus_softcard3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, const XTAL &clock) :
	device_t(mconfig, type, tag, owner, clock),
	device_a2bus_card_interface(mconfig, *this),
	m_z80(*this, "z80"),
	m_prom(*this, "mapping_prom"),
	m_timer(*this, "timer"),
	m_bEnabled(false),
	m_reset(false),
	m_enable_fffx(false)
{
}

a2bus_softcard3_device::a2bus_softcard3_device(const machine_config &mconfig, const char *tag, device_t *owner, const XTAL &clock) :
	a2bus_softcard3_device(mconfig, A2BUS_SOFTCARD3, tag, owner, clock)
{
}

const tiny_rom_entry *a2bus_softcard3_device::device_rom_region() const
{
	return ROM_NAME(softcard3);
}

//-------------------------------------------------
//  device_start - device-specific startup
//-------------------------------------------------

void a2bus_softcard3_device::device_start()
{
	save_item(NAME(m_bEnabled));
	save_item(NAME(m_reset));
	save_item(NAME(m_enable_fffx));
}

void a2bus_softcard3_device::device_reset()
{
	m_bEnabled = false;
	m_reset = false;
	m_enable_fffx = false;
	m_z80->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
	m_timer->adjust(attotime::never);
}

uint8_t a2bus_softcard3_device::read_c0nx(uint8_t offset)
{
	return 0x50; //software is looking for 0x50, needs to be checked if this can return other flags
}

void a2bus_softcard3_device::write_c0nx(uint8_t offset, uint8_t data)
{
	switch (data)
	{
		case 0x01: // reset
			m_reset = true; // flag we need a reset when we enable the Z80
			break;

		case 0x10: // enable the card fffc & fffd memory mapped address to appear
			m_enable_fffx = true;
			break;

		default:
			//printf("Softcard3: %02x to unhandled c0n%x\n", data, offset);
			break;
	}
}

// read to fffc halts 6502 and enables z80
uint8_t a2bus_softcard3_device::read_inh_rom(uint16_t offset)
{
	if (offset == 0xfffc)
	{
		m_bEnabled = true;
		raise_slot_dma();
		m_z80->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
		if (m_reset)
		{
			m_z80->reset();
		}
		m_timer->adjust(attotime::from_hz(5.0)); //start supervision timer
		//printf("timer start\n");
	}

	if (offset == 0xfffd)
	{
		m_timer->adjust(attotime::never); //disable supervision timer
		//printf("disable timer\n");
	}

	return 0xff;
}

// returns if we want to /INH a read or write to a specific address
bool a2bus_softcard3_device::inh_check(u16 offset, bool bIsWrite)
{
	if (!m_enable_fffx)
	{
		return false;
	}

	if (!(bIsWrite) && (offset == 0xfffc)) //only a read to fffc is mapped in
	{
		return true;
	}

	if (!(bIsWrite) && (offset == 0xfffd)) //only a read to fffd is mapped in
	{
		return true;
	}

	return false;
}

// this io write halts the z80 and returns to the 6502
void a2bus_softcard3_device::z80_io_w(offs_t offset, uint8_t data)
{
	m_z80->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
	lower_slot_dma();
	m_bEnabled = false;
	m_enable_fffx = false;
	m_reset = false;
	m_timer->adjust(attotime::never);
	//printf("z80 io timer stop\n");
}

// fires if Z80 has not handed back to the 6502 in this timer period
// this ensures 6502 can run and service console i/o
//  actual time to be checked on real hw
TIMER_DEVICE_CALLBACK_MEMBER(a2bus_softcard3_device::timercallback)
{
	m_z80->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
	lower_slot_dma();
	m_bEnabled = false;
	m_enable_fffx = false;
	m_reset = false;
	//printf("timer callback stop\n");
}

//memory mapping based on a dump of the mapping rom 256x8
//maps the top 8 address lines
uint8_t a2bus_softcard3_device::dma_r(offs_t offset)
{
	if (m_bEnabled)
	{
		return slot_dma_read((offset & 0xff) + (m_prom[offset >> 8] << 8));
	}

	return 0xff;
}

//-------------------------------------------------
//  dma_w -
//-------------------------------------------------

void a2bus_softcard3_device::dma_w(offs_t offset, uint8_t data)
{
	if (m_bEnabled)
	{
		slot_dma_write((offset & 0xff) + (m_prom[offset >> 8] << 8), data);
	}
}

bool a2bus_softcard3_device::take_c800()
{
	return false;
}