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(s32 param) override;
virtual void vblank_stop(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
|