summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/nes_vt_soc.h
blob: d4289aaa2fa8bff3df3b733af01fe3173493da06 (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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// license:BSD-3-Clause
// copyright-holders:David Haywood
#ifndef MAME_MACHINE_NES_VT_SOC_H
#define MAME_MACHINE_NES_VT_SOC_H

#pragma once

#include "cpu/m6502/n2a03.h"
#include "sound/nes_apu_vt.h"
#include "machine/m6502_vtscr.h"
#include "machine/m6502_swap_op_d5_d6.h"
#include "video/ppu2c0x_vt.h"
#include "screen.h"
#include "speaker.h"

class nes_vt02_vt03_soc_device : public device_t, public device_memory_interface
{
public:
	nes_vt02_vt03_soc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	void program_map(address_map &map);

	void vt03_8000_mapper_w(offs_t offset, uint8_t data);

	// 8-bit ports
	auto write_0_callback() { return m_write_0_callback.bind(); }
	auto read_0_callback() { return m_read_0_callback.bind(); }
	auto read_1_callback() { return m_read_1_callback.bind(); }

	// 4-bit ports
	auto extra_read_0_callback() { return m_extra_read_0_callback.bind(); }
	auto extra_read_1_callback() { return m_extra_read_1_callback.bind(); }
	auto extra_read_2_callback() { return m_extra_read_2_callback.bind(); }
	auto extra_read_3_callback() { return m_extra_read_3_callback.bind(); }

	auto extra_write_0_callback() { return m_extra_write_0_callback.bind(); }
	auto extra_write_1_callback() { return m_extra_write_1_callback.bind(); }
	auto extra_write_2_callback() { return m_extra_write_2_callback.bind(); }
	auto extra_write_3_callback() { return m_extra_write_3_callback.bind(); }

	void set_201x_descramble(uint8_t reg0, uint8_t reg1, uint8_t reg2, uint8_t reg3, uint8_t reg4, uint8_t reg5)
	{
		m_2012_2017_descramble[0] = reg0; // TOOD: name regs
		m_2012_2017_descramble[1] = reg1;
		m_2012_2017_descramble[2] = reg2;
		m_2012_2017_descramble[3] = reg3;
		m_2012_2017_descramble[4] = reg4;
		m_2012_2017_descramble[5] = reg5;
	};

	void set_8000_scramble(uint8_t reg0, uint8_t reg1, uint8_t reg2, uint8_t reg3, uint8_t reg4, uint8_t reg5, uint8_t reg6, uint8_t reg7);
	void set_410x_scramble(uint8_t reg0, uint8_t reg1);
	void force_bad_dma() { m_force_baddma = true; }
	void force_raster_timing_hack() { m_use_raster_timing_hack = true; }

	void set_default_palette_mode(vtxx_pal_mode pmode) { m_default_palette_mode = pmode; }

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

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

	virtual space_config_vector memory_space_config() const override;
	virtual void device_add_mconfig(machine_config &config) override;

	required_device<cpu_device> m_maincpu;
	required_device<screen_device> m_screen;
	required_device<ppu_vt03_device> m_ppu;
	required_device<nes_apu_vt_device> m_apu;

	void nes_vt_map(address_map& map);

	uint32_t get_banks(uint8_t bnk);
	void update_banks();
	uint16_t decode_nt_addr(uint16_t addr);
	void vt03_410x_w(offs_t offset, uint8_t data);
	uint8_t vt03_410x_r(offs_t offset);
	void scrambled_410x_w(uint16_t offset, uint8_t data);
	uint8_t spr_r(offs_t offset);
	uint8_t chr_r(offs_t offset);
	void chr_w(offs_t offset, uint8_t data);
	void scanline_irq(int scanline, int vblank, int blanked);
	void hblank_irq(int scanline, int vblank, int blanked);
	void video_irq(bool hblank, int scanline, int vblank, int blanked);
	uint8_t nt_r(offs_t offset);
	void nt_w(offs_t offset, uint8_t data);
	int calculate_real_video_address(int addr, int extended, int readtype);
	void scrambled_8000_w(uint16_t offset, uint8_t data);
	uint8_t psg1_4014_r();
	uint8_t psg1_4015_r();
	void psg1_4015_w(uint8_t data);
	void psg1_4017_w(uint8_t data);
	void vt_dma_w(uint8_t data);
	void do_dma(uint8_t data, bool has_ntsc_bug);
	void vt03_4034_w(uint8_t data);

	uint8_t in0_r();
	uint8_t in1_r();
	void in0_w(offs_t offset, uint8_t data);

	void extra_io_control_w(uint8_t data);
	uint8_t extrain_01_r();
	uint8_t extrain_23_r();
	void extraout_01_w(uint8_t data);
	void extraout_23_w(uint8_t data);
	uint8_t rs232flags_region_r();

	uint32_t screen_update(screen_device& screen, bitmap_rgb32& bitmap, const rectangle& cliprect);

	uint8_t m_410x[0xc];

	uint8_t m_vdma_ctrl;
	int m_timer_irq_enabled;
	int m_timer_running;
	int m_timer_val;

	uint8_t m_8000_scramble[8];
	uint8_t m_410x_scramble[2];

	uint8_t m_8000_addr_latch;

	uint8_t m_4242;
	uint8_t m_411c;
	uint8_t m_411d;

	uint8_t m_initial_e000_bank;
	/* expansion nametable - todo, see if we can refactor NES code to be reusable without having to add full NES bus etc. */
	std::unique_ptr<uint8_t[]> m_ntram;
	std::unique_ptr<uint8_t[]> m_chrram;

	DECLARE_WRITE_LINE_MEMBER(apu_irq);
	uint8_t apu_read_mem(offs_t offset);

	uint8_t external_space_read(offs_t offset);
	void external_space_write(offs_t offset, uint8_t data);

	void do_pal_timings_and_ppu_replacement(machine_config& config);

private:

	address_space_config        m_space_config;

	int m_bankaddr[4];

	devcb_write8 m_write_0_callback;
	devcb_read8 m_read_0_callback;
	devcb_read8 m_read_1_callback;

	devcb_write8 m_extra_write_0_callback;
	devcb_write8 m_extra_write_1_callback;
	devcb_write8 m_extra_write_2_callback;
	devcb_write8 m_extra_write_3_callback;

	devcb_read8 m_extra_read_0_callback;
	devcb_read8 m_extra_read_1_callback;
	devcb_read8 m_extra_read_2_callback;
	devcb_read8 m_extra_read_3_callback;

	uint8_t m_2012_2017_descramble[0x6]; // passed to PPU in reset
	vtxx_pal_mode m_default_palette_mode;
	bool m_force_baddma;
	bool m_use_raster_timing_hack;
};

class nes_vt02_vt03_soc_pal_device : public nes_vt02_vt03_soc_device
{
public:
	nes_vt02_vt03_soc_pal_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock);

protected:
	virtual void device_add_mconfig(machine_config& config) override;
};

class nes_vt02_vt03_soc_scramble_device : public nes_vt02_vt03_soc_device
{
public:
	nes_vt02_vt03_soc_scramble_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock);

protected:
	virtual void device_add_mconfig(machine_config& config) override;
};

DECLARE_DEVICE_TYPE(NES_VT02_VT03_SOC, nes_vt02_vt03_soc_device)
DECLARE_DEVICE_TYPE(NES_VT02_VT03_SOC_PAL, nes_vt02_vt03_soc_pal_device)
DECLARE_DEVICE_TYPE(NES_VT02_VT03_SOC_SCRAMBLE, nes_vt02_vt03_soc_scramble_device)

#endif // MAME_MACHINE_NES_VT_SOC_H