summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/video/voodoo_2.h
blob: 9a6f0c9ef0104589d6e86e9afc5b0bc41bf4f992 (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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    voodoo_2.h

    3dfx Voodoo Graphics SST-1/2 emulator.

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

#ifndef MAME_VIDEO_VOODOO_2_H
#define MAME_VIDEO_VOODOO_2_H

#pragma once

#include "voodoo.h"


// forward declarations
class voodoo_2_device;


//**************************************************************************
//  INTERNAL CLASSES
//**************************************************************************

namespace voodoo
{

// ======================> command_fifo

// command_fifo is a more intelligent FIFO that was introduced with the Voodoo-2
class command_fifo
{
public:
	// construction
	command_fifo(voodoo_2_device &device);

	// initialization
	void init(u8 *ram, u32 size) { m_ram = (u32 *)ram; m_mask = (size / 4) - 1; }

	// state saving
	void register_save(save_proxy &save);

	// getters
	bool enabled() const { return m_enable; }
	u32 address_min() const { return m_address_min; }
	u32 address_max() const { return m_address_max; }
	u32 read_pointer() const { return m_read_index * 4; }
	u32 depth() const { return m_depth; }
	u32 holes() const { return m_holes; }

	// setters
	void set_enable(bool enabled) { m_enable = enabled; }
	void set_count_holes(bool count) { m_count_holes = count; }
	void set_base(u32 base) { m_ram_base = base; }
	void set_end(u32 end) { m_ram_end = end; }
	void set_size(u32 size) { m_ram_end = m_ram_base + size; }
	void set_read_pointer(u32 ptr) { m_read_index = ptr / 4; }
	void set_address_min(u32 addr) { m_address_min = addr; }
	void set_address_max(u32 addr) { m_address_max = addr; }
	void set_depth(u32 depth) { m_depth = depth; }
	void set_holes(u32 holes) { m_holes = holes; }

	// operations
	u32 execute_if_ready();

	// write to the FIFO if within the address range
	bool write_if_in_range(offs_t addr, u32 data)
	{
		if (m_enable && addr >= m_ram_base && addr < m_ram_end)
		{
			write(addr, data);
			return true;
		}
		return false;
	}

	// write directly to the FIFO, relative to the base
	void write_direct(offs_t offset, u32 data)
	{
		write(m_ram_base + offset * 4, data);
	}

private:
	// internal helpers
	void consume(u32 words) { m_read_index += words; m_depth -= words; }
	u32 peek_next() { return m_ram[m_read_index & m_mask]; }
	u32 read_next() { u32 result = peek_next(); consume(1); return result; }
	float read_next_float() { float result = *(float *)&m_ram[m_read_index & m_mask]; consume(1); return result; }

	// internal operations
	u32 words_needed(u32 command);
	void write(offs_t addr, u32 data);

	// packet handlers
	using packet_handler = u32 (command_fifo::*)(u32);
	u32 packet_type_0(u32 command);
	u32 packet_type_1(u32 command);
	u32 packet_type_2(u32 command);
	u32 packet_type_3(u32 command);
	u32 packet_type_4(u32 command);
	u32 packet_type_5(u32 command);
	u32 packet_type_unknown(u32 command);

	// internal state
	voodoo_2_device &m_device;     // reference to our device
	u32 *m_ram;                    // base of RAM
	u32 m_mask;                    // mask for RAM accesses
	bool m_enable;                 // enabled?
	bool m_count_holes;            // count holes?
	u32 m_ram_base;                // base address in framebuffer RAM
	u32 m_ram_end;                 // end address in framebuffer RAM
	u32 m_read_index;              // current read index into 32-bit RAM
	u32 m_address_min;             // minimum address
	u32 m_address_max;             // maximum address
	u32 m_depth;                   // current depth
	u32 m_holes;                   // number of holes

	static packet_handler s_packet_handler[8];
};


// ======================> setup_vertex

// setup_vertex a set of coordinates managed by the triangle setup engine
// that was introduced with the Voodoo-2
struct setup_vertex
{
	// state saving
	void register_save(save_proxy &save)
	{
		save.save_item(NAME(x));
		save.save_item(NAME(y));
		save.save_item(NAME(z));
		save.save_item(NAME(wb));
		save.save_item(NAME(r));
		save.save_item(NAME(g));
		save.save_item(NAME(b));
		save.save_item(NAME(a));
		save.save_item(NAME(s0));
		save.save_item(NAME(t0));
		save.save_item(NAME(w0));
		save.save_item(NAME(s1));
		save.save_item(NAME(t1));
		save.save_item(NAME(w1));
	}

	float x, y;               // X, Y coordinates
	float z, wb;              // Z and broadcast W values
	float r, g, b, a;         // A, R, G, B values
	float s0, t0, w0;         // W, S, T for TMU 0
	float s1, t1, w1;         // W, S, T for TMU 1
};

}


//**************************************************************************
//  VOODOO 2 DEVICE
//**************************************************************************

DECLARE_DEVICE_TYPE(VOODOO_2, voodoo_2_device)

// ======================> voodoo_2_device

// voodoo_2_device represents the 2nd generation of 3dfx Voodoo Graphics devices;
// these are pretty similar in architecture to the first generation, with the
// addition of command FIFOs and several other smaller features
class voodoo_2_device : public voodoo_1_device
{
	friend class voodoo::command_fifo;

protected:
	// internal construction
	voodoo_2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, voodoo::voodoo_model model);

public:
	// nominal clock value
	static constexpr u32 NOMINAL_CLOCK = 90'000'000;

	// construction
	voodoo_2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
		voodoo_2_device(mconfig, VOODOO_2, tag, owner, clock, voodoo::voodoo_model::VOODOO_2) { }

	// address map and read/write helpers
	virtual void core_map(address_map &map) override;
	virtual u32 read(offs_t offset, u32 mem_mask = ~0) override;
	virtual void write(offs_t offset, u32 data, u32 mem_mask = ~0) override;

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

	// system management
	virtual void soft_reset() override;
	virtual void register_save(voodoo::save_proxy &save, u32 total_allocation) override;

	// mapped writes
	void map_register_w(offs_t offset, u32 data, u32 mem_mask = ~0);

	// read/write and FIFO helpers
	virtual u32 execute_fifos() override;

	// register read accessors
	u32 reg_hvretrace_r(u32 chipmask, u32 regnum);
	u32 reg_cmdfifoptr_r(u32 chipmask, u32 regnum);
	u32 reg_cmdfifodepth_r(u32 chipmask, u32 regnum);
	u32 reg_cmdfifoholes_r(u32 chipmask, u32 regnum);

	// register write accessors
	u32 reg_intrctrl_w(u32 chipmask, u32 regnum, u32 data);
	u32 reg_video2_w(u32 chipmask, u32 regnum, u32 data);
	u32 reg_sargb_w(u32 chipmask, u32 regnum, u32 data);
	u32 reg_userintr_w(u32 chipmask, u32 regnum, u32 data);
	u32 reg_cmdfifo_w(u32 chipmask, u32 regnum, u32 data);
	u32 reg_cmdfifoptr_w(u32 chipmask, u32 regnum, u32 data);
	u32 reg_cmdfifodepth_w(u32 chipmask, u32 regnum, u32 data);
	u32 reg_cmdfifoholes_w(u32 chipmask, u32 regnum, u32 data);
	u32 reg_fbiinit5_7_w(u32 chipmask, u32 regnum, u32 data);
	u32 reg_draw_tri_w(u32 chipmask, u32 regnum, u32 data);
	u32 reg_begin_tri_w(u32 chipmask, u32 regnum, u32 data);

	// command FIFO-specific write handlers
	virtual u32 cmdfifo_register_w(u32 offset, u32 data);
	virtual u32 cmdfifo_2d_w(u32 offset, u32 data);

	// VBLANK timing
	virtual void vblank_start(void *ptr, s32 param) override;
	virtual void vblank_stop(void *ptr, s32 param) override;

	// video timing and updates
	virtual void recompute_video_memory() override;

	// rendering
	s32 begin_triangle();
	s32 draw_triangle();
	s32 setup_and_draw_triangle();

	// internal state
	u8 m_sverts = 0;                         // number of vertices ready
	voodoo::setup_vertex m_svert[3];         // 3 setup vertices
	voodoo::command_fifo m_cmdfifo;          // command FIFO

	// register table
	static voodoo::static_register_table_entry<voodoo_2_device> const s_register_table[256];
};

#endif // MAME_VIDEO_VOODOO_2_H