summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/deco146.h
blob: 31a4b5a4af5c56a56068f05b950de87a27a52ef8 (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
// license:BSD-3-Clause
// copyright-holders:David Haywood, Charles MacDonald
#ifndef MAME_MACHINE_DECO146_H
#define MAME_MACHINE_DECO146_H

#pragma once

#include "machine/gen_latch.h"

#define BLK (0xff)
#define INPUT_PORT_A (-1)
#define INPUT_PORT_B (-2)
#define INPUT_PORT_C (-3)


#define NIB3__ 0xc, 0xd, 0xe, 0xf
#define NIB3R1 0xd, 0xe, 0xf, 0xc
#define NIB3R2 0xe, 0xf, 0xc, 0xd
#define NIB3R3 0xf, 0xc, 0xd, 0xe

#define NIB2__ 0x8, 0x9, 0xa, 0xb
#define NIB2R1 0x9, 0xa, 0xb, 0x8
#define NIB2R2 0xa, 0xb, 0x8, 0x9
#define NIB2R3 0xb, 0x8, 0x9, 0xa

#define NIB1__ 0x4, 0x5, 0x6, 0x7
#define NIB1R1 0x5, 0x6, 0x7, 0x4
#define NIB1R2 0x6, 0x7, 0x4, 0x5
#define NIB1R3 0x7, 0x4, 0x5, 0x6

#define NIB0__ 0x0, 0x1, 0x2, 0x3
#define NIB0R1 0x1, 0x2, 0x3, 0x0
#define NIB0R2 0x2, 0x3, 0x0, 0x1
#define NIB0R3 0x3, 0x0, 0x1, 0x2

#define BLANK_ BLK, BLK, BLK, BLK

struct deco146port_xx
{
	int write_offset;
	u8 mapping[16];
	int use_xor;
	int use_nand;
};


/* Data East 146 protection chip */

class deco_146_base_device : public device_t
{
public:
	void write_data(u16 address, u16 data, u16 mem_mask, u8 &csflags);
	u16 read_data(u16 address, u8 &csflags);

	auto port_a_cb() { return m_port_a_r.bind(); }
	auto port_b_cb() { return m_port_b_r.bind(); }
	auto port_c_cb() { return m_port_c_r.bind(); }

	// there are some standard ways the chip gets hooked up, so have them here ready to use
	void set_interface_scramble(u8 a9, u8 a8, u8 a7, u8 a6, u8 a5, u8 a4, u8 a3,u8 a2,u8 a1,u8 a0)
	{
		m_external_addrswap[9] = a9;
		m_external_addrswap[8] = a8;
		m_external_addrswap[7] = a7;
		m_external_addrswap[6] = a6;
		m_external_addrswap[5] = a5;
		m_external_addrswap[4] = a4;
		m_external_addrswap[3] = a3;
		m_external_addrswap[2] = a2;
		m_external_addrswap[1] = a1;
		m_external_addrswap[0] = a0;
	}
	void set_interface_scramble_reverse() { set_interface_scramble(0,1,2,3,4,5,6,7,8,9); }
	void set_interface_scramble_interleave() { set_interface_scramble(4, 5, 3, 6, 2, 7, 1, 8, 0, 9); }
	void set_use_magic_read_address_xor(bool use_xor) { m_magic_read_address_xor_enabled = use_xor; }

	auto soundlatch_irq_cb() { return m_soundlatch_irq_cb.bind(); }

	u8 soundlatch_r();

	devcb_read16 m_port_a_r;
	devcb_read16 m_port_b_r;
	devcb_read16 m_port_c_r;

	u8 m_bankswitch_swap_read_address;
	u16 m_magic_read_address_xor;
	bool m_magic_read_address_xor_enabled;
	u8 m_xor_port;
	u8 m_mask_port;
	u8 m_soundlatch_port;

	u8 m_external_addrswap[10];

	deco146port_xx const *m_lookup_table;

protected:
	deco_146_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);

	virtual void device_start() override;
	virtual void device_reset() override;

	u16 read_protport(u16 address);
	virtual void write_protport(u16 address, u16 data, u16 mem_mask);
	virtual u16 read_data_getloc(u16 address, int& location);

	std::unique_ptr<u16[]> m_rambank[2];

	int m_current_rambank;

	u16 m_nand;
	u16 m_xor;

	u16 m_latchaddr;
	u16 m_latchdata;

	u8 m_configregion; // which value of upper 4 address lines accesses the config region
	int m_latchflag;

private:
	TIMER_CALLBACK_MEMBER(write_soundlatch);

	u8 region_selects[6];

	u8 m_soundlatch;
	devcb_write_line m_soundlatch_irq_cb;
};

class deco146_device : public deco_146_base_device
{
public:
	deco146_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};

DECLARE_DEVICE_TYPE(DECO146PROT, deco146_device)

#endif // MAME_MACHINE_DECO146_H