summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/dirom.cpp
blob: 85cd3e3c6b3c467c6480f9a2c6a60b4a9bdcf7d9 (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
#include "emu.h"


device_rom_interface::device_rom_interface(const machine_config &mconfig, device_t &device, uint8_t addrwidth, endianness_t endian, uint8_t datawidth) :
	device_memory_interface(mconfig, device),
	m_rom_config("rom", endian, datawidth, addrwidth)
{
}

device_rom_interface::~device_rom_interface()
{
}

const address_space_config *device_rom_interface::memory_space_config(address_spacenum spacenum) const
{
	return spacenum ? nullptr : &m_rom_config;
}

void device_rom_interface::rom_bank_updated()
{
}

void device_rom_interface::set_rom_bank(int bank)
{
	if(!m_bank)
		emu_fatalerror("%s: device_rom_interface::set_rom_bank called without banking setup", device().tag());

	if(bank >= m_bank_count) {
		device().logerror("Warning: requested bank %x higher than actual bank count %x\n", bank, m_bank_count);
		bank = bank % m_bank_count;
	}

	m_cur_bank = bank;
	m_bank->set_entry(bank);
	rom_bank_updated();
}

void device_rom_interface::reset_bank()
{
	if(m_bank)
		m_bank->set_entry(m_cur_bank);
}

void device_rom_interface::set_rom(const void *base, uint32_t size)
{
	uint32_t mend = m_rom_config.addr_width() == 32 ? 0xffffffff : (1 << m_rom_config.addr_width()) - 1;
	uint32_t rend = size-1;
	m_bank_count = mend == 0xffffffff ? 1 : (rend+1) / (mend+1);
	if(m_bank_count < 1)
		m_bank_count = 1;

	if(rend >= mend) {
		space().install_read_bank(0, mend, device().tag());
		m_bank = device().machine().memory().banks().find(device().tag())->second.get();
		m_bank->configure_entries(0, m_bank_count, const_cast<void *>(base), mend+1);
		m_cur_bank = 0;

	} else {
		// Round up to the nearest power-of-two-minus-one
		uint32_t rmask = rend;
		rmask |= rmask >> 1;
		rmask |= rmask >> 2;
		rmask |= rmask >> 4;
		rmask |= rmask >> 8;
		rmask |= rmask >> 16;
		if(rmask != rend)
			space().unmap_read(0, mend);
		// Mirror over the high bits.  mend and rmask are both
		// powers-of-two-minus-one, so the xor works
		space().install_rom(0, rend, mend ^ rmask, const_cast<void *>(base));
	}
}

void device_rom_interface::interface_pre_start()
{
	m_rom_direct = &space().direct();
	m_bank = nullptr;
	m_cur_bank = -1;
	device().save_item(NAME(m_cur_bank));
	device().save_item(NAME(m_bank_count));
	device().machine().save().register_postload(save_prepost_delegate(FUNC(device_rom_interface::reset_bank), this));

	if(!has_configured_map(0)) {
		memory_region *reg = device().memregion(DEVICE_SELF);
		if(reg)
			set_rom(reg->base(), reg->bytes());
		else {
			uint32_t end = m_rom_config.addr_width() == 32 ? 0xffffffff : (1 << m_rom_config.addr_width()) - 1;
			space().unmap_read(0, end);
		}
	}
}