summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/elan_ep3a19a_soc.cpp
blob: 9fde0663c9528634571a0508245317c8504ebf52 (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
// license:BSD-3-Clause
// copyright-holders:David Haywood

#include "emu.h"
#include "elan_ep3a19a_soc.h"

DEFINE_DEVICE_TYPE(ELAN_EP3A19A_SOC,     elan_ep3a19a_soc_device,     "elan_ep3a19a_soc_device",     "ELAN EP3A19A")

elan_ep3a19a_soc_device::elan_ep3a19a_soc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
	m6502_device(mconfig, type, tag, owner, clock),
	m_extbus_config("extbus", ENDIANNESS_LITTLE, 8, 24),
	m_sys(*this, "sys"),
	m_gpio(*this, "gpio"),
	m_screen(*this, ":screen"),
	m_ram(*this, "ram"),
	m_sound(*this, "eu3a05sound"),
	m_vid(*this, "vid"),
	m_palette(*this, "palette"),
	m_read_callback(*this, 0xff),
	m_write_callback(*this)
{
	m_extbus_config.m_addr_width = 24;
	m_extbus_config.m_logaddr_width = 24;
	m_program_config.m_internal_map = address_map_constructor(FUNC(elan_ep3a19a_soc_device::int_map), this);
}

elan_ep3a19a_soc_device::elan_ep3a19a_soc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
	elan_ep3a19a_soc_device(mconfig, ELAN_EP3A19A_SOC, tag, owner, clock)
{
}


static const gfx_layout helper_4bpp_8_layout =
{
	8,1,
	RGN_FRAC(1,1),
	4,
	{ 0,1,2,3 },
	{ STEP8(0,4) },
	{ 0 },
	8 * 4
};

static const gfx_layout helper_8bpp_8_layout =
{
	8,1,
	RGN_FRAC(1,1),
	8,
	{ 0,1,2,3,4,5,6,7 },
	{ STEP8(0,8) },
	{ 0 },
	8 * 8
};

// these are fake just to make looking at the texture pages easier
static const uint32_t texlayout_xoffset_8bpp[256] = { STEP256(0,8) };
static const uint32_t texlayout_yoffset_8bpp[256] = { STEP256(0,256*8) };
static const gfx_layout texture_helper_8bpp_layout =
{
	256, 256,
	RGN_FRAC(1,1),
	8,
	{ 0,1,2,3,4,5,6,7 },
	EXTENDED_XOFFS,
	EXTENDED_YOFFS,
	256*256*8,
	texlayout_xoffset_8bpp,
	texlayout_yoffset_8bpp
};

static const uint32_t texlayout_xoffset_4bpp[256] = { STEP256(0,4) };
static const uint32_t texlayout_yoffset_4bpp[256] = { STEP256(0,256*4) };
static const gfx_layout texture_helper_4bpp_layout =
{
	256, 256,
	RGN_FRAC(1,1),
	4,
	{ 0,1,2,3 },
	EXTENDED_XOFFS,
	EXTENDED_YOFFS,
	256*256*4,
	texlayout_xoffset_4bpp,
	texlayout_yoffset_4bpp
};

static GFXDECODE_START( gfx_ep3a19a_fake )
	// TODO: how do we avoid the direct region reference here? (this is only used for debugging)
	GFXDECODE_ENTRY( ":maincpu", 0, helper_4bpp_8_layout,  0x0, 1  )
	GFXDECODE_ENTRY( ":maincpu", 0, texture_helper_4bpp_layout,  0x0, 1  )
	GFXDECODE_ENTRY( ":maincpu", 0, helper_8bpp_8_layout,  0x0, 1  )
	GFXDECODE_ENTRY( ":maincpu", 0, texture_helper_8bpp_layout,  0x0, 1  )
GFXDECODE_END

void elan_ep3a19a_soc_device::device_add_mconfig(machine_config &config)
{
	PALETTE(config, m_palette).set_entries(256);

	ELAN_EU3A05_GPIO(config, m_gpio, 0);
	m_gpio->read_callback<0>().set(FUNC(elan_ep3a19a_soc_device::port_r<0>));
	m_gpio->write_callback<0>().set(FUNC(elan_ep3a19a_soc_device::port_w<0>));
	m_gpio->read_callback<1>().set(FUNC(elan_ep3a19a_soc_device::port_r<1>));
	m_gpio->write_callback<1>().set(FUNC(elan_ep3a19a_soc_device::port_w<1>));
	m_gpio->read_callback<2>().set(FUNC(elan_ep3a19a_soc_device::port_r<2>));
	m_gpio->write_callback<2>().set(FUNC(elan_ep3a19a_soc_device::port_w<2>));

	ELAN_EP3A19A_SYS(config, m_sys, 0);
	m_sys->set_cpu(DEVICE_SELF);
	m_sys->bank_change_callback().set(FUNC(elan_ep3a19a_soc_device::bank_change));

	ELAN_EP3A19A_VID(config, m_vid, 0);
	m_vid->set_cpu(DEVICE_SELF);
	m_vid->set_palette(m_palette);
	m_vid->set_entries(256);

	/* sound hardware */
	SPEAKER(config, "mono").front_center();

	ELAN_EU3A05_SOUND(config, m_sound, 8000);
	m_sound->space_read_callback().set(FUNC(elan_ep3a19a_soc_device::read_full_space));
	m_sound->add_route(ALL_OUTPUTS, "mono", 1.0);

	/*
	m_sound->sound_end_cb<0>().set(FUNC(elan_ep3a19a_soc_device::sound_end0));
	m_sound->sound_end_cb<1>().set(FUNC(elan_ep3a19a_soc_device::sound_end1));
	m_sound->sound_end_cb<2>().set(FUNC(elan_ep3a19a_soc_device::sound_end2));
	m_sound->sound_end_cb<3>().set(FUNC(elan_ep3a19a_soc_device::sound_end3));
	m_sound->sound_end_cb<4>().set(FUNC(elan_ep3a19a_soc_device::sound_end4));
	m_sound->sound_end_cb<5>().set(FUNC(elan_ep3a19a_soc_device::sound_end5));
	*/

	GFXDECODE(config, "gfxdecode", m_palette, gfx_ep3a19a_fake);
}

device_memory_interface::space_config_vector elan_ep3a19a_soc_device::memory_space_config() const
{
	if(has_configured_map(AS_OPCODES))
		return space_config_vector {
			std::make_pair(AS_PROGRAM, &m_program_config),
			std::make_pair(AS_OPCODES, &m_sprogram_config),
			std::make_pair(AS_EXTERNAL, &m_extbus_config),
		};
	else
		return space_config_vector {
			std::make_pair(AS_PROGRAM, &m_program_config),
			std::make_pair(AS_EXTERNAL, &m_extbus_config),
		};
}

void elan_ep3a19a_soc_device::device_reset()
{
	m6502_device::device_reset();

	// see note in eu3a05, probably applies here too but nothing depends on it
	set_state_int(M6502_S, 0x1ff);
}

void elan_ep3a19a_soc_device::device_start()
{
	m6502_device::device_start();
}

void elan_ep3a19a_soc_device::int_map(address_map &map)
{
	// can the addresses move around?
	map(0x0000, 0x3fff).ram().share("ram");
	map(0x4800, 0x49ff).rw(m_vid, FUNC(elan_eu3a05commonvid_device::palette_r), FUNC(elan_eu3a05commonvid_device::palette_w));

	map(0x5000, 0x5014).m(m_sys, FUNC(elan_ep3a19asys_device::map)); // including DMA controller
	map(0x5020, 0x503f).m(m_vid, FUNC(elan_eu3a05vid_device::map));

	// 504x GPIO area?
	map(0x5040, 0x5046).rw(m_gpio, FUNC(elan_eu3a05gpio_device::gpio_r), FUNC(elan_eu3a05gpio_device::gpio_w));
	// 5047
	//map(0x5048, 0x504a).w(m_gpio, FUNC(elan_eu3a05gpio_device::gpio_unk_w));

	// 506x unknown
	//map(0x5060, 0x506d).ram(); // read/written by tetris (ADC?)

	// 508x sound
	map(0x5080, 0x50bf).m(m_sound, FUNC(elan_eu3a05_sound_device::map));

	//map(0x5000, 0x50ff).ram();
	map(0x6000, 0xdfff).rw(FUNC(elan_ep3a19a_soc_device::bank_r), FUNC(elan_ep3a19a_soc_device::bank_w));

	map(0xe000, 0xffff).r(FUNC(elan_ep3a19a_soc_device::fixed_r));
	// not sure how these work, might be a modified 6502 core instead.
	//map(0xfffa, 0xfffb).r(m_sys, FUNC(elan_eu3a05commonsys_device::nmi_vector_r)); // custom vectors handled with NMI for now
	map(0xfffa, 0xfffb).r(FUNC(elan_ep3a19a_soc_device::nmi_vector_r)); // custom vectors handled with NMI for now

	//map(0xfffe, 0xffff).r(m_sys, FUNC(elan_eu3a05commonsys_device::irq_vector_r));  // allow normal IRQ for brk
}