summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/video/ps2gif.h
blob: 2cd7215269e90762691c5b7f55e130ccd291b17f (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:Ryan Holtz
/******************************************************************************
*
*   Sony Playstation 2 GS Interface (GIF) device skeleton
*
*   To Do:
*     Everything
*
*/

#ifndef DEVICES_VIDEO_PS2GIF_H
#define DEVICES_VIDEO_PS2GIF_H

#pragma once

#include "emu.h"

class ps2_gs_device;
class sonyvu1_device;

class ps2_gif_device : public device_t, public device_execute_interface
{
public:
	template <typename T, typename U>
    ps2_gif_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&gs_tag, U &&vu1_tag)
    	: ps2_gif_device(mconfig, tag, owner, clock)
    {
		m_gs.set_tag(std::forward<T>(gs_tag));
		m_vu1.set_tag(std::forward<U>(vu1_tag));
	}

    ps2_gif_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	DECLARE_READ32_MEMBER(read);
	DECLARE_WRITE32_MEMBER(write);

	void kick_path1(uint32_t address);
	void write_path1(uint64_t hi, uint64_t lo);
	void write_path3(uint64_t hi, uint64_t lo);
	void set_path3_mask(bool masked);
	bool path1_available() const { return !m_current_path1_tag.valid(); }
	bool path3_available() const { return m_path3_available; }

protected:
    virtual void device_start() override;
    virtual void device_reset() override;
	virtual void execute_run() override;

	void fetch_path1(uint64_t &hi, uint64_t &lo);

	void gif_reset();

	class tag_t
	{
	public:
		tag_t() : m_nloop(0), m_end(false), m_prim_enable(false), m_prim_output(false), m_prim(0), m_format(FMT_DISABLE), m_reg_count(0), m_curr_reg(0)
		{
			memset(m_regs, 0, 16);
			memset(m_words, 0, sizeof(uint32_t) * 4);
		}
		tag_t(uint64_t lo, uint64_t hi);

		enum format_t : uint8_t
		{
			FMT_PACKED = 0,
			FMT_REGLIST,
			FMT_IMAGE,
			FMT_DISABLE
		};

		bool valid() const { return m_nloop != 0; }
		uint16_t nloop() const { return m_nloop; }
		bool end() const { return m_end; }
		bool is_prim() const { return m_prim_enable; }
		bool is_prim_output() const { return m_prim_output; }
		void set_prim_output() { m_prim_output = true; }
		uint16_t prim() const { return m_prim; }
		format_t format() const { return m_format; }
		uint32_t word(offs_t index) const { return m_words[index]; }
		uint32_t reg() const { return m_regs[m_curr_reg]; }

		void loop() { m_nloop--; }
		void next_reg();

	protected:
		uint16_t m_nloop;
		bool m_end;
		bool m_prim_enable;
		bool m_prim_output;
		uint16_t m_prim;
		format_t m_format;
		uint8_t m_reg_count;
		uint8_t m_curr_reg;
		uint8_t m_regs[16];
		uint32_t m_words[4];
	};

	void process_tag(tag_t &tag, uint64_t hi, uint64_t lo);

	enum : uint32_t
	{
		CTRL_RST = (1 << 0),
		CTRL_PSE = (1 << 3)
	};

	required_device<ps2_gs_device> m_gs;
	required_device<sonyvu1_device> m_vu1;

	int m_icount;

	uint32_t m_ctrl;
	uint32_t m_mode;
	uint32_t m_stat;
	tag_t m_current_path1_tag;
	tag_t m_current_path3_tag;
	tag_t m_last_tag;
	uint32_t m_cnt;
	uint32_t m_p3cnt;
	uint32_t m_p3tag;
	uint64_t m_next_path3_hi;
	uint64_t m_next_path3_lo;
	bool m_path3_available;
	bool m_p3mask;
	uint32_t m_vu_mem_address;
};

DECLARE_DEVICE_TYPE(SONYPS2_GIF, ps2_gif_device)

#endif // DEVICES_VIDEO_PS2GIF_H