summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/fd1094.h
blob: ba04da2858ade667ee93ba83c639dd36fe75b020 (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
// license:BSD-3-Clause
// copyright-holders:Nicola Salmoria, Andreas Naive, Charles MacDonald
/***************************************************************************

    Hitachi FD1094 encryption emulation

****************************************************************************

    Copyright Nicola Salmoria, Andreas Naive, and Charles MacDonald.

    All rights reserved.

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

#ifndef __FD1094_H__
#define __FD1094_H__

#include "cpu/m68000/m68000.h"


//**************************************************************************
//  CONSTANTS
//**************************************************************************

// device type definition
extern const device_type FD1094;



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

class fd1094_device;


// ======================> fd1094_decryption_cache

class fd1094_decryption_cache
{
public:
	// construction/destruction
	fd1094_decryption_cache(fd1094_device &fd1094);

	// getters
	fd1094_device &fd1094() const { return m_fd1094; }
	uint16_t *decrypted_opcodes(uint8_t state);

	// operations
	void reset();
	void configure(offs_t baseaddress, uint32_t size, offs_t rgnoffset);

protected:
	// internal state
	fd1094_device &         m_fd1094;
	uint32_t                  m_baseaddress;
	uint32_t                  m_size;
	uint32_t                  m_rgnoffset;
	std::vector<uint16_t>     m_decrypted_opcodes[256];
};


// ======================> fd1094_device

// base device, shared implementation between A and B variants
class fd1094_device : public m68000_device
{
public:
	typedef delegate<void (uint8_t)> state_change_delegate;

	// construction/destruction
	fd1094_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	// explicit decryption helpers
	void decrypt(offs_t baseaddr, uint32_t size, offs_t regionoffs, uint16_t *opcodesptr, uint8_t state) { decrypt(baseaddr, size, &m_srcbase[regionoffs/2], opcodesptr, state); }

	// live state management
	uint8_t state() const { return m_irqmode ? m_key[0] : m_state; }
	void change_state(int newstate = -1);
	void notify_state_change(state_change_delegate callback) { m_state_change = callback; }

	// constants
	enum
	{
		STATE_RESET = 0x100,
		STATE_IRQ = 0x200,
		STATE_RTE = 0x300
	};

protected:
	required_memory_bank m_decrypted_opcodes_bank;

	// device overrides
	virtual void device_start() override;
	virtual void device_reset() override;
	virtual void device_postload();

	// internal helpers
	uint16_t decrypt_one(offs_t address, uint16_t val, const uint8_t *main_key, uint8_t state, bool vector_fetch);
	void decrypt(offs_t baseaddr, uint32_t size, const uint16_t *srcptr, uint16_t *opcodesptr, uint8_t state);
	void default_state_change(uint8_t state);
	IRQ_CALLBACK_MEMBER( irq_callback );

	// static helpers
	DECLARE_WRITE32_MEMBER(cmp_callback);
	DECLARE_WRITE_LINE_MEMBER(rte_callback);

	// internal state
	uint8_t                   m_state;
	bool                    m_irqmode;
	state_change_delegate   m_state_change;
	fd1094_decryption_cache m_cache;
	uint16_t const            *m_srcbase;
	optional_region_ptr<uint16_t> m_rom;
	required_region_ptr<uint8_t> m_key;
	uint8_t                   m_masked_opcodes_lookup[2][65536/8/2];

	// static tables
	static const uint16_t s_masked_opcodes[];
};

struct fd1094_constraint
{
	offs_t  pc;
	uint16_t  state;
	uint16_t  value;
	uint16_t  mask;
};

#endif