summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/astrocde/ram.cpp
blob: 39eb299d8f69d9b1c309c7179cf1652513bcee76 (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
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
// license:BSD-3-Clause
// copyright-holders:Fabio Priuli
/***********************************************************************************************************


  Bally Astrocade RAM expansion emulation

      RAM Expansions (info below courtesy of Paul Thacker)

      Several third party RAM expansions have been made for the Astrocade.  These
      allow access to various ranges of the expansion memory ($5000 to $FFFF).
      A RAM expansion is required to use extended BASIC programs like Blue RAM BASIC
      and VIPERSoft BASIC.  All of the expansions also have a RAM protect switch, which
      can be flipped at any time to make the RAM act like ROM.  Extended BASIC
      programs need access to the RAM and won't work with RAM protect enabled, but
      this can be useful with Bally and Astrocade BASIC.  They also have a range switch
      (not implemented).  The default position is 6K, but it can be switched to
      2K.  This means that the expanded memory starting at $6000 will instead be
      mapped to the cartridge memory starting at $2000.  So it would be possible to
      load a cartridge program from tape into the expansion memory, then flip the range
      switch and run it as a cartridge.  This is useful for cartridge development.

      Blue RAM -- available in 4K, 16K, and 32K.  These also use an INS8154 chip,
      which has an additional $80 bytes of RAM mapped immediately after the end of
      the expansion address space (not yet implemented).  This memory can't be write
      protected.  The INS8154 has I/O features needed for loading tape programs into
      Blue RAM BASIC, as well as running the Blue RAM Utility cart.
      4K:  $6000 to $6FFF (can't run VIPERSoft BASIC, because this program needs memory
      past this range)
      16K:  $6000 to $9FFF
      32K:  $6000 to $DFFF

      VIPER System 1 -- This is available in 16K only.  It also includes a keyboard (not implemented).
      16K:  $6000 to $9FFF

      Lil' WHITE RAM -- This is available in 32K only.  Attempts to read and write
      to memory outside of its address range ($D000 to $FFFF) are mapped to the expansion
      memory $5000 to $7FFF.  The current implementation won't allow the shadow RAM area
      to be accessed when RAM protect is on, but there is no known software that will
      access the upper range of the expansion RAM when RAM protect is enabled.
      32K:  $5000 to $CFFF

      R&L 64K RAM Board -- This is a highly configurable kit.  RAM can be installed in
      2K increments.  So, the entire 44K expansion memory can be filled.  It is also
      possible to override the rest of the memory map with RAM (not implemented).
      There are 32 switches allowing users to activate and deactivate each 2K block (not implemented).
      RAM write protection can be implemented in three ranges through jumpers or by
      installing switches.  The ranges are $0000 to $0FFF (first 4K), $0000 to $3FFF (first 16K),
      and $0000 to $FFFF (all 64K).  The current implementation is for 44K expansion memory mapped from
      $5000 to $FFFF, with only a single write protect covering this entire range.

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


#include "emu.h"
#include "ram.h"


//-------------------------------------------------
//  astrocade_rom_device - constructor
//-------------------------------------------------

DEFINE_DEVICE_TYPE(ASTROCADE_BLUERAM_4K,  astrocade_blueram_4k_device,  "astrocade_br4",  "Bally Astrocade Blue RAM 4K")
DEFINE_DEVICE_TYPE(ASTROCADE_BLUERAM_16K, astrocade_blueram_16k_device, "astrocade_br16", "Bally Astrocade Blue RAM 16K")
DEFINE_DEVICE_TYPE(ASTROCADE_BLUERAM_32K, astrocade_blueram_32k_device, "astrocade_br32", "Bally Astrocade Blue RAM 32K")
DEFINE_DEVICE_TYPE(ASTROCADE_VIPER_SYS1,  astrocade_viper_sys1_device,  "astrocade_vs1",  "Bally Astrocade Viper System 1")
DEFINE_DEVICE_TYPE(ASTROCADE_WHITERAM,    astrocade_whiteram_device,    "astrocade_lwr",  "Bally Astrocade Lil' White RAM 32K")
DEFINE_DEVICE_TYPE(ASTROCADE_RL64RAM,     astrocade_rl64ram_device,     "astrocade_rl64", "Bally Astrocade R&L RAM 64K")


astrocade_blueram_4k_device::astrocade_blueram_4k_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, type, tag, owner, clock)
	, device_astrocade_exp_interface(mconfig, *this)
	, m_write_prot(*this, "RAM_PROTECT")
	, m_ramio(*this, "ramio")
	, m_cassette(*this, "cassette")
{
}

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

astrocade_blueram_16k_device::astrocade_blueram_16k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: astrocade_blueram_4k_device(mconfig, ASTROCADE_BLUERAM_16K, tag, owner, clock)
{
}

astrocade_blueram_32k_device::astrocade_blueram_32k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: astrocade_blueram_4k_device(mconfig, ASTROCADE_BLUERAM_32K, tag, owner, clock)
{
}

astrocade_viper_sys1_device::astrocade_viper_sys1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, ASTROCADE_VIPER_SYS1, tag, owner, clock)
	, device_astrocade_exp_interface(mconfig, *this)
	, m_write_prot(*this, "RAM_PROTECT")
{
}

astrocade_whiteram_device::astrocade_whiteram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, ASTROCADE_WHITERAM, tag, owner, clock)
	, device_astrocade_exp_interface(mconfig, *this)
	, m_write_prot(*this, "RAM_PROTECT")
{
}

astrocade_rl64ram_device::astrocade_rl64ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, ASTROCADE_RL64RAM, tag, owner, clock)
	, device_astrocade_exp_interface(mconfig, *this)
	, m_write_prot(*this, "RAM_PROTECT")
{
}


//-------------------------------------------------
//  RAM Write protect switch
//-------------------------------------------------

static INPUT_PORTS_START( exp_switches )
	PORT_START("RAM_PROTECT")
	PORT_CONFNAME( 0x01, 0x00, "Write Protect RAM")
	PORT_CONFSETTING( 0x00, DEF_STR(Off))
	PORT_CONFSETTING( 0x01, DEF_STR(On))
INPUT_PORTS_END


ioport_constructor astrocade_blueram_4k_device::device_input_ports() const
{
	return INPUT_PORTS_NAME( exp_switches );
}

ioport_constructor astrocade_viper_sys1_device::device_input_ports() const
{
	return INPUT_PORTS_NAME( exp_switches );
}

ioport_constructor astrocade_whiteram_device::device_input_ports() const
{
	return INPUT_PORTS_NAME( exp_switches );
}

ioport_constructor astrocade_rl64ram_device::device_input_ports() const
{
	return INPUT_PORTS_NAME( exp_switches );
}

/*-------------------------------------------------
 specific handlers
 -------------------------------------------------*/

// Blue RAM expansions have RAM starting at 0x6000, up to the RAM size
uint8_t astrocade_blueram_4k_device::read(offs_t offset)
{
	if (offset >= 0x1000 && offset < 0x1000 + m_ram.size())
		return m_ram[offset - 0x1000];
	else
		return 0;
}

void astrocade_blueram_4k_device::write(offs_t offset, uint8_t data)
{
	if (offset >= 0x1000 && offset < 0x1000 + m_ram.size() && !m_write_prot->read())
		m_ram[offset - 0x1000] = data;
}

uint8_t astrocade_blueram_4k_device::read_io(offs_t offset)
{
	return m_ramio->read_io(offset & 0x7f);
}

void astrocade_blueram_4k_device::write_io(offs_t offset, uint8_t data)
{
	logerror("write_io: %04x = %02x\n", offset, data);
	m_ramio->write_io(offset & 0x7f, data);
}

uint8_t astrocade_blueram_4k_device::porta_r()
{
	return 0;
}

uint8_t astrocade_blueram_4k_device::portb_r()
{
	return m_cassette->input() > 0.0 ? 1 : 0;
}

void astrocade_blueram_4k_device::porta_w(uint8_t data)
{
}

void astrocade_blueram_4k_device::portb_w(uint8_t data)
{
	m_cassette->output(BIT(data, 0) ? +1 : -1);
}

// Viper System 1 expansion has RAM in 0x6000-0x9fff
uint8_t astrocade_viper_sys1_device::read(offs_t offset)
{
	if (offset >= 0x1000 && offset < 0xa000)
		return m_ram[offset - 0x1000];
	else
		return 0;
}

void astrocade_viper_sys1_device::write(offs_t offset, uint8_t data)
{
	if (offset >= 0x1000 && offset < 0xa000 && !m_write_prot->read())
		m_ram[offset - 0x1000] = data;
}



// Lil' WHITE RAM expansion has RAM in 0x5000-0xcfff + a mirror of the first 0x3000 bytes up to 0xffff
uint8_t astrocade_whiteram_device::read(offs_t offset)
{
	return m_ram[offset % 0x8000];
}

void astrocade_whiteram_device::write(offs_t offset, uint8_t data)
{
	if (!m_write_prot->read())
		m_ram[offset % 0x8000] = data;
}



// R&L 64K RAM Board (44KB installed) has RAM in 0x5000-0xffff
uint8_t astrocade_rl64ram_device::read(offs_t offset)
{
	return m_ram[offset];
}

void astrocade_rl64ram_device::write(offs_t offset, uint8_t data)
{
	if (!m_write_prot->read())
		m_ram[offset] = data;
}

/*-------------------------------------------------
 machine configuration
 -------------------------------------------------*/

void astrocade_blueram_4k_device::device_add_mconfig(machine_config &config)
{
	CASSETTE(config, m_cassette);
	m_cassette->set_default_state(CASSETTE_STOPPED);
	m_cassette->set_interface("astrocade_cass");

	INS8154(config, m_ramio);
	m_ramio->out_a().set(FUNC(astrocade_blueram_4k_device::porta_w));
	m_ramio->out_b().set(FUNC(astrocade_blueram_4k_device::portb_w));
	m_ramio->in_a().set(FUNC(astrocade_blueram_4k_device::porta_r));
	m_ramio->in_b().set(FUNC(astrocade_blueram_4k_device::portb_r));
}