summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/315_5195.h
blob: bc95415a2cd29e60aacdc1c3cb5fefe2575765e6 (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
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    Sega 315-5195 memory mapper

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

#ifndef MAME_MACHINE_315_5195_H
#define MAME_MACHINE_315_5195_H

#pragma once

#include "cpu/m68000/m68000.h"
#include "machine/fd1089.h"
#include "machine/fd1094.h"


//**************************************************************************
//  TYPE DEFINITIONS
//**************************************************************************


// ======================> sega_315_5195_mapper_device

class sega_315_5195_mapper_device : public device_t
{
public:
	typedef device_delegate<void (sega_315_5195_mapper_device &, u8)> mapper_delegate;

	// construction/destruction
	template <typename T>
	sega_315_5195_mapper_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, T &&cpu_tag)
		: sega_315_5195_mapper_device(mconfig, tag, owner, clock)
	{
		m_cpu.set_tag(std::forward<T>(cpu_tag));
		m_cpuregion.set_tag(std::forward<T>(cpu_tag));
	}

	sega_315_5195_mapper_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);

	// configuration helpers
	template <typename... T> void set_mapper(T &&... args) { m_mapper.set(std::forward<T>(args)...); }

	auto pbf() { return m_pbf_callback.bind(); }
	auto mcu_int() { return m_mcu_int_callback.bind(); }

	// public interface
	u8 read(address_space &space, offs_t offset);
	void write(offs_t offset, u8 data);
	u8 pread();
	void pwrite(u8 data);

	// mapping helpers
	void map_as_rom(u32 offset, u32 length, offs_t mirror, const char *bank_name, const char *decrypted_bank_name, offs_t rgnoffset, write16_delegate whandler);
	void map_as_ram(u32 offset, u32 length, offs_t mirror, const char *bank_share_name, write16_delegate whandler);
	void map_as_handler(u32 offset, u32 length, offs_t mirror, read16_delegate rhandler, write16_delegate whandler);

	// perform an explicit configuration (for bootlegs with hard-coded mappings)
	void configure_explicit(const u8 *map_data);

	// open bus read helpers
	u16 open_bus_r();

protected:
	// device-level overrides
	virtual void device_start() override;
	virtual void device_reset() override;

private:
	TIMER_CALLBACK_MEMBER(write_to_sound);
	TIMER_CALLBACK_MEMBER(write_from_sound);

	// internal region struct
	struct region_info
	{
		offs_t  size_mask;
		offs_t  base;
		offs_t  mirror;
		offs_t  start;
		offs_t  end;
	};

	// helper class for tracking banks mapped to ROM regions
	class decrypt_bank
	{
	public:
		// construction/destruction
		decrypt_bank();
		~decrypt_bank();

		// configuration
		void set_decrypt(fd1089_base_device *fd1089);
		void set_decrypt(fd1094_device *fd1094);
		void clear() { set(nullptr, nullptr, 0, 0, ~0, nullptr); }
		void set(memory_bank *bank, memory_bank *decrypted_bank, offs_t start, offs_t end, offs_t rgnoffs, u8 *src);

		// updating
		void update();
		void reset() { m_fd1089_decrypted.clear(); if (m_fd1094_cache != nullptr) m_fd1094_cache->reset(); }

	private:
		// internal state
		memory_bank *      m_bank;
		memory_bank *      m_decrypted_bank;
		offs_t             m_start;
		offs_t             m_end;
		offs_t             m_rgnoffs;
		u8 *               m_srcptr;
		fd1089_base_device *m_fd1089;
		std::vector<u16>   m_fd1089_decrypted;
		std::unique_ptr<fd1094_decryption_cache> m_fd1094_cache;
	};

	// internal helpers
	void compute_region(region_info &info, u8 index, u32 length, u32 mirror, u32 offset = 0);
	void update_mapping();
	void fd1094_state_change(u8 state);

	// configuration
	required_device<m68000_device> m_cpu;
	required_memory_region      m_cpuregion;
	mapper_delegate             m_mapper;
	devcb_write_line            m_pbf_callback;
	devcb_write_line            m_mcu_int_callback;

	// internal state
	address_space *        m_space;
	address_space *        m_decrypted_space;
	u8                     m_regs[0x20];
	u8                     m_curregion;
	decrypt_bank           m_banks[8];

	// communication registers
	u8                     m_to_sound;
	u8                     m_from_sound;

	// flag to track recursion through open_bus_r
	bool     m_open_bus_recurse;
};


// device type definition
DECLARE_DEVICE_TYPE(SEGA_315_5195_MEM_MAPPER, sega_315_5195_mapper_device)


#endif // MAME_MACHINE_315_5195_H