summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/video/voodoo_2.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/video/voodoo_2.h')
-rw-r--r--src/devices/video/voodoo_2.h249
1 files changed, 249 insertions, 0 deletions
diff --git a/src/devices/video/voodoo_2.h b/src/devices/video/voodoo_2.h
new file mode 100644
index 00000000000..9a6f0c9ef01
--- /dev/null
+++ b/src/devices/video/voodoo_2.h
@@ -0,0 +1,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