summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/acorn/system/8k.cpp
blob: 97939b7362f4b1f648bd36d5f6e0b7b0f290a145 (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
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************

    Acorn 8K Static Memory Board

    Part No. 200,003

    http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_Memory.html

    The Acorn Extension Memory board provides an extra 8K bytes of
    user RAM space and has sockets for two ROMs which may be 2, 4 or 8K
    devices providing 4 or 8K bytes of firmware.

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


#include "emu.h"
#include "8k.h"


//**************************************************************************
//  DEVICE DEFINITIONS
//**************************************************************************

DEFINE_DEVICE_TYPE(ACORN_8K, acorn_8k_device, "acorn_8k", "Acorn 8K Static Memory Board")


//-------------------------------------------------
//  INPUT_PORTS( 8k )
//-------------------------------------------------

INPUT_PORTS_START( 8k )
	PORT_START("LINKS")
	PORT_CONFNAME(0x07, 0x01, "Address Selection (RAM)")
	PORT_CONFSETTING(0x00, "&0000-&1FFF")
	PORT_CONFSETTING(0x01, "&2000-&3FFF")
	PORT_CONFSETTING(0x02, "&4000-&5FFF")
	PORT_CONFSETTING(0x03, "&6000-&7FFF")
	PORT_CONFSETTING(0x04, "&8000-&9FFF")
	PORT_CONFSETTING(0x05, "&A000-&BFFF")
	PORT_CONFSETTING(0x06, "&C000-&DFFF")
	PORT_CONFSETTING(0x07, "&E000-&FFFF")
	PORT_CONFNAME(0x70, 0x50, "Address Selection (ROM)")
	PORT_CONFSETTING(0x00, "&0000-&1FFF")
	PORT_CONFSETTING(0x10, "&2000-&3FFF")
	PORT_CONFSETTING(0x20, "&4000-&5FFF")
	PORT_CONFSETTING(0x30, "&6000-&7FFF")
	PORT_CONFSETTING(0x40, "&8000-&9FFF")
	PORT_CONFSETTING(0x50, "&A000-&BFFF")
	PORT_CONFSETTING(0x60, "&C000-&DFFF")
	PORT_CONFSETTING(0x70, "&E000-&FFFF")
INPUT_PORTS_END


//-------------------------------------------------
//  input_ports - device-specific input ports
//-------------------------------------------------

ioport_constructor acorn_8k_device::device_input_ports() const
{
	return INPUT_PORTS_NAME( 8k );
}


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

void acorn_8k_device::device_add_mconfig(machine_config &config)
{
	/* rom sockets */
	GENERIC_SOCKET(config, "rom0", generic_plain_slot, "acrnsys_rom", "bin,rom").set_device_load(FUNC(acorn_8k_device::rom0_load)); // IC17
	GENERIC_SOCKET(config, "rom1", generic_plain_slot, "acrnsys_rom", "bin,rom").set_device_load(FUNC(acorn_8k_device::rom1_load)); // IC18
}


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

//-------------------------------------------------
//  acorn_8k_device - constructor
//-------------------------------------------------

acorn_8k_device::acorn_8k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, ACORN_8K, tag, owner, clock)
	, device_acorn_bus_interface(mconfig, *this)
	, m_rom(*this, "rom%u", 0)
	, m_links(*this, "LINKS")
{
}


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

void acorn_8k_device::device_start()
{
}

//-------------------------------------------------
//  device_reset - device-specific reset
//-------------------------------------------------

void acorn_8k_device::device_reset()
{
	address_space &space = m_bus->memspace();

	uint16_t ram_addr = (m_links->read() & 0x0f) << 13;

	if (ram_addr == 0x0000) // BLK0
	{
		space.install_ram(0x1000, 0x1fff);
	}
	else
	{
		space.install_ram(ram_addr, ram_addr + 0x1fff);
	}

	uint16_t rom_addr = (m_links->read() & 0xf0) << 9;

	if (m_rom[0]->exists() && rom_addr != 0x0000) // BLK0
	{
		space.install_rom(rom_addr + 0x0000, rom_addr + 0x0fff, m_rom[0]->get_rom_base());
	}
	if (m_rom[1]->exists() && rom_addr != 0xe000) // don't replace OS in page F
	{
		space.install_rom(rom_addr + 0x1000, rom_addr + 0x1fff, m_rom[1]->get_rom_base());
	}
}


//**************************************************************************
//  IMPLEMENTATION
//**************************************************************************

image_init_result acorn_8k_device::load_rom(device_image_interface &image, generic_slot_device *slot)
{
	uint32_t size = slot->common_get_size("rom");

	// socket accepts 2K and 4K ROM only
	if (size != 0x0800 && size != 0x1000)
	{
		image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid size: Only 2K/4K is supported");
		return image_init_result::FAIL;
	}

	slot->rom_alloc(0x1000, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
	slot->common_load_rom(slot->get_rom_base(), size, "rom");

	// mirror 2K ROMs
	uint8_t *rom = slot->get_rom_base();
	if (size <= 0x0800) memcpy(rom + 0x0800, rom, 0x0800);

	return image_init_result::PASS;
}