1 // license:BSD-3-Clause
2 // copyright-holders:Nigel Barnes
3 /**********************************************************************
4
5 Morley Electronics RAM Disc
6
7 Notes:
8 - 1MB model has 4096 sectors &0000 to &0fff
9 - 2MB model has 8192 sectors &0000 to &1fff
10
11 **********************************************************************/
12
13
14 #include "emu.h"
15 #include "ramdisc.h"
16
17
18 //**************************************************************************
19 // DEVICE DEFINITIONS
20 //**************************************************************************
21
22 DEFINE_DEVICE_TYPE(BBC_RAMDISC, bbc_ramdisc_device, "bbc_ramdisc", "Morley Electronics RAM Disc");
23
24
25 //-------------------------------------------------
26 // INPUT_PORTS( ramdisc )
27 //-------------------------------------------------
28
29 static INPUT_PORTS_START(ramdisc)
30 PORT_START("POWER")
31 PORT_CONFNAME(0x01, 0x01, "Power") PORT_CHANGED_MEMBER(DEVICE_SELF, bbc_ramdisc_device, power_changed, 0)
DEF_STR(Off)32 PORT_CONFSETTING(0x00, DEF_STR(Off))
33 PORT_CONFSETTING(0x01, DEF_STR(On))
34 PORT_START("SIZE")
35 PORT_CONFNAME(0x03, 0x02, "RAM Disk Capacity")
36 PORT_CONFSETTING(0x01, "1MB")
37 PORT_CONFSETTING(0x02, "2MB")
38 INPUT_PORTS_END
39
40 //-------------------------------------------------
41 // input_ports - device-specific input ports
42 //-------------------------------------------------
43
44 ioport_constructor bbc_ramdisc_device::device_input_ports() const
45 {
46 return INPUT_PORTS_NAME(ramdisc);
47 }
48
49 //-------------------------------------------------
50 // ROM( ramdisc )
51 //-------------------------------------------------
52
53 ROM_START(ramdisc)
54 ROM_REGION(0x4000, "exp_rom", 0)
55 ROM_LOAD("ramdisc101.rom", 0x0000, 0x4000, CRC(627568c2) SHA1(17e727998756fe35ff451fd2ce1d4b5977be24fc))
56 ROM_END
57
58 //-------------------------------------------------
59 // device_add_mconfig - add device configuration
60 //-------------------------------------------------
61
device_add_mconfig(machine_config & config)62 void bbc_ramdisc_device::device_add_mconfig(machine_config &config)
63 {
64 /* ram disk */
65 NVRAM(config, "nvram", nvram_device::DEFAULT_NONE);
66
67 BBC_1MHZBUS_SLOT(config, m_1mhzbus, DERIVED_CLOCK(1, 1), bbc_1mhzbus_devices, nullptr);
68 m_1mhzbus->irq_handler().set(DEVICE_SELF_OWNER, FUNC(bbc_1mhzbus_slot_device::irq_w));
69 m_1mhzbus->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(bbc_1mhzbus_slot_device::nmi_w));
70 }
71
72 //-------------------------------------------------
73 // rom_region - device-specific ROM region
74 //-------------------------------------------------
75
device_rom_region() const76 const tiny_rom_entry *bbc_ramdisc_device::device_rom_region() const
77 {
78 return ROM_NAME(ramdisc);
79 }
80
81 //**************************************************************************
82 // LIVE DEVICE
83 //**************************************************************************
84
85 //-------------------------------------------------
86 // bbc_ramdisc_device - constructor
87 //-------------------------------------------------
88
bbc_ramdisc_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)89 bbc_ramdisc_device::bbc_ramdisc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
90 : device_t(mconfig, BBC_RAMDISC, tag, owner, clock)
91 , device_bbc_1mhzbus_interface(mconfig, *this)
92 , m_1mhzbus(*this, "1mhzbus")
93 , m_nvram(*this, "nvram")
94 , m_ram_size(*this, "SIZE")
95 , m_power(*this, "POWER")
96 , m_sector(0)
97 {
98 }
99
100 //-------------------------------------------------
101 // device_start - device-specific startup
102 //-------------------------------------------------
103
device_start()104 void bbc_ramdisc_device::device_start()
105 {
106 /* define 2mb ram */
107 m_ram = std::make_unique<uint8_t[]>(0x200000);
108 m_nvram->set_base(m_ram.get(), 0x200000);
109
110 /* register for save states */
111 save_pointer(NAME(m_ram), 0x200000);
112 save_item(NAME(m_sector));
113 }
114
115
116 //**************************************************************************
117 // IMPLEMENTATION
118 //**************************************************************************
119
INPUT_CHANGED_MEMBER(bbc_ramdisc_device::power_changed)120 INPUT_CHANGED_MEMBER(bbc_ramdisc_device::power_changed)
121 {
122 /* clear RAM on power off */
123 if (!newval)
124 {
125 memset(m_ram.get(), 0xff, 0x200000);
126 }
127 }
128
fred_r(offs_t offset)129 uint8_t bbc_ramdisc_device::fred_r(offs_t offset)
130 {
131 uint8_t data = 0xff;
132
133 if (m_power->read())
134 {
135 switch (offset)
136 {
137 case 0xc0:
138 /* sector LSB */
139 data = m_sector & 0x00ff;
140 break;
141 case 0xc2:
142 /* sector MSB */
143 data = (m_sector & 0xff00) >> 8;
144 break;
145 case 0xc1:
146 case 0xc3:
147 /* TODO: unknown purpose, must return 0x3f or 0x5f */
148 data = 0x3f;
149 logerror("Read %04x -> %02x\n", offset | 0xfcc0, data);
150 break;
151 }
152 }
153
154 data &= m_1mhzbus->fred_r(offset);
155
156 return data;
157 }
158
fred_w(offs_t offset,uint8_t data)159 void bbc_ramdisc_device::fred_w(offs_t offset, uint8_t data)
160 {
161 if (m_power->read())
162 {
163 switch (offset)
164 {
165 case 0xc0:
166 /* sector LSB */
167 m_sector = (m_sector & 0xff00) | data;
168 break;
169 case 0xc2:
170 /* sector MSB */
171 m_sector = (m_sector & 0x00ff) | (data << 8);
172 break;
173 case 0xc1:
174 case 0xc3:
175 /* TODO: unknown purpose, always writes 0x00 or 0xff */
176 logerror("Write %04x <- %02x\n", offset | 0xfcc0, data);
177 break;
178 }
179 }
180
181 m_1mhzbus->fred_w(offset, data);
182 }
183
jim_r(offs_t offset)184 uint8_t bbc_ramdisc_device::jim_r(offs_t offset)
185 {
186 uint8_t data = 0xff;
187
188 /* power on and sector < 2mb */
189 if (m_power->read() && m_sector < (m_ram_size->read() << 8))
190 {
191 data &= m_ram[(m_sector << 8) | offset];
192 }
193
194 data &= m_1mhzbus->jim_r(offset);
195
196 return data;
197 }
198
jim_w(offs_t offset,uint8_t data)199 void bbc_ramdisc_device::jim_w(offs_t offset, uint8_t data)
200 {
201 /* power on and sector < 2mb */
202 if (m_power->read() && m_sector < (m_ram_size->read() << 8))
203 {
204 m_ram[(m_sector << 8) | offset] = data;
205 }
206
207 m_1mhzbus->jim_w(offset, data);
208 }
209