summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/mz80/ar_romcard.cpp
blob: 83283fd36d59f2eae7a140931c289a8933ed9e11 (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
// license:BSD-3-Clause
// copyright-holders:AJR
/**************************************************************************************************

A simple ROM card for the MZ-800 described in issue A11/90 of the Czech Amatérské Rádio magazine.

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

#include "emu.h"
#include "ar_romcard.h"

#include "imagedev/cartrom.h"
#include "softlist_dev.h"

namespace {

// ======================> ar_romcard_device

class ar_romcard_device : public device_t, public device_mz80_exp_interface, public device_rom_image_interface
{
public:
	// construction/destruction
	ar_romcard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);

protected:
	// device_t implementation
	virtual void device_start() override ATTR_COLD;
	virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;

	// device_image_interface implementation
	virtual bool is_reset_on_load() const noexcept override { return false; }
	virtual const char *file_extensions() const noexcept override { return "bin"; }
	std::pair<std::error_condition, std::string> call_load() override;

	// device_mz80_exp_interface implementation
	virtual void io_map(address_map &map) override ATTR_COLD;

private:
	u8 reset_address_r();
	void reset_address_w(u8 data);
	u8 rom_data_r();
	void increment_address_w(u8 data);

	std::unique_ptr<u8 []> m_rom;
	u16 m_rom_address;
};

ar_romcard_device::ar_romcard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
	: device_t(mconfig, AR_ROMCARD, tag, owner, clock)
	, device_mz80_exp_interface(mconfig, *this)
	, device_rom_image_interface(mconfig, *this)
	, m_rom_address(0)
{
}

void ar_romcard_device::device_start()
{
	m_rom = util::make_unique_clear<u8 []>(0x10000);

	save_item(NAME(m_rom_address));
}

void ar_romcard_device::device_add_mconfig(machine_config &config)
{
	SOFTWARE_LIST(config, "rom_list").set_original("mz800_rom");
}

std::pair<std::error_condition, std::string> ar_romcard_device::call_load()
{
	u32 const size = loaded_through_softlist() ? get_software_region_length("rom") : length();
	if (size != 0x4000 && size != 0x8000 && size != 0x10000)
	{
		osd_printf_error("ar_romcard: Incorrect size for 27128/27256/27512 ROM\n");
		return std::make_pair(image_error::INVALIDLENGTH, std::string());
	}

	if (loaded_through_softlist())
		memcpy(&m_rom[0], get_software_region("rom"), size);
	else
		fread(&m_rom[0], size);

	// Mirror contents
	for (offs_t b = size; b < 0x10000; b += size)
		memcpy(&m_rom[b], &m_rom[0], size);

	return std::make_pair(std::error_condition(), std::string());
}

void ar_romcard_device::io_map(address_map &map)
{
	map(0xf8, 0xf8).mirror(0xff00).rw(FUNC(ar_romcard_device::reset_address_r), FUNC(ar_romcard_device::reset_address_w));
	map(0xf9, 0xf9).mirror(0xff00).rw(FUNC(ar_romcard_device::rom_data_r), FUNC(ar_romcard_device::increment_address_w));
}

u8 ar_romcard_device::reset_address_r()
{
	if (!machine().side_effects_disabled())
		m_rom_address = 0;
	return 0xff; // open bus
}

void ar_romcard_device::reset_address_w(u8 data)
{
	m_rom_address = 0;
}

u8 ar_romcard_device::rom_data_r()
{
	u8 data = m_rom[m_rom_address];
	if (!machine().side_effects_disabled())
		m_rom_address++;
	return data;
}

void ar_romcard_device::increment_address_w(u8 data)
{
	m_rom_address++;
}

} // anonymous namespace

// device type definition
DEFINE_DEVICE_TYPE_PRIVATE(AR_ROMCARD, device_mz80_exp_interface, ar_romcard_device, "ar_romcard", u8"Amatérské Rádio ROM Card")