summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/video/voodoo.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/video/voodoo.h')
-rw-r--r--src/devices/video/voodoo.h2009
1 files changed, 644 insertions, 1365 deletions
diff --git a/src/devices/video/voodoo.h b/src/devices/video/voodoo.h
index e33928ce78b..7c56fb985d2 100644
--- a/src/devices/video/voodoo.h
+++ b/src/devices/video/voodoo.h
@@ -13,1478 +13,757 @@
#pragma once
-#include "video/polylgcy.h"
-#include "video/rgbutil.h"
#include "screen.h"
-/*************************************
- *
- * Misc. constants
- *
- *************************************/
-
-/* enumeration describing reasons we might be stalled */
-enum
-{
- NOT_STALLED = 0,
- STALLED_UNTIL_FIFO_LWM,
- STALLED_UNTIL_FIFO_EMPTY
-};
+// forward declarations
+class voodoo_1_device;
+namespace voodoo { class save_proxy; }
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
-// Use old table lookup versus straight double divide
-#define USE_FAST_RECIP 0
-
-/* maximum number of TMUs */
-#define MAX_TMU 2
-
-/* accumulate operations less than this number of clocks */
-#define ACCUMULATE_THRESHOLD 0
-
-/* number of clocks to set up a triangle (just a guess) */
-#define TRIANGLE_SETUP_CLOCKS 100
-
-/* maximum number of rasterizers */
-#define MAX_RASTERIZERS 1024
-
-/* size of the rasterizer hash table */
-#define RASTER_HASH_SIZE 97
-
-/* flags for LFB writes */
-#define LFB_RGB_PRESENT 1
-#define LFB_ALPHA_PRESENT 2
-#define LFB_DEPTH_PRESENT 4
-#define LFB_DEPTH_PRESENT_MSW 8
-
-/* flags for the register access array */
-#define REGISTER_READ 0x01 /* reads are allowed */
-#define REGISTER_WRITE 0x02 /* writes are allowed */
-#define REGISTER_PIPELINED 0x04 /* writes are pipelined */
-#define REGISTER_FIFO 0x08 /* writes go to FIFO */
-#define REGISTER_WRITETHRU 0x10 /* writes are valid even for CMDFIFO */
-
-/* shorter combinations to make the table smaller */
-#define REG_R (REGISTER_READ)
-#define REG_W (REGISTER_WRITE)
-#define REG_WT (REGISTER_WRITE | REGISTER_WRITETHRU)
-#define REG_RW (REGISTER_READ | REGISTER_WRITE)
-#define REG_RWT (REGISTER_READ | REGISTER_WRITE | REGISTER_WRITETHRU)
-#define REG_RP (REGISTER_READ | REGISTER_PIPELINED)
-#define REG_WP (REGISTER_WRITE | REGISTER_PIPELINED)
-#define REG_RWP (REGISTER_READ | REGISTER_WRITE | REGISTER_PIPELINED)
-#define REG_RWPT (REGISTER_READ | REGISTER_WRITE | REGISTER_PIPELINED | REGISTER_WRITETHRU)
-#define REG_RF (REGISTER_READ | REGISTER_FIFO)
-#define REG_WF (REGISTER_WRITE | REGISTER_FIFO)
-#define REG_RWF (REGISTER_READ | REGISTER_WRITE | REGISTER_FIFO)
-#define REG_RPF (REGISTER_READ | REGISTER_PIPELINED | REGISTER_FIFO)
-#define REG_WPF (REGISTER_WRITE | REGISTER_PIPELINED | REGISTER_FIFO)
-#define REG_RWPF (REGISTER_READ | REGISTER_WRITE | REGISTER_PIPELINED | REGISTER_FIFO)
-
-/* lookup bits is the log2 of the size of the reciprocal/log table */
-#define RECIPLOG_LOOKUP_BITS 9
-
-/* input precision is how many fraction bits the input value has; this is a 64-bit number */
-#define RECIPLOG_INPUT_PREC 32
-
-/* lookup precision is how many fraction bits each table entry contains */
-#define RECIPLOG_LOOKUP_PREC 22
-
-/* output precision is how many fraction bits the result should have */
-#define RECIP_OUTPUT_PREC 15
-#define LOG_OUTPUT_PREC 8
-
-
-
-/*************************************
- *
- * Register constants
- *
- *************************************/
-
-/* Codes to the right:
- R = readable
- W = writeable
- P = pipelined
- F = goes to FIFO
-*/
-
-/* 0x000 */
-#define vdstatus (0x000/4) /* R P */
-#define intrCtrl (0x004/4) /* RW P -- Voodoo2/Banshee only */
-#define vertexAx (0x008/4) /* W PF */
-#define vertexAy (0x00c/4) /* W PF */
-#define vertexBx (0x010/4) /* W PF */
-#define vertexBy (0x014/4) /* W PF */
-#define vertexCx (0x018/4) /* W PF */
-#define vertexCy (0x01c/4) /* W PF */
-#define startR (0x020/4) /* W PF */
-#define startG (0x024/4) /* W PF */
-#define startB (0x028/4) /* W PF */
-#define startZ (0x02c/4) /* W PF */
-#define startA (0x030/4) /* W PF */
-#define startS (0x034/4) /* W PF */
-#define startT (0x038/4) /* W PF */
-#define startW (0x03c/4) /* W PF */
-
-/* 0x040 */
-#define dRdX (0x040/4) /* W PF */
-#define dGdX (0x044/4) /* W PF */
-#define dBdX (0x048/4) /* W PF */
-#define dZdX (0x04c/4) /* W PF */
-#define dAdX (0x050/4) /* W PF */
-#define dSdX (0x054/4) /* W PF */
-#define dTdX (0x058/4) /* W PF */
-#define dWdX (0x05c/4) /* W PF */
-#define dRdY (0x060/4) /* W PF */
-#define dGdY (0x064/4) /* W PF */
-#define dBdY (0x068/4) /* W PF */
-#define dZdY (0x06c/4) /* W PF */
-#define dAdY (0x070/4) /* W PF */
-#define dSdY (0x074/4) /* W PF */
-#define dTdY (0x078/4) /* W PF */
-#define dWdY (0x07c/4) /* W PF */
-
-/* 0x080 */
-#define triangleCMD (0x080/4) /* W PF */
-#define fvertexAx (0x088/4) /* W PF */
-#define fvertexAy (0x08c/4) /* W PF */
-#define fvertexBx (0x090/4) /* W PF */
-#define fvertexBy (0x094/4) /* W PF */
-#define fvertexCx (0x098/4) /* W PF */
-#define fvertexCy (0x09c/4) /* W PF */
-#define fstartR (0x0a0/4) /* W PF */
-#define fstartG (0x0a4/4) /* W PF */
-#define fstartB (0x0a8/4) /* W PF */
-#define fstartZ (0x0ac/4) /* W PF */
-#define fstartA (0x0b0/4) /* W PF */
-#define fstartS (0x0b4/4) /* W PF */
-#define fstartT (0x0b8/4) /* W PF */
-#define fstartW (0x0bc/4) /* W PF */
-
-/* 0x0c0 */
-#define fdRdX (0x0c0/4) /* W PF */
-#define fdGdX (0x0c4/4) /* W PF */
-#define fdBdX (0x0c8/4) /* W PF */
-#define fdZdX (0x0cc/4) /* W PF */
-#define fdAdX (0x0d0/4) /* W PF */
-#define fdSdX (0x0d4/4) /* W PF */
-#define fdTdX (0x0d8/4) /* W PF */
-#define fdWdX (0x0dc/4) /* W PF */
-#define fdRdY (0x0e0/4) /* W PF */
-#define fdGdY (0x0e4/4) /* W PF */
-#define fdBdY (0x0e8/4) /* W PF */
-#define fdZdY (0x0ec/4) /* W PF */
-#define fdAdY (0x0f0/4) /* W PF */
-#define fdSdY (0x0f4/4) /* W PF */
-#define fdTdY (0x0f8/4) /* W PF */
-#define fdWdY (0x0fc/4) /* W PF */
-
-/* 0x100 */
-#define ftriangleCMD (0x100/4) /* W PF */
-#define fbzColorPath (0x104/4) /* RW PF */
-#define fogMode (0x108/4) /* RW PF */
-#define alphaMode (0x10c/4) /* RW PF */
-#define fbzMode (0x110/4) /* RW F */
-#define lfbMode (0x114/4) /* RW F */
-#define clipLeftRight (0x118/4) /* RW F */
-#define clipLowYHighY (0x11c/4) /* RW F */
-#define nopCMD (0x120/4) /* W F */
-#define fastfillCMD (0x124/4) /* W F */
-#define swapbufferCMD (0x128/4) /* W F */
-#define fogColor (0x12c/4) /* W F */
-#define zaColor (0x130/4) /* W F */
-#define chromaKey (0x134/4) /* W F */
-#define chromaRange (0x138/4) /* W F -- Voodoo2/Banshee only */
-#define userIntrCMD (0x13c/4) /* W F -- Voodoo2/Banshee only */
-
-/* 0x140 */
-#define stipple (0x140/4) /* RW F */
-#define color0 (0x144/4) /* RW F */
-#define color1 (0x148/4) /* RW F */
-#define fbiPixelsIn (0x14c/4) /* R */
-#define fbiChromaFail (0x150/4) /* R */
-#define fbiZfuncFail (0x154/4) /* R */
-#define fbiAfuncFail (0x158/4) /* R */
-#define fbiPixelsOut (0x15c/4) /* R */
-#define fogTable (0x160/4) /* W F */
-
-/* 0x1c0 */
-#define cmdFifoBaseAddr (0x1e0/4) /* RW -- Voodoo2 only */
-#define cmdFifoBump (0x1e4/4) /* RW -- Voodoo2 only */
-#define cmdFifoRdPtr (0x1e8/4) /* RW -- Voodoo2 only */
-#define cmdFifoAMin (0x1ec/4) /* RW -- Voodoo2 only */
-#define colBufferAddr (0x1ec/4) /* RW -- Banshee only */
-#define cmdFifoAMax (0x1f0/4) /* RW -- Voodoo2 only */
-#define colBufferStride (0x1f0/4) /* RW -- Banshee only */
-#define cmdFifoDepth (0x1f4/4) /* RW -- Voodoo2 only */
-#define auxBufferAddr (0x1f4/4) /* RW -- Banshee only */
-#define cmdFifoHoles (0x1f8/4) /* RW -- Voodoo2 only */
-#define auxBufferStride (0x1f8/4) /* RW -- Banshee only */
-
-/* 0x200 */
-#define fbiInit4 (0x200/4) /* RW -- Voodoo/Voodoo2 only */
-#define clipLeftRight1 (0x200/4) /* RW -- Banshee only */
-#define vRetrace (0x204/4) /* R -- Voodoo/Voodoo2 only */
-#define clipTopBottom1 (0x204/4) /* RW -- Banshee only */
-#define backPorch (0x208/4) /* RW -- Voodoo/Voodoo2 only */
-#define videoDimensions (0x20c/4) /* RW -- Voodoo/Voodoo2 only */
-#define fbiInit0 (0x210/4) /* RW -- Voodoo/Voodoo2 only */
-#define fbiInit1 (0x214/4) /* RW -- Voodoo/Voodoo2 only */
-#define fbiInit2 (0x218/4) /* RW -- Voodoo/Voodoo2 only */
-#define fbiInit3 (0x21c/4) /* RW -- Voodoo/Voodoo2 only */
-#define hSync (0x220/4) /* W -- Voodoo/Voodoo2 only */
-#define vSync (0x224/4) /* W -- Voodoo/Voodoo2 only */
-#define clutData (0x228/4) /* W F -- Voodoo/Voodoo2 only */
-#define dacData (0x22c/4) /* W -- Voodoo/Voodoo2 only */
-#define maxRgbDelta (0x230/4) /* W -- Voodoo/Voodoo2 only */
-#define hBorder (0x234/4) /* W -- Voodoo2 only */
-#define vBorder (0x238/4) /* W -- Voodoo2 only */
-#define borderColor (0x23c/4) /* W -- Voodoo2 only */
-
-/* 0x240 */
-#define hvRetrace (0x240/4) /* R -- Voodoo2 only */
-#define fbiInit5 (0x244/4) /* RW -- Voodoo2 only */
-#define fbiInit6 (0x248/4) /* RW -- Voodoo2 only */
-#define fbiInit7 (0x24c/4) /* RW -- Voodoo2 only */
-#define swapPending (0x24c/4) /* W -- Banshee only */
-#define leftOverlayBuf (0x250/4) /* W -- Banshee only */
-#define rightOverlayBuf (0x254/4) /* W -- Banshee only */
-#define fbiSwapHistory (0x258/4) /* R -- Voodoo2/Banshee only */
-#define fbiTrianglesOut (0x25c/4) /* R -- Voodoo2/Banshee only */
-#define sSetupMode (0x260/4) /* W PF -- Voodoo2/Banshee only */
-#define sVx (0x264/4) /* W PF -- Voodoo2/Banshee only */
-#define sVy (0x268/4) /* W PF -- Voodoo2/Banshee only */
-#define sARGB (0x26c/4) /* W PF -- Voodoo2/Banshee only */
-#define sRed (0x270/4) /* W PF -- Voodoo2/Banshee only */
-#define sGreen (0x274/4) /* W PF -- Voodoo2/Banshee only */
-#define sBlue (0x278/4) /* W PF -- Voodoo2/Banshee only */
-#define sAlpha (0x27c/4) /* W PF -- Voodoo2/Banshee only */
-
-/* 0x280 */
-#define sVz (0x280/4) /* W PF -- Voodoo2/Banshee only */
-#define sWb (0x284/4) /* W PF -- Voodoo2/Banshee only */
-#define sWtmu0 (0x288/4) /* W PF -- Voodoo2/Banshee only */
-#define sS_W0 (0x28c/4) /* W PF -- Voodoo2/Banshee only */
-#define sT_W0 (0x290/4) /* W PF -- Voodoo2/Banshee only */
-#define sWtmu1 (0x294/4) /* W PF -- Voodoo2/Banshee only */
-#define sS_Wtmu1 (0x298/4) /* W PF -- Voodoo2/Banshee only */
-#define sT_Wtmu1 (0x29c/4) /* W PF -- Voodoo2/Banshee only */
-#define sDrawTriCMD (0x2a0/4) /* W PF -- Voodoo2/Banshee only */
-#define sBeginTriCMD (0x2a4/4) /* W PF -- Voodoo2/Banshee only */
-
-/* 0x2c0 */
-#define bltSrcBaseAddr (0x2c0/4) /* RW PF -- Voodoo2 only */
-#define bltDstBaseAddr (0x2c4/4) /* RW PF -- Voodoo2 only */
-#define bltXYStrides (0x2c8/4) /* RW PF -- Voodoo2 only */
-#define bltSrcChromaRange (0x2cc/4) /* RW PF -- Voodoo2 only */
-#define bltDstChromaRange (0x2d0/4) /* RW PF -- Voodoo2 only */
-#define bltClipX (0x2d4/4) /* RW PF -- Voodoo2 only */
-#define bltClipY (0x2d8/4) /* RW PF -- Voodoo2 only */
-#define bltSrcXY (0x2e0/4) /* RW PF -- Voodoo2 only */
-#define bltDstXY (0x2e4/4) /* RW PF -- Voodoo2 only */
-#define bltSize (0x2e8/4) /* RW PF -- Voodoo2 only */
-#define bltRop (0x2ec/4) /* RW PF -- Voodoo2 only */
-#define bltColor (0x2f0/4) /* RW PF -- Voodoo2 only */
-#define bltCommand (0x2f8/4) /* RW PF -- Voodoo2 only */
-#define bltData (0x2fc/4) /* W PF -- Voodoo2 only */
-
-/* 0x300 */
-#define textureMode (0x300/4) /* W PF */
-#define tLOD (0x304/4) /* W PF */
-#define tDetail (0x308/4) /* W PF */
-#define texBaseAddr (0x30c/4) /* W PF */
-#define texBaseAddr_1 (0x310/4) /* W PF */
-#define texBaseAddr_2 (0x314/4) /* W PF */
-#define texBaseAddr_3_8 (0x318/4) /* W PF */
-#define trexInit0 (0x31c/4) /* W F -- Voodoo/Voodoo2 only */
-#define trexInit1 (0x320/4) /* W F */
-#define nccTable (0x324/4) /* W F */
-
-
-
-// 2D registers
-#define banshee2D_clip0Min (0x008/4)
-#define banshee2D_clip0Max (0x00c/4)
-#define banshee2D_dstBaseAddr (0x010/4)
-#define banshee2D_dstFormat (0x014/4)
-#define banshee2D_srcColorkeyMin (0x018/4)
-#define banshee2D_srcColorkeyMax (0x01c/4)
-#define banshee2D_dstColorkeyMin (0x020/4)
-#define banshee2D_dstColorkeyMax (0x024/4)
-#define banshee2D_bresError0 (0x028/4)
-#define banshee2D_bresError1 (0x02c/4)
-#define banshee2D_rop (0x030/4)
-#define banshee2D_srcBaseAddr (0x034/4)
-#define banshee2D_commandExtra (0x038/4)
-#define banshee2D_lineStipple (0x03c/4)
-#define banshee2D_lineStyle (0x040/4)
-#define banshee2D_pattern0Alias (0x044/4)
-#define banshee2D_pattern1Alias (0x048/4)
-#define banshee2D_clip1Min (0x04c/4)
-#define banshee2D_clip1Max (0x050/4)
-#define banshee2D_srcFormat (0x054/4)
-#define banshee2D_srcSize (0x058/4)
-#define banshee2D_srcXY (0x05c/4)
-#define banshee2D_colorBack (0x060/4)
-#define banshee2D_colorFore (0x064/4)
-#define banshee2D_dstSize (0x068/4)
-#define banshee2D_dstXY (0x06c/4)
-#define banshee2D_command (0x070/4)
-
-
-/*************************************
- *
- * Voodoo Banshee I/O space registers
- *
- *************************************/
-
-/* 0x000 */
-#define io_status (0x000/4) /* */
-#define io_pciInit0 (0x004/4) /* */
-#define io_sipMonitor (0x008/4) /* */
-#define io_lfbMemoryConfig (0x00c/4) /* */
-#define io_miscInit0 (0x010/4) /* */
-#define io_miscInit1 (0x014/4) /* */
-#define io_dramInit0 (0x018/4) /* */
-#define io_dramInit1 (0x01c/4) /* */
-#define io_agpInit (0x020/4) /* */
-#define io_tmuGbeInit (0x024/4) /* */
-#define io_vgaInit0 (0x028/4) /* */
-#define io_vgaInit1 (0x02c/4) /* */
-#define io_dramCommand (0x030/4) /* */
-#define io_dramData (0x034/4) /* */
-
-/* 0x040 */
-#define io_pllCtrl0 (0x040/4) /* */
-#define io_pllCtrl1 (0x044/4) /* */
-#define io_pllCtrl2 (0x048/4) /* */
-#define io_dacMode (0x04c/4) /* */
-#define io_dacAddr (0x050/4) /* */
-#define io_dacData (0x054/4) /* */
-#define io_rgbMaxDelta (0x058/4) /* */
-#define io_vidProcCfg (0x05c/4) /* */
-#define io_hwCurPatAddr (0x060/4) /* */
-#define io_hwCurLoc (0x064/4) /* */
-#define io_hwCurC0 (0x068/4) /* */
-#define io_hwCurC1 (0x06c/4) /* */
-#define io_vidInFormat (0x070/4) /* */
-#define io_vidInStatus (0x074/4) /* */
-#define io_vidSerialParallelPort (0x078/4) /* */
-#define io_vidInXDecimDeltas (0x07c/4) /* */
-
-/* 0x080 */
-#define io_vidInDecimInitErrs (0x080/4) /* */
-#define io_vidInYDecimDeltas (0x084/4) /* */
-#define io_vidPixelBufThold (0x088/4) /* */
-#define io_vidChromaMin (0x08c/4) /* */
-#define io_vidChromaMax (0x090/4) /* */
-#define io_vidCurrentLine (0x094/4) /* */
-#define io_vidScreenSize (0x098/4) /* */
-#define io_vidOverlayStartCoords (0x09c/4) /* */
-#define io_vidOverlayEndScreenCoord (0x0a0/4) /* */
-#define io_vidOverlayDudx (0x0a4/4) /* */
-#define io_vidOverlayDudxOffsetSrcWidth (0x0a8/4) /* */
-#define io_vidOverlayDvdy (0x0ac/4) /* */
-#define io_vgab0 (0x0b0/4) /* */
-#define io_vgab4 (0x0b4/4) /* */
-#define io_vgab8 (0x0b8/4) /* */
-#define io_vgabc (0x0bc/4) /* */
-
-/* 0x0c0 */
-#define io_vgac0 (0x0c0/4) /* */
-#define io_vgac4 (0x0c4/4) /* */
-#define io_vgac8 (0x0c8/4) /* */
-#define io_vgacc (0x0cc/4) /* */
-#define io_vgad0 (0x0d0/4) /* */
-#define io_vgad4 (0x0d4/4) /* */
-#define io_vgad8 (0x0d8/4) /* */
-#define io_vgadc (0x0dc/4) /* */
-#define io_vidOverlayDvdyOffset (0x0e0/4) /* */
-#define io_vidDesktopStartAddr (0x0e4/4) /* */
-#define io_vidDesktopOverlayStride (0x0e8/4) /* */
-#define io_vidInAddr0 (0x0ec/4) /* */
-#define io_vidInAddr1 (0x0f0/4) /* */
-#define io_vidInAddr2 (0x0f4/4) /* */
-#define io_vidInStride (0x0f8/4) /* */
-#define io_vidCurrOverlayStartAddr (0x0fc/4) /* */
-
-
-
-/*************************************
- *
- * Voodoo Banshee AGP space registers
- *
- *************************************/
-
-/* 0x000 */
-#define agpReqSize (0x000/4) /* */
-#define agpHostAddressLow (0x004/4) /* */
-#define agpHostAddressHigh (0x008/4) /* */
-#define agpGraphicsAddress (0x00c/4) /* */
-#define agpGraphicsStride (0x010/4) /* */
-#define agpMoveCMD (0x014/4) /* */
-#define cmdBaseAddr0 (0x020/4) /* */
-#define cmdBaseSize0 (0x024/4) /* */
-#define cmdBump0 (0x028/4) /* */
-#define cmdRdPtrL0 (0x02c/4) /* */
-#define cmdRdPtrH0 (0x030/4) /* */
-#define cmdAMin0 (0x034/4) /* */
-#define cmdAMax0 (0x03c/4) /* */
-
-/* 0x040 */
-#define cmdFifoDepth0 (0x044/4) /* */
-#define cmdHoleCnt0 (0x048/4) /* */
-#define cmdBaseAddr1 (0x050/4) /* */
-#define cmdBaseSize1 (0x054/4) /* */
-#define cmdBump1 (0x058/4) /* */
-#define cmdRdPtrL1 (0x05c/4) /* */
-#define cmdRdPtrH1 (0x060/4) /* */
-#define cmdAMin1 (0x064/4) /* */
-#define cmdAMax1 (0x06c/4) /* */
-#define cmdFifoDepth1 (0x074/4) /* */
-#define cmdHoleCnt1 (0x078/4) /* */
-
-/* 0x080 */
-#define cmdFifoThresh (0x080/4) /* */
-#define cmdHoleInt (0x084/4) /* */
-
-/* 0x100 */
-#define yuvBaseAddress (0x100/4) /* */
-#define yuvStride (0x104/4) /* */
-#define crc1 (0x120/4) /* */
-#define crc2 (0x130/4) /* */
-
-
-
-/*************************************
- *
- * Dithering tables
- *
- *************************************/
-
-static const uint8_t dither_matrix_4x4[16] =
+namespace voodoo
{
- 0, 8, 2, 10,
- 12, 4, 14, 6,
- 3, 11, 1, 9,
- 15, 7, 13, 5
-};
-//static const uint8_t dither_matrix_2x2[16] =
-//{
-// 2, 10, 2, 10,
-// 14, 6, 14, 6,
-// 2, 10, 2, 10,
-// 14, 6, 14, 6
-//};
-// Using this matrix allows iteagle video memory tests to pass
-static const uint8_t dither_matrix_2x2[16] =
+// enumeration specifying which model of Voodoo we are emulating
+enum class voodoo_model : u8
{
- 8, 10, 8, 10,
- 11, 9, 11, 9,
- 8, 10, 8, 10,
- 11, 9, 11, 9
+ VOODOO_1,
+ VOODOO_2,
+ VOODOO_BANSHEE,
+ VOODOO_3
};
-// Dither 4x4 subtraction matrix used in alpha blending
-static const uint8_t dither_subtract_4x4[16] =
-{
- (15 - 0) >> 1, (15 - 8) >> 1, (15 - 2) >> 1, (15 - 10) >> 1,
- (15 - 12) >> 1, (15 - 4) >> 1, (15 - 14) >> 1, (15 - 6) >> 1,
- (15 - 3) >> 1, (15 - 11) >> 1, (15 - 1) >> 1, (15 - 9) >> 1,
- (15 - 15) >> 1, (15 - 7) >> 1, (15 - 13) >> 1, (15 - 5) >> 1
-};
-
-// Dither 2x2 subtraction matrix used in alpha blending
-static const uint8_t dither_subtract_2x2[16] =
-{
- (15 - 8) >> 1, (15 - 10) >> 1, (15 - 8) >> 1, (15 - 10) >> 1,
- (15 - 11) >> 1, (15 - 9) >> 1, (15 - 11) >> 1, (15 - 9) >> 1,
- (15 - 8) >> 1, (15 - 10) >> 1, (15 - 8) >> 1, (15 - 10) >> 1,
- (15 - 11) >> 1, (15 - 9) >> 1, (15 - 11) >> 1, (15 - 9) >> 1
-};
+// debug
+static constexpr bool DEBUG_DEPTH = false; // ENTER key to view depthbuf
+static constexpr bool DEBUG_BACKBUF = false; // L key to view backbuf
+static constexpr bool DEBUG_STATS = false; // \ key to view stats
-/*************************************
- *
- * Macros for extracting pixels
- *
- *************************************/
-
-#define EXTRACT_565_TO_888(val, a, b, c) \
- (a) = (((val) >> 8) & 0xf8) | (((val) >> 13) & 0x07); \
- (b) = (((val) >> 3) & 0xfc) | (((val) >> 9) & 0x03); \
- (c) = (((val) << 3) & 0xf8) | (((val) >> 2) & 0x07);
-#define EXTRACT_x555_TO_888(val, a, b, c) \
- (a) = (((val) >> 7) & 0xf8) | (((val) >> 12) & 0x07); \
- (b) = (((val) >> 2) & 0xf8) | (((val) >> 7) & 0x07); \
- (c) = (((val) << 3) & 0xf8) | (((val) >> 2) & 0x07);
-#define EXTRACT_555x_TO_888(val, a, b, c) \
- (a) = (((val) >> 8) & 0xf8) | (((val) >> 13) & 0x07); \
- (b) = (((val) >> 3) & 0xf8) | (((val) >> 8) & 0x07); \
- (c) = (((val) << 2) & 0xf8) | (((val) >> 3) & 0x07);
-#define EXTRACT_1555_TO_8888(val, a, b, c, d) \
- (a) = ((int16_t)(val) >> 15) & 0xff; \
- EXTRACT_x555_TO_888(val, b, c, d)
-#define EXTRACT_5551_TO_8888(val, a, b, c, d) \
- EXTRACT_555x_TO_888(val, a, b, c) \
- (d) = ((val) & 0x0001) ? 0xff : 0x00;
-#define EXTRACT_x888_TO_888(val, a, b, c) \
- (a) = ((val) >> 16) & 0xff; \
- (b) = ((val) >> 8) & 0xff; \
- (c) = ((val) >> 0) & 0xff;
-#define EXTRACT_888x_TO_888(val, a, b, c) \
- (a) = ((val) >> 24) & 0xff; \
- (b) = ((val) >> 16) & 0xff; \
- (c) = ((val) >> 8) & 0xff;
-#define EXTRACT_8888_TO_8888(val, a, b, c, d) \
- (a) = ((val) >> 24) & 0xff; \
- (b) = ((val) >> 16) & 0xff; \
- (c) = ((val) >> 8) & 0xff; \
- (d) = ((val) >> 0) & 0xff;
-#define EXTRACT_4444_TO_8888(val, a, b, c, d) \
- (a) = (((val) >> 8) & 0xf0) | (((val) >> 12) & 0x0f); \
- (b) = (((val) >> 4) & 0xf0) | (((val) >> 8) & 0x0f); \
- (c) = (((val) >> 0) & 0xf0) | (((val) >> 4) & 0x0f); \
- (d) = (((val) << 4) & 0xf0) | (((val) >> 0) & 0x0f);
-#define EXTRACT_332_TO_888(val, a, b, c) \
- (a) = (((val) >> 0) & 0xe0) | (((val) >> 3) & 0x1c) | (((val) >> 6) & 0x03); \
- (b) = (((val) << 3) & 0xe0) | (((val) >> 0) & 0x1c) | (((val) >> 3) & 0x03); \
- (c) = (((val) << 6) & 0xc0) | (((val) << 4) & 0x30) | (((val) << 2) & 0x0c) | (((val) << 0) & 0x03);
-
-
-/*************************************
- *
- * Misc. macros
- *
- *************************************/
-
-/* macro for clamping a value between minimum and maximum values */
-#define CLAMP(val,min,max) do { if ((val) < (min)) { (val) = (min); } else if ((val) > (max)) { (val) = (max); } } while (0)
-
-/* macro to compute the base 2 log for LOD calculations */
-#define LOGB2(x) (log((double)(x)) / log(2.0))
-
-
-
-/*************************************
- *
- * Macros for extracting bitfields
- *
- *************************************/
-
-#define INITEN_ENABLE_HW_INIT(val) (((val) >> 0) & 1)
-#define INITEN_ENABLE_PCI_FIFO(val) (((val) >> 1) & 1)
-#define INITEN_REMAP_INIT_TO_DAC(val) (((val) >> 2) & 1)
-#define INITEN_ENABLE_SNOOP0(val) (((val) >> 4) & 1)
-#define INITEN_SNOOP0_MEMORY_MATCH(val) (((val) >> 5) & 1)
-#define INITEN_SNOOP0_READWRITE_MATCH(val) (((val) >> 6) & 1)
-#define INITEN_ENABLE_SNOOP1(val) (((val) >> 7) & 1)
-#define INITEN_SNOOP1_MEMORY_MATCH(val) (((val) >> 8) & 1)
-#define INITEN_SNOOP1_READWRITE_MATCH(val) (((val) >> 9) & 1)
-#define INITEN_SLI_BUS_OWNER(val) (((val) >> 10) & 1)
-#define INITEN_SLI_ODD_EVEN(val) (((val) >> 11) & 1)
-#define INITEN_SECONDARY_REV_ID(val) (((val) >> 12) & 0xf) /* voodoo 2 only */
-#define INITEN_MFCTR_FAB_ID(val) (((val) >> 16) & 0xf) /* voodoo 2 only */
-#define INITEN_ENABLE_PCI_INTERRUPT(val) (((val) >> 20) & 1) /* voodoo 2 only */
-#define INITEN_PCI_INTERRUPT_TIMEOUT(val) (((val) >> 21) & 1) /* voodoo 2 only */
-#define INITEN_ENABLE_NAND_TREE_TEST(val) (((val) >> 22) & 1) /* voodoo 2 only */
-#define INITEN_ENABLE_SLI_ADDRESS_SNOOP(val) (((val) >> 23) & 1) /* voodoo 2 only */
-#define INITEN_SLI_SNOOP_ADDRESS(val) (((val) >> 24) & 0xff) /* voodoo 2 only */
-
-#define FBZCP_CC_RGBSELECT(val) (((val) >> 0) & 3)
-#define FBZCP_CC_ASELECT(val) (((val) >> 2) & 3)
-#define FBZCP_CC_LOCALSELECT(val) (((val) >> 4) & 1)
-#define FBZCP_CCA_LOCALSELECT(val) (((val) >> 5) & 3)
-#define FBZCP_CC_LOCALSELECT_OVERRIDE(val) (((val) >> 7) & 1)
-#define FBZCP_CC_ZERO_OTHER(val) (((val) >> 8) & 1)
-#define FBZCP_CC_SUB_CLOCAL(val) (((val) >> 9) & 1)
-#define FBZCP_CC_MSELECT(val) (((val) >> 10) & 7)
-#define FBZCP_CC_REVERSE_BLEND(val) (((val) >> 13) & 1)
-#define FBZCP_CC_ADD_ACLOCAL(val) (((val) >> 14) & 3)
-#define FBZCP_CC_INVERT_OUTPUT(val) (((val) >> 16) & 1)
-#define FBZCP_CCA_ZERO_OTHER(val) (((val) >> 17) & 1)
-#define FBZCP_CCA_SUB_CLOCAL(val) (((val) >> 18) & 1)
-#define FBZCP_CCA_MSELECT(val) (((val) >> 19) & 7)
-#define FBZCP_CCA_REVERSE_BLEND(val) (((val) >> 22) & 1)
-#define FBZCP_CCA_ADD_ACLOCAL(val) (((val) >> 23) & 3)
-#define FBZCP_CCA_INVERT_OUTPUT(val) (((val) >> 25) & 1)
-#define FBZCP_CCA_SUBPIXEL_ADJUST(val) (((val) >> 26) & 1)
-#define FBZCP_TEXTURE_ENABLE(val) (((val) >> 27) & 1)
-#define FBZCP_RGBZW_CLAMP(val) (((val) >> 28) & 1) /* voodoo 2 only */
-#define FBZCP_ANTI_ALIAS(val) (((val) >> 29) & 1) /* voodoo 2 only */
-
-#define ALPHAMODE_ALPHATEST(val) (((val) >> 0) & 1)
-#define ALPHAMODE_ALPHAFUNCTION(val) (((val) >> 1) & 7)
-#define ALPHAMODE_ALPHABLEND(val) (((val) >> 4) & 1)
-#define ALPHAMODE_ANTIALIAS(val) (((val) >> 5) & 1)
-#define ALPHAMODE_SRCRGBBLEND(val) (((val) >> 8) & 15)
-#define ALPHAMODE_DSTRGBBLEND(val) (((val) >> 12) & 15)
-#define ALPHAMODE_SRCALPHABLEND(val) (((val) >> 16) & 15)
-#define ALPHAMODE_DSTALPHABLEND(val) (((val) >> 20) & 15)
-#define ALPHAMODE_ALPHAREF(val) (((val) >> 24) & 0xff)
-
-#define FOGMODE_ENABLE_FOG(val) (((val) >> 0) & 1)
-#define FOGMODE_FOG_ADD(val) (((val) >> 1) & 1)
-#define FOGMODE_FOG_MULT(val) (((val) >> 2) & 1)
-#define FOGMODE_FOG_ZALPHA(val) (((val) >> 3) & 3)
-#define FOGMODE_FOG_CONSTANT(val) (((val) >> 5) & 1)
-#define FOGMODE_FOG_DITHER(val) (((val) >> 6) & 1) /* voodoo 2 only */
-#define FOGMODE_FOG_ZONES(val) (((val) >> 7) & 1) /* voodoo 2 only */
-
-#define FBZMODE_ENABLE_CLIPPING(val) (((val) >> 0) & 1)
-#define FBZMODE_ENABLE_CHROMAKEY(val) (((val) >> 1) & 1)
-#define FBZMODE_ENABLE_STIPPLE(val) (((val) >> 2) & 1)
-#define FBZMODE_WBUFFER_SELECT(val) (((val) >> 3) & 1)
-#define FBZMODE_ENABLE_DEPTHBUF(val) (((val) >> 4) & 1)
-#define FBZMODE_DEPTH_FUNCTION(val) (((val) >> 5) & 7)
-#define FBZMODE_ENABLE_DITHERING(val) (((val) >> 8) & 1)
-#define FBZMODE_RGB_BUFFER_MASK(val) (((val) >> 9) & 1)
-#define FBZMODE_AUX_BUFFER_MASK(val) (((val) >> 10) & 1)
-#define FBZMODE_DITHER_TYPE(val) (((val) >> 11) & 1)
-#define FBZMODE_STIPPLE_PATTERN(val) (((val) >> 12) & 1)
-#define FBZMODE_ENABLE_ALPHA_MASK(val) (((val) >> 13) & 1)
-#define FBZMODE_DRAW_BUFFER(val) (((val) >> 14) & 3)
-#define FBZMODE_ENABLE_DEPTH_BIAS(val) (((val) >> 16) & 1)
-#define FBZMODE_Y_ORIGIN(val) (((val) >> 17) & 1)
-#define FBZMODE_ENABLE_ALPHA_PLANES(val) (((val) >> 18) & 1)
-#define FBZMODE_ALPHA_DITHER_SUBTRACT(val) (((val) >> 19) & 1)
-#define FBZMODE_DEPTH_SOURCE_COMPARE(val) (((val) >> 20) & 1)
-#define FBZMODE_DEPTH_FLOAT_SELECT(val) (((val) >> 21) & 1) /* voodoo 2 only */
-
-#define LFBMODE_WRITE_FORMAT(val) (((val) >> 0) & 0xf)
-#define LFBMODE_WRITE_BUFFER_SELECT(val) (((val) >> 4) & 3)
-#define LFBMODE_READ_BUFFER_SELECT(val) (((val) >> 6) & 3)
-#define LFBMODE_ENABLE_PIXEL_PIPELINE(val) (((val) >> 8) & 1)
-#define LFBMODE_RGBA_LANES(val) (((val) >> 9) & 3)
-#define LFBMODE_WORD_SWAP_WRITES(val) (((val) >> 11) & 1)
-#define LFBMODE_BYTE_SWIZZLE_WRITES(val) (((val) >> 12) & 1)
-#define LFBMODE_Y_ORIGIN(val) (((val) >> 13) & 1)
-#define LFBMODE_WRITE_W_SELECT(val) (((val) >> 14) & 1)
-#define LFBMODE_WORD_SWAP_READS(val) (((val) >> 15) & 1)
-#define LFBMODE_BYTE_SWIZZLE_READS(val) (((val) >> 16) & 1)
-
-#define CHROMARANGE_BLUE_EXCLUSIVE(val) (((val) >> 24) & 1)
-#define CHROMARANGE_GREEN_EXCLUSIVE(val) (((val) >> 25) & 1)
-#define CHROMARANGE_RED_EXCLUSIVE(val) (((val) >> 26) & 1)
-#define CHROMARANGE_UNION_MODE(val) (((val) >> 27) & 1)
-#define CHROMARANGE_ENABLE(val) (((val) >> 28) & 1)
-
-#define FBIINIT0_VGA_PASSTHRU(val) (((val) >> 0) & 1)
-#define FBIINIT0_GRAPHICS_RESET(val) (((val) >> 1) & 1)
-#define FBIINIT0_FIFO_RESET(val) (((val) >> 2) & 1)
-#define FBIINIT0_SWIZZLE_REG_WRITES(val) (((val) >> 3) & 1)
-#define FBIINIT0_STALL_PCIE_FOR_HWM(val) (((val) >> 4) & 1)
-#define FBIINIT0_PCI_FIFO_LWM(val) (((val) >> 6) & 0x1f)
-#define FBIINIT0_LFB_TO_MEMORY_FIFO(val) (((val) >> 11) & 1)
-#define FBIINIT0_TEXMEM_TO_MEMORY_FIFO(val) (((val) >> 12) & 1)
-#define FBIINIT0_ENABLE_MEMORY_FIFO(val) (((val) >> 13) & 1)
-#define FBIINIT0_MEMORY_FIFO_HWM(val) (((val) >> 14) & 0x7ff)
-#define FBIINIT0_MEMORY_FIFO_BURST(val) (((val) >> 25) & 0x3f)
-
-#define FBIINIT1_PCI_DEV_FUNCTION(val) (((val) >> 0) & 1)
-#define FBIINIT1_PCI_WRITE_WAIT_STATES(val) (((val) >> 1) & 1)
-#define FBIINIT1_MULTI_SST1(val) (((val) >> 2) & 1) /* not on voodoo 2 */
-#define FBIINIT1_ENABLE_LFB(val) (((val) >> 3) & 1)
-#define FBIINIT1_X_VIDEO_TILES(val) (((val) >> 4) & 0xf)
-#define FBIINIT1_VIDEO_TIMING_RESET(val) (((val) >> 8) & 1)
-#define FBIINIT1_SOFTWARE_OVERRIDE(val) (((val) >> 9) & 1)
-#define FBIINIT1_SOFTWARE_HSYNC(val) (((val) >> 10) & 1)
-#define FBIINIT1_SOFTWARE_VSYNC(val) (((val) >> 11) & 1)
-#define FBIINIT1_SOFTWARE_BLANK(val) (((val) >> 12) & 1)
-#define FBIINIT1_DRIVE_VIDEO_TIMING(val) (((val) >> 13) & 1)
-#define FBIINIT1_DRIVE_VIDEO_BLANK(val) (((val) >> 14) & 1)
-#define FBIINIT1_DRIVE_VIDEO_SYNC(val) (((val) >> 15) & 1)
-#define FBIINIT1_DRIVE_VIDEO_DCLK(val) (((val) >> 16) & 1)
-#define FBIINIT1_VIDEO_TIMING_VCLK(val) (((val) >> 17) & 1)
-#define FBIINIT1_VIDEO_CLK_2X_DELAY(val) (((val) >> 18) & 3)
-#define FBIINIT1_VIDEO_TIMING_SOURCE(val) (((val) >> 20) & 3)
-#define FBIINIT1_ENABLE_24BPP_OUTPUT(val) (((val) >> 22) & 1)
-#define FBIINIT1_ENABLE_SLI(val) (((val) >> 23) & 1)
-#define FBIINIT1_X_VIDEO_TILES_BIT5(val) (((val) >> 24) & 1) /* voodoo 2 only */
-#define FBIINIT1_ENABLE_EDGE_FILTER(val) (((val) >> 25) & 1)
-#define FBIINIT1_INVERT_VID_CLK_2X(val) (((val) >> 26) & 1)
-#define FBIINIT1_VID_CLK_2X_SEL_DELAY(val) (((val) >> 27) & 3)
-#define FBIINIT1_VID_CLK_DELAY(val) (((val) >> 29) & 3)
-#define FBIINIT1_DISABLE_FAST_READAHEAD(val) (((val) >> 31) & 1)
-
-#define FBIINIT2_DISABLE_DITHER_SUB(val) (((val) >> 0) & 1)
-#define FBIINIT2_DRAM_BANKING(val) (((val) >> 1) & 1)
-#define FBIINIT2_ENABLE_TRIPLE_BUF(val) (((val) >> 4) & 1)
-#define FBIINIT2_ENABLE_FAST_RAS_READ(val) (((val) >> 5) & 1)
-#define FBIINIT2_ENABLE_GEN_DRAM_OE(val) (((val) >> 6) & 1)
-#define FBIINIT2_ENABLE_FAST_READWRITE(val) (((val) >> 7) & 1)
-#define FBIINIT2_ENABLE_PASSTHRU_DITHER(val) (((val) >> 8) & 1)
-#define FBIINIT2_SWAP_BUFFER_ALGORITHM(val) (((val) >> 9) & 3)
-#define FBIINIT2_VIDEO_BUFFER_OFFSET(val) (((val) >> 11) & 0x1ff)
-#define FBIINIT2_ENABLE_DRAM_BANKING(val) (((val) >> 20) & 1)
-#define FBIINIT2_ENABLE_DRAM_READ_FIFO(val) (((val) >> 21) & 1)
-#define FBIINIT2_ENABLE_DRAM_REFRESH(val) (((val) >> 22) & 1)
-#define FBIINIT2_REFRESH_LOAD_VALUE(val) (((val) >> 23) & 0x1ff)
-
-#define FBIINIT3_TRI_REGISTER_REMAP(val) (((val) >> 0) & 1)
-#define FBIINIT3_VIDEO_FIFO_THRESH(val) (((val) >> 1) & 0x1f)
-#define FBIINIT3_DISABLE_TMUS(val) (((val) >> 6) & 1)
-#define FBIINIT3_FBI_MEMORY_TYPE(val) (((val) >> 8) & 7)
-#define FBIINIT3_VGA_PASS_RESET_VAL(val) (((val) >> 11) & 1)
-#define FBIINIT3_HARDCODE_PCI_BASE(val) (((val) >> 12) & 1)
-#define FBIINIT3_FBI2TREX_DELAY(val) (((val) >> 13) & 0xf)
-#define FBIINIT3_TREX2FBI_DELAY(val) (((val) >> 17) & 0x1f)
-#define FBIINIT3_YORIGIN_SUBTRACT(val) (((val) >> 22) & 0x3ff)
-
-#define FBIINIT4_PCI_READ_WAITS(val) (((val) >> 0) & 1)
-#define FBIINIT4_ENABLE_LFB_READAHEAD(val) (((val) >> 1) & 1)
-#define FBIINIT4_MEMORY_FIFO_LWM(val) (((val) >> 2) & 0x3f)
-#define FBIINIT4_MEMORY_FIFO_START_ROW(val) (((val) >> 8) & 0x3ff)
-#define FBIINIT4_MEMORY_FIFO_STOP_ROW(val) (((val) >> 18) & 0x3ff)
-#define FBIINIT4_VIDEO_CLOCKING_DELAY(val) (((val) >> 29) & 7) /* voodoo 2 only */
-
-#define FBIINIT5_DISABLE_PCI_STOP(val) (((val) >> 0) & 1) /* voodoo 2 only */
-#define FBIINIT5_PCI_SLAVE_SPEED(val) (((val) >> 1) & 1) /* voodoo 2 only */
-#define FBIINIT5_DAC_DATA_OUTPUT_WIDTH(val) (((val) >> 2) & 1) /* voodoo 2 only */
-#define FBIINIT5_DAC_DATA_17_OUTPUT(val) (((val) >> 3) & 1) /* voodoo 2 only */
-#define FBIINIT5_DAC_DATA_18_OUTPUT(val) (((val) >> 4) & 1) /* voodoo 2 only */
-#define FBIINIT5_GENERIC_STRAPPING(val) (((val) >> 5) & 0xf) /* voodoo 2 only */
-#define FBIINIT5_BUFFER_ALLOCATION(val) (((val) >> 9) & 3) /* voodoo 2 only */
-#define FBIINIT5_DRIVE_VID_CLK_SLAVE(val) (((val) >> 11) & 1) /* voodoo 2 only */
-#define FBIINIT5_DRIVE_DAC_DATA_16(val) (((val) >> 12) & 1) /* voodoo 2 only */
-#define FBIINIT5_VCLK_INPUT_SELECT(val) (((val) >> 13) & 1) /* voodoo 2 only */
-#define FBIINIT5_MULTI_CVG_DETECT(val) (((val) >> 14) & 1) /* voodoo 2 only */
-#define FBIINIT5_SYNC_RETRACE_READS(val) (((val) >> 15) & 1) /* voodoo 2 only */
-#define FBIINIT5_ENABLE_RHBORDER_COLOR(val) (((val) >> 16) & 1) /* voodoo 2 only */
-#define FBIINIT5_ENABLE_LHBORDER_COLOR(val) (((val) >> 17) & 1) /* voodoo 2 only */
-#define FBIINIT5_ENABLE_BVBORDER_COLOR(val) (((val) >> 18) & 1) /* voodoo 2 only */
-#define FBIINIT5_ENABLE_TVBORDER_COLOR(val) (((val) >> 19) & 1) /* voodoo 2 only */
-#define FBIINIT5_DOUBLE_HORIZ(val) (((val) >> 20) & 1) /* voodoo 2 only */
-#define FBIINIT5_DOUBLE_VERT(val) (((val) >> 21) & 1) /* voodoo 2 only */
-#define FBIINIT5_ENABLE_16BIT_GAMMA(val) (((val) >> 22) & 1) /* voodoo 2 only */
-#define FBIINIT5_INVERT_DAC_HSYNC(val) (((val) >> 23) & 1) /* voodoo 2 only */
-#define FBIINIT5_INVERT_DAC_VSYNC(val) (((val) >> 24) & 1) /* voodoo 2 only */
-#define FBIINIT5_ENABLE_24BIT_DACDATA(val) (((val) >> 25) & 1) /* voodoo 2 only */
-#define FBIINIT5_ENABLE_INTERLACING(val) (((val) >> 26) & 1) /* voodoo 2 only */
-#define FBIINIT5_DAC_DATA_18_CONTROL(val) (((val) >> 27) & 1) /* voodoo 2 only */
-#define FBIINIT5_RASTERIZER_UNIT_MODE(val) (((val) >> 30) & 3) /* voodoo 2 only */
-
-#define FBIINIT6_WINDOW_ACTIVE_COUNTER(val) (((val) >> 0) & 7) /* voodoo 2 only */
-#define FBIINIT6_WINDOW_DRAG_COUNTER(val) (((val) >> 3) & 0x1f) /* voodoo 2 only */
-#define FBIINIT6_SLI_SYNC_MASTER(val) (((val) >> 8) & 1) /* voodoo 2 only */
-#define FBIINIT6_DAC_DATA_22_OUTPUT(val) (((val) >> 9) & 3) /* voodoo 2 only */
-#define FBIINIT6_DAC_DATA_23_OUTPUT(val) (((val) >> 11) & 3) /* voodoo 2 only */
-#define FBIINIT6_SLI_SYNCIN_OUTPUT(val) (((val) >> 13) & 3) /* voodoo 2 only */
-#define FBIINIT6_SLI_SYNCOUT_OUTPUT(val) (((val) >> 15) & 3) /* voodoo 2 only */
-#define FBIINIT6_DAC_RD_OUTPUT(val) (((val) >> 17) & 3) /* voodoo 2 only */
-#define FBIINIT6_DAC_WR_OUTPUT(val) (((val) >> 19) & 3) /* voodoo 2 only */
-#define FBIINIT6_PCI_FIFO_LWM_RDY(val) (((val) >> 21) & 0x7f) /* voodoo 2 only */
-#define FBIINIT6_VGA_PASS_N_OUTPUT(val) (((val) >> 28) & 3) /* voodoo 2 only */
-#define FBIINIT6_X_VIDEO_TILES_BIT0(val) (((val) >> 30) & 1) /* voodoo 2 only */
-
-#define FBIINIT7_GENERIC_STRAPPING(val) (((val) >> 0) & 0xff) /* voodoo 2 only */
-#define FBIINIT7_CMDFIFO_ENABLE(val) (((val) >> 8) & 1) /* voodoo 2 only */
-#define FBIINIT7_CMDFIFO_MEMORY_STORE(val) (((val) >> 9) & 1) /* voodoo 2 only */
-#define FBIINIT7_DISABLE_CMDFIFO_HOLES(val) (((val) >> 10) & 1) /* voodoo 2 only */
-#define FBIINIT7_CMDFIFO_READ_THRESH(val) (((val) >> 11) & 0x1f) /* voodoo 2 only */
-#define FBIINIT7_SYNC_CMDFIFO_WRITES(val) (((val) >> 16) & 1) /* voodoo 2 only */
-#define FBIINIT7_SYNC_CMDFIFO_READS(val) (((val) >> 17) & 1) /* voodoo 2 only */
-#define FBIINIT7_RESET_PCI_PACKER(val) (((val) >> 18) & 1) /* voodoo 2 only */
-#define FBIINIT7_ENABLE_CHROMA_STUFF(val) (((val) >> 19) & 1) /* voodoo 2 only */
-#define FBIINIT7_CMDFIFO_PCI_TIMEOUT(val) (((val) >> 20) & 0x7f) /* voodoo 2 only */
-#define FBIINIT7_ENABLE_TEXTURE_BURST(val) (((val) >> 27) & 1) /* voodoo 2 only */
-
-#define TEXMODE_ENABLE_PERSPECTIVE(val) (((val) >> 0) & 1)
-#define TEXMODE_MINIFICATION_FILTER(val) (((val) >> 1) & 1)
-#define TEXMODE_MAGNIFICATION_FILTER(val) (((val) >> 2) & 1)
-#define TEXMODE_CLAMP_NEG_W(val) (((val) >> 3) & 1)
-#define TEXMODE_ENABLE_LOD_DITHER(val) (((val) >> 4) & 1)
-#define TEXMODE_NCC_TABLE_SELECT(val) (((val) >> 5) & 1)
-#define TEXMODE_CLAMP_S(val) (((val) >> 6) & 1)
-#define TEXMODE_CLAMP_T(val) (((val) >> 7) & 1)
-#define TEXMODE_FORMAT(val) (((val) >> 8) & 0xf)
-#define TEXMODE_TC_ZERO_OTHER(val) (((val) >> 12) & 1)
-#define TEXMODE_TC_SUB_CLOCAL(val) (((val) >> 13) & 1)
-#define TEXMODE_TC_MSELECT(val) (((val) >> 14) & 7)
-#define TEXMODE_TC_REVERSE_BLEND(val) (((val) >> 17) & 1)
-#define TEXMODE_TC_ADD_ACLOCAL(val) (((val) >> 18) & 3)
-#define TEXMODE_TC_INVERT_OUTPUT(val) (((val) >> 20) & 1)
-#define TEXMODE_TCA_ZERO_OTHER(val) (((val) >> 21) & 1)
-#define TEXMODE_TCA_SUB_CLOCAL(val) (((val) >> 22) & 1)
-#define TEXMODE_TCA_MSELECT(val) (((val) >> 23) & 7)
-#define TEXMODE_TCA_REVERSE_BLEND(val) (((val) >> 26) & 1)
-#define TEXMODE_TCA_ADD_ACLOCAL(val) (((val) >> 27) & 3)
-#define TEXMODE_TCA_INVERT_OUTPUT(val) (((val) >> 29) & 1)
-#define TEXMODE_TRILINEAR(val) (((val) >> 30) & 1)
-#define TEXMODE_SEQ_8_DOWNLD(val) (((val) >> 31) & 1)
-
-#define TEXLOD_LODMIN(val) (((val) >> 0) & 0x3f)
-#define TEXLOD_LODMAX(val) (((val) >> 6) & 0x3f)
-#define TEXLOD_LODBIAS(val) (((val) >> 12) & 0x3f)
-#define TEXLOD_LOD_ODD(val) (((val) >> 18) & 1)
-#define TEXLOD_LOD_TSPLIT(val) (((val) >> 19) & 1)
-#define TEXLOD_LOD_S_IS_WIDER(val) (((val) >> 20) & 1)
-#define TEXLOD_LOD_ASPECT(val) (((val) >> 21) & 3)
-#define TEXLOD_LOD_ZEROFRAC(val) (((val) >> 23) & 1)
-#define TEXLOD_TMULTIBASEADDR(val) (((val) >> 24) & 1)
-#define TEXLOD_TDATA_SWIZZLE(val) (((val) >> 25) & 1)
-#define TEXLOD_TDATA_SWAP(val) (((val) >> 26) & 1)
-#define TEXLOD_TDIRECT_WRITE(val) (((val) >> 27) & 1) /* Voodoo 2 only */
-
-#define TEXDETAIL_DETAIL_MAX(val) (((val) >> 0) & 0xff)
-#define TEXDETAIL_DETAIL_BIAS(val) (((val) >> 8) & 0x3f)
-#define TEXDETAIL_DETAIL_SCALE(val) (((val) >> 14) & 7)
-#define TEXDETAIL_RGB_MIN_FILTER(val) (((val) >> 17) & 1) /* Voodoo 2 only */
-#define TEXDETAIL_RGB_MAG_FILTER(val) (((val) >> 18) & 1) /* Voodoo 2 only */
-#define TEXDETAIL_ALPHA_MIN_FILTER(val) (((val) >> 19) & 1) /* Voodoo 2 only */
-#define TEXDETAIL_ALPHA_MAG_FILTER(val) (((val) >> 20) & 1) /* Voodoo 2 only */
-#define TEXDETAIL_SEPARATE_RGBA_FILTER(val) (((val) >> 21) & 1) /* Voodoo 2 only */
-
-#define TREXINIT_SEND_TMU_CONFIG(val) (((val) >> 18) & 1)
-
-
-
-struct rgba
-{
-#ifdef LSB_FIRST
- uint8_t b, g, r, a;
-#else
- uint8_t a, r, g, b;
-#endif
-};
+// logging
+static constexpr bool LOG_VBLANK_SWAP = false;
+static constexpr bool LOG_FIFO = false;
+static constexpr bool LOG_FIFO_VERBOSE = false;
+static constexpr bool LOG_REGISTERS = false;
+static constexpr bool LOG_WAITS = false;
+static constexpr bool LOG_LFB = false;
+static constexpr bool LOG_TEXTURE_RAM = false;
+static constexpr bool LOG_CMDFIFO = false;
+static constexpr bool LOG_CMDFIFO_VERBOSE = false;
+}
-union voodoo_reg
-{
- int32_t i;
- uint32_t u;
- float f;
- rgba rgb;
-};
+//**************************************************************************
+// INTERNAL CLASSES
+//**************************************************************************
+// include register and render classes
+#include "voodoo_regs.h"
+#include "voodoo_render.h"
+namespace voodoo
+{
+// ======================> save_proxy
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
-/* enumeration specifying which model of Voodoo we are emulating */
-enum
+// save_proxy is a helper class to make hierarchical state saving more manageable;
+class save_proxy
{
- TYPE_VOODOO_1,
- TYPE_VOODOO_2,
- TYPE_VOODOO_BANSHEE,
- TYPE_VOODOO_3
-};
+public:
+ // constructor
+ save_proxy(device_t &device) :
+ m_device(device)
+ {
+ }
-#define STD_VOODOO_1_CLOCK 50000000
-#define STD_VOODOO_2_CLOCK 90000000
-#define STD_VOODOO_BANSHEE_CLOCK 90000000
-#define STD_VOODOO_3_CLOCK 132000000
+ // save an item; append the current prefix and pass through
+ template<typename T>
+ void save_item(T &&item, char const *name)
+ {
+ std::string fullname = m_prefix;
+ fullname += name;
+ m_device.save_item(std::forward<T>(item), fullname.c_str());
+ }
+ // save a pointer item; append the current prefix and pass through
+ template<typename T>
+ void save_pointer(T &&item, char const *name, u32 count)
+ {
+ std::string fullname = m_prefix;
+ fullname += name;
+ m_device.save_pointer(std::forward<T>(item), fullname.c_str(), count);
+ }
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
+ // save a class; update the prefix then call the register_save method on the class
+ template<typename T>
+ void save_class(T &item, char const *name)
+ {
+ std::string orig = m_prefix;
+ m_prefix += name;
+ m_prefix += "/";
+ item.register_save(*this);
+ m_prefix = orig;
+ }
-/* ----- device interface ----- */
+private:
+ // internal state
+ device_t &m_device;
+ std::string m_prefix;
+};
-class voodoo_device : public device_t
-{
-public:
- ~voodoo_device();
- void set_fbmem(int value) { m_fbmem = value; }
- void set_tmumem(int value1, int value2) { m_tmumem0 = value1; m_tmumem1 = value2; }
- template <typename T> void set_screen_tag(T &&tag) { m_screen_finder.set_tag(std::forward<T>(tag)); }
- template <typename T> void set_cpu_tag(T &&tag) { m_cpu_finder.set_tag(std::forward<T>(tag)); }
- auto vblank_callback() { return m_vblank.bind(); }
- auto stall_callback() { return m_stall.bind(); }
- auto pciint_callback() { return m_pciint.bind(); }
+// ======================> shared_tables
- void set_screen(screen_device &screen) { assert(!m_screen); m_screen = &screen; }
- void set_cpu(cpu_device &cpu) { assert(!m_cpu); m_cpu = &cpu; }
+// shared_tables are global tables that are shared between different components
+struct shared_tables
+{
+ // construction
+ shared_tables();
+
+ // texel lookups
+ rgb_t *texel[16]; // 16 texture formats
+
+ // 8-bit lookups
+ rgb_t rgb332[256]; // RGB 3-3-2 lookup table
+ rgb_t alpha8[256]; // alpha 8-bit lookup table
+ rgb_t int8[256]; // intensity 8-bit lookup table
+ rgb_t ai44[256]; // alpha, intensity 4-4 lookup table
+
+ // 16-bit lookups
+ rgb_t rgb565[65536]; // RGB 5-6-5 lookup table
+ rgb_t argb1555[65536]; // ARGB 1-5-5-5 lookup table
+ rgb_t argb4444[65536]; // ARGB 4-4-4-4 lookup table
+};
- u32 voodoo_r(offs_t offset);
- void voodoo_w(offs_t offset, u32 data, u32 mem_mask = ~0);
- uint8_t m_fbmem;
- uint8_t m_tmumem0;
- uint8_t m_tmumem1;
- devcb_write_line m_vblank;
- devcb_write_line m_stall;
- // This is for internally generated PCI interrupts in Voodoo3
- devcb_write_line m_pciint;
+// ======================> tmu_state
- TIMER_CALLBACK_MEMBER( vblank_off_callback );
- TIMER_CALLBACK_MEMBER( stall_cpu_callback );
- TIMER_CALLBACK_MEMBER( vblank_callback );
+// tmu_state holds TMU-specific register and palette state
+class tmu_state
+{
+public:
+ // construction
+ tmu_state();
- void voodoo_postload();
+ // initialization
+ void init(int index, shared_tables const &share, u8 *ram, u32 size);
- int voodoo_update(bitmap_rgb32 &bitmap, const rectangle &cliprect);
- int voodoo_get_type();
- int voodoo_is_stalled();
- void voodoo_set_init_enable(uint32_t newval);
+ // configuration
+ void set_baseaddr_mask_shift(u32 mask, u8 shift) { m_basemask = mask; m_baseshift = shift; }
-protected:
- voodoo_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint8_t vdt);
+ // state saving
+ void register_save(save_proxy &save);
+ void post_load();
- // device-level overrides
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
- virtual void device_stop() override;
- virtual void device_reset() override;
+ // simple getters
+ voodoo_regs &regs() { return m_reg; }
+ bool dirty() const { return m_regdirty; }
- struct tmu_shared_state;
+ // simple setters
+ void mark_dirty() { m_regdirty = true; }
- struct voodoo_stats
- {
- voodoo_stats()
- {
- std::fill(std::begin(texture_mode), std::end(texture_mode), 0);
- buffer[0] = 0;
- }
+ // write to the NCC/palette registers
+ void ncc_w(offs_t offset, u32 data);
- uint8_t lastkey = 0; // last key state
- uint8_t display = 0; // display stats?
- int32_t swaps = 0; // total swaps
- int32_t stalls = 0; // total stalls
- int32_t total_triangles = 0; // total triangles
- int32_t total_pixels_in = 0; // total pixels in
- int32_t total_pixels_out = 0; // total pixels out
- int32_t total_chroma_fail = 0; // total chroma fail
- int32_t total_zfunc_fail = 0; // total z func fail
- int32_t total_afunc_fail = 0; // total a func fail
- int32_t total_clipped = 0; // total clipped
- int32_t total_stippled = 0; // total stippled
- int32_t lfb_writes = 0; // LFB writes
- int32_t lfb_reads = 0; // LFB reads
- int32_t reg_writes = 0; // register writes
- int32_t reg_reads = 0; // register reads
- int32_t tex_writes = 0; // texture writes
- int32_t texture_mode[16]; // 16 different texture modes
- uint8_t render_override = 0; // render override
- char buffer[1024]; // string
- };
+ // prepare a texture for the renderer
+ rasterizer_texture &prepare_texture(voodoo_renderer &renderer);
+private:
+ // internal state
+ int m_index; // index of ourself
+ u8 *m_ram; // pointer to our RAM
+ u32 m_mask; // mask to apply to pointers
+ u32 m_basemask; // mask to apply to the texBaseAddr
+ u8 m_baseshift; // shift to apply to the texBaseAddr
+
+ // register state
+ voodoo_regs m_reg; // TMU registers
+ bool m_regdirty; // true if the LOD/mode/base registers have changed
+
+ // lookups
+ rgb_t const * const *m_texel_lookup; // texel lookups for each format
+
+ // palettes
+ bool m_palette_dirty[4]; // true if palette (0-1) or NCC (2-3) is dirty
+ rgb_t m_palette[2][256]; // 2 versions of the palette
+};
- /* note that this structure is an even 64 bytes long */
- struct stats_block
- {
- int32_t pixels_in = 0; // pixels in statistic
- int32_t pixels_out = 0; // pixels out statistic
- int32_t chroma_fail = 0; // chroma test fail statistic
- int32_t zfunc_fail = 0; // z function test fail statistic
- int32_t afunc_fail = 0; // alpha function test fail statistic
- int32_t clip_fail = 0; // clipping fail statistic
- int32_t stipple_count = 0; // stipple statistic
- int32_t filler[64/4 - 7]; // pad this structure to 64 bytes
- };
+// ======================> memory_fifo
- struct fifo_state
- {
- void reset() { in = out = 0; }
- void add(uint32_t data);
- uint32_t remove();
- uint32_t peek() { return base[out]; }
- bool empty() const { return in == out; }
- bool full() const { return ((in + 1) == out) || ((in == (size - 1)) && (out == 0)); }
- int32_t items() const;
- int32_t space() const { return size - 1 - items(); }
-
- uint32_t * base = nullptr; // base of the FIFO
- int32_t size = 0; // size of the FIFO
- int32_t in = 0; // input pointer
- int32_t out = 0; // output pointer
- };
+// memory_fifo is a simple memory access FIFO that is used on the frontend
+// PCI bus (64 entries) or within the framebuffer (up to 64k)
+class memory_fifo
+{
+public:
+ // FIFO flags, added to offset
+ static constexpr offs_t FLAGS_MASK = 0xf0000000;
+ static constexpr offs_t TYPE_MASK = 0xc0000000;
+ static constexpr offs_t TYPE_REGISTER = 0x00000000;
+ static constexpr offs_t TYPE_LFB = 0x40000000;
+ static constexpr offs_t TYPE_TEXTURE = 0x80000000;
+ static constexpr offs_t NO_16_31 = 0x20000000;
+ static constexpr offs_t NO_0_15 = 0x10000000;
+
+ // construction
+ memory_fifo();
+
+ // configuration
+ void configure(u32 *base, u32 size);
+
+ // state saving
+ void register_save(save_proxy &save);
+
+ // basic queries
+ bool configured() const { return (m_size != 0); }
+ u32 peek() const { return m_base[m_out]; }
+ bool empty() const { return (m_in == m_out); }
+ bool full() const { return ((m_in + 1) == m_out) || (m_in == (m_size - 1) && m_out == 0); }
+ s32 items() const { s32 result = m_in - m_out; if (result < 0) result += m_size; return result; }
+ s32 space() const { return m_size - 1 - items(); }
+
+ // reset
+ void reset() { m_in = m_out = 0; }
+
+ // add/remove items
+ void add(u32 data);
+ u32 remove();
+private:
+ // internal state
+ u32 *m_base; // base of the FIFO
+ s32 m_size; // size of the FIFO
+ s32 m_in; // input pointer
+ s32 m_out; // output pointer
+};
- struct cmdfifo_info
- {
- uint8_t enable = 0; // enabled?
- uint8_t count_holes = 0; // count holes?
- uint32_t base = 0; // base address in framebuffer RAM
- uint32_t end = 0; // end address in framebuffer RAM
- uint32_t rdptr = 0; // current read pointer
- uint32_t amin = 0; // minimum address
- uint32_t amax = 0; // maximum address
- uint32_t depth = 0; // current depth
- uint32_t holes = 0; // number of holes
- };
+// ======================> debug_stats
- struct pci_state
- {
- fifo_state fifo; // PCI FIFO
- uint32_t init_enable = 0; // initEnable value
- uint8_t stall_state = 0; // state of the system if we're stalled
- uint8_t op_pending = 0; // true if an operation is pending
- attotime op_end_time = attotime::zero; // time when the pending operation ends
- emu_timer * continue_timer = nullptr; // timer to use to continue processing
- uint32_t fifo_mem[64*2]; // memory backing the PCI FIFO
- };
+// debug_stats are enabled via DEBUG_STATS and displayed via the backslash key;
+// these are independent of the real on-chip stats kept in thread_stats_block
+class debug_stats
+{
+public:
+ // construction
+ debug_stats();
+ // add in states from the emulation
+ void add_emulation_stats(thread_stats_block const &block);
- struct tmu_state
- {
- class stw_t;
- void recompute_texture_params();
- void init(uint8_t vdt, tmu_shared_state &share, voodoo_reg *r, void *memory, int tmem);
- int32_t prepare();
- static int32_t new_log2(double &value, const int &offset);
- rgbaint_t genTexture(int32_t x, const uint8_t *dither4, const uint32_t TEXMODE, rgb_t *LOOKUP, int32_t LODBASE, const stw_t &iterstw, int32_t &lod);
- rgbaint_t combineTexture(const uint32_t TEXMODE, const rgbaint_t& c_local, const rgbaint_t& c_other, int32_t lod);
-
- struct ncc_table
- {
- void write(offs_t regnum, uint32_t data);
- void update();
-
- uint8_t dirty = 0; // is the texel lookup dirty?
- voodoo_reg * reg = nullptr; // pointer to our registers
- int32_t ir[4], ig[4], ib[4]; // I values for R,G,B
- int32_t qr[4], qg[4], qb[4]; // Q values for R,G,B
- int32_t y[16]; // Y values
- rgb_t * palette = nullptr; // pointer to associated RGB palette
- rgb_t * palettea = nullptr; // pointer to associated ARGB palette
- rgb_t texel[256]; // texel lookup
- };
-
- uint8_t * ram = nullptr; // pointer to our RAM
- uint32_t mask = 0; // mask to apply to pointers
- voodoo_reg * reg = nullptr; // pointer to our register base
- uint32_t regdirty = 0; // true if the LOD/mode/base registers have changed
-
- uint32_t texaddr_mask = 0; // mask for texture address
- uint8_t texaddr_shift = 0; // shift for texture address
-
- int64_t starts = 0, startt = 0; // starting S,T (14.18)
- int64_t startw = 0; // starting W (2.30)
- int64_t dsdx = 0, dtdx = 0; // delta S,T per X
- int64_t dwdx = 0; // delta W per X
- int64_t dsdy = 0, dtdy = 0; // delta S,T per Y
- int64_t dwdy = 0; // delta W per Y
-
- int32_t lodmin = 0, lodmax = 0; // min, max LOD values
- int32_t lodbias = 0; // LOD bias
- uint32_t lodmask = 0; // mask of available LODs
- uint32_t lodoffset[9]; // offset of texture base for each LOD
- int32_t detailmax = 0; // detail clamp
- int32_t detailbias = 0; // detail bias
- uint8_t detailscale = 0; // detail scale
-
- uint32_t wmask = 0; // mask for the current texture width
- uint32_t hmask = 0; // mask for the current texture height
-
- uint32_t bilinear_mask = 0; // mask for bilinear resolution (0xf0 for V1, 0xff for V2)
-
- ncc_table ncc[2]; // two NCC tables
-
- rgb_t * lookup = nullptr; // currently selected lookup
- rgb_t * texel[16]; // texel lookups for each format
-
- rgb_t palette[256]; // palette lookup table
- rgb_t palettea[256]; // palette+alpha lookup table
- };
+ // reset the stats
+ void reset();
+ // simple getters
+ bool displayed() const { return m_display; }
+ char const *string() const { return m_string.c_str(); }
- struct tmu_shared_state
- {
- void init();
+ // compute the string to display
+ void update_string(rectangle const &visarea, u32 swap_history);
- rgb_t rgb332[256]; // RGB 3-3-2 lookup table
- rgb_t alpha8[256]; // alpha 8-bit lookup table
- rgb_t int8[256]; // intensity 8-bit lookup table
- rgb_t ai44[256]; // alpha, intensity 4-4 lookup table
+ // based on the current key state, update and return whether stats should be shown
+ bool update_display_state(bool key_pressed);
- rgb_t* rgb565; // RGB 5-6-5 lookup table
- rgb_t argb1555[65536]; // ARGB 1-5-5-5 lookup table
- rgb_t argb4444[65536]; // ARGB 4-4-4-4 lookup table
- };
+ // public access to the statistics that are hand-updated
+ s32 m_swaps; // total swaps
+ s32 m_stalls; // total stalls
+ s32 m_triangles; // total triangles
+ s32 m_lfb_writes; // LFB writes
+ s32 m_lfb_reads; // LFB reads
+ s32 m_reg_writes; // register writes
+ s32 m_reg_reads; // register reads
+ s32 m_tex_writes; // texture writes
+ s32 m_texture_mode[16]; // 16 different texture modes
+private:
+ // stats that are updated from emulation stats
+ s32 m_pixels_in; // total pixels in
+ s32 m_pixels_out; // total pixels out
+ s32 m_chroma_fail; // total chroma fail
+ s32 m_zfunc_fail; // total z func fail
+ s32 m_afunc_fail; // total a func fail
+ s32 m_clipped; // total clipped
+ s32 m_stippled; // total stippled
+
+ // internal state
+ bool m_lastkey; // last key state
+ bool m_display; // display stats?
+ std::string m_string; // string
+};
- struct fbi_state
- {
- struct setup_vertex
- {
- 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
- };
-
- uint8_t * ram = nullptr; // pointer to frame buffer RAM
- uint32_t mask = 0; // mask to apply to pointers
- uint32_t rgboffs[3] = { 0, 0, 0 }; // word offset to 3 RGB buffers
- uint32_t auxoffs = 0; // word offset to 1 aux buffer
-
- uint8_t frontbuf = 0; // front buffer index
- uint8_t backbuf = 0; // back buffer index
- uint8_t swaps_pending = 0; // number of pending swaps
- uint8_t video_changed = 0; // did the frontbuffer video change?
-
- uint32_t yorigin = 0; // Y origin subtract value
- uint32_t lfb_base = 0; // base of LFB in memory
- uint8_t lfb_stride = 0; // stride of LFB accesses in bits
-
- uint32_t width = 0; // width of current frame buffer
- uint32_t height = 0; // height of current frame buffer
- uint32_t xoffs = 0; // horizontal offset (back porch)
- uint32_t yoffs = 0; // vertical offset (back porch)
- uint32_t vsyncstart = 0; // vertical sync start scanline
- uint32_t vsyncstop = 0; // vertical sync stop
- uint32_t rowpixels = 0; // pixels per row
- uint32_t tile_width = 0; // width of video tiles
- uint32_t tile_height = 0; // height of video tiles
- uint32_t x_tiles = 0; // number of tiles in the X direction
-
- emu_timer * vsync_stop_timer = nullptr; // VBLANK End timer
- emu_timer * vsync_start_timer = nullptr; // VBLANK timer
- uint8_t vblank = 0; // VBLANK state
- uint8_t vblank_count = 0; // number of VBLANKs since last swap
- uint8_t vblank_swap_pending = 0;// a swap is pending, waiting for a vblank
- uint8_t vblank_swap = 0; // swap when we hit this count
- uint8_t vblank_dont_swap = 0; // don't actually swap when we hit this point
-
- /* triangle setup info */
- uint8_t cheating_allowed = 0; // allow cheating?
- int32_t sign; // triangle sign
- int16_t ax, ay; // vertex A x,y (12.4)
- int16_t bx, by; // vertex B x,y (12.4)
- int16_t cx, cy; // vertex C x,y (12.4)
- int32_t startr, startg, startb, starta; // starting R,G,B,A (12.12)
- int32_t startz; // starting Z (20.12)
- int64_t startw; // starting W (16.32)
- int32_t drdx, dgdx, dbdx, dadx; // delta R,G,B,A per X
- int32_t dzdx; // delta Z per X
- int64_t dwdx; // delta W per X
- int32_t drdy, dgdy, dbdy, dady; // delta R,G,B,A per Y
- int32_t dzdy; // delta Z per Y
- int64_t dwdy; // delta W per Y
-
- stats_block lfb_stats; // LFB-access statistics
-
- uint8_t sverts = 0; // number of vertices ready */
- setup_vertex svert[3]; // 3 setup vertices */
-
- fifo_state fifo; // framebuffer memory fifo */
- cmdfifo_info cmdfifo[2]; // command FIFOs */
-
- uint8_t fogblend[64]; // 64-entry fog table */
- uint8_t fogdelta[64]; // 64-entry fog table */
- uint8_t fogdelta_mask; // mask for for delta (0xff for V1, 0xfc for V2) */
-
- rgb_t pen[65536]; // mapping from pixels to pens */
- rgb_t clut[512]; // clut gamma data */
- uint8_t clut_dirty = 1; // do we need to recompute? */
- rgb_t rgb565[65536]; // RGB 5-6-5 lookup table */
- };
+// ======================> static_register_table_entry
- struct dac_state
+// static_register_table_entry represents a read/write handler pair for Voodoo
+// registers, along with a valid mask, access flags, and a string name
+template<typename BaseType>
+struct static_register_table_entry
+{
+ static constexpr u32 make_mask(int maskbits)
{
- void data_w(uint8_t regum, uint8_t data);
- void data_r(uint8_t regnum);
-
- uint8_t reg[8]; // 8 registers
- uint8_t read_result; // pending read result
- };
+ if (maskbits == 0)
+ return 0;
+ if (maskbits == 32)
+ return 0xffffffff;
+ return (1 << maskbits) - 1;
+ }
+ using read_handler = u32 (BaseType::*)(u32 chipmask, u32 regnum);
+ using write_handler = u32 (BaseType::*)(u32 chipmask, u32 regnum, u32 data);
- struct raster_info
- {
- uint32_t compute_hash() const;
-
- raster_info * next = nullptr; // pointer to next entry with the same hash
- poly_draw_scanline_func callback = nullptr; // callback pointer
- bool is_generic = false; // true if this is one of the generic rasterizers
- uint8_t display; // display index
- uint32_t hits; // how many hits (pixels) we've used this for
- uint32_t polys; // how many polys we've used this for
- uint32_t eff_color_path; // effective fbzColorPath value
- uint32_t eff_alpha_mode; // effective alphaMode value
- uint32_t eff_fog_mode; // effective fogMode value
- uint32_t eff_fbz_mode; // effective fbzMode value
- uint32_t eff_tex_mode_0; // effective textureMode value for TMU #0
- uint32_t eff_tex_mode_1; // effective textureMode value for TMU #1
- uint32_t hash = 0U;
- };
-
+ u32 m_mask; // mask to apply to written data
+ u32 m_chipmask_flags; // valid chips, plus flags
+ char const *m_name; // string name
+ write_handler m_write; // write handler
+ read_handler m_read; // read handler
+};
- struct poly_extra_data;
+// ======================> register_table_entry
- struct banshee_info
+// register_table_entry is a live version of static_register_table_entry with
+// bound delegates in place of the member function pointers
+class register_table_entry
+{
+public:
+ // internal delegates
+ using read_handler = delegate<u32 (u32, u32)>;
+ using write_handler = delegate<u32 (u32, u32, u32)>;
+
+ // flags for the chipmask
+ static constexpr u32 CHIPMASK_NA = 0x0000;
+ static constexpr u32 CHIPMASK_FBI = 0x0001;
+ static constexpr u32 CHIPMASK_TREX = 0x0006;
+ static constexpr u32 CHIPMASK_FBI_TREX = 0x0007;
+
+ // flags for the sync state
+ static constexpr u32 SYNC_NA = 0x0000;
+ static constexpr u32 SYNC_NOSYNC = 0x0000;
+ static constexpr u32 SYNC_SYNC = 0x0100;
+
+ // flags for the FIFO state
+ static constexpr u32 FIFO_NA = 0x0000;
+ static constexpr u32 FIFO_NOFIFO = 0x0000;
+ static constexpr u32 FIFO_FIFO = 0x0200;
+
+ // simple getters
+ char const *name() const { return m_name; }
+ bool is_sync() const { return ((m_chipmask_flags & SYNC_SYNC) != 0); }
+ bool is_fifo() const { return ((m_chipmask_flags & FIFO_FIFO) != 0); }
+
+ // read/write helpers
+ u32 read(voodoo_1_device &device, u32 chipmask, u32 regnum) const;
+ u32 write(voodoo_1_device &device, u32 chipmask, u32 regnum, u32 data) const;
+
+ // unpack from a static entry
+ template<typename BaseType>
+ void unpack(static_register_table_entry<BaseType> const &source, BaseType &device)
{
- uint32_t io[0x40]; // I/O registers
- uint32_t agp[0x80]; // AGP registers
- uint8_t vga[0x20]; // VGA registers
- uint8_t crtc[0x27]; // VGA CRTC registers
- uint8_t seq[0x05]; // VGA sequencer registers
- uint8_t gc[0x05]; // VGA graphics controller registers
- uint8_t att[0x15]; // VGA attribute registers
- uint8_t attff; // VGA attribute flip-flop
-
- uint32_t blt_regs[0x20]; // 2D Blitter registers
- uint32_t blt_dst_base = 0;
- uint32_t blt_dst_x = 0;
- uint32_t blt_dst_y = 0;
- uint32_t blt_dst_width = 0;
- uint32_t blt_dst_height = 0;
- uint32_t blt_dst_stride = 0;
- uint32_t blt_dst_bpp = 0;
- uint32_t blt_cmd = 0;
- uint32_t blt_src_base = 0;
- uint32_t blt_src_x = 0;
- uint32_t blt_src_y = 0;
- uint32_t blt_src_width = 0;
- uint32_t blt_src_height = 0;
- uint32_t blt_src_stride = 0;
- uint32_t blt_src_bpp = 0;
- };
+ m_mask = source.m_mask;
+ m_chipmask_flags = source.m_chipmask_flags;
+ m_name = source.m_name;
+ m_write = write_handler(source.m_write, &device);
+ m_read = read_handler(source.m_read, &device);
+ }
+private:
+ // internal state
+ u32 m_mask; // mask to apply to written data
+ u32 m_chipmask_flags; // valid chips, plus flags
+ char const *m_name; // string name
+ write_handler m_write; // write handler
+ read_handler m_read; // read handler
+};
- static const raster_info predef_raster_table[];
+}
- // not all of these need to be static, review.
- void check_stalled_cpu(attotime current_time);
- static void flush_fifos( voodoo_device* vd, attotime current_time);
- static void init_fbi(voodoo_device *vd, fbi_state *f, void *memory, int fbmem);
- static int32_t register_w(voodoo_device *vd, offs_t offset, uint32_t data);
- static int32_t swapbuffer(voodoo_device *vd, uint32_t data);
- static int32_t lfb_w(voodoo_device *vd, offs_t offset, uint32_t data, uint32_t mem_mask);
- static int32_t texture_w(voodoo_device *vd, offs_t offset, uint32_t data);
- int32_t lfb_direct_w(offs_t offset, uint32_t data, uint32_t mem_mask);
- static int32_t banshee_2d_w(voodoo_device *vd, offs_t offset, uint32_t data);
- void stall_cpu(int state, attotime current_time);
- void soft_reset();
- void recompute_video_memory();
- void adjust_vblank_timer();
- static int32_t fastfill(voodoo_device *vd);
- static int32_t triangle(voodoo_device *vd);
- static int32_t begin_triangle(voodoo_device *vd);
- static int32_t draw_triangle(voodoo_device *vd);
- static int32_t setup_and_draw_triangle(voodoo_device *vd);
- static int32_t triangle_create_work_item(voodoo_device* vd,uint16_t *drawbuf, int texcount);
- static raster_info *add_rasterizer(voodoo_device *vd, const raster_info *cinfo);
- static raster_info *find_rasterizer(voodoo_device *vd, int texcount);
- static void dump_rasterizer_stats(voodoo_device *vd);
-
- void accumulate_statistics(const stats_block &block);
- void update_statistics(bool accumulate);
- void reset_counters();
+//**************************************************************************
+// GENERIC VOODOO DEVICE
+//**************************************************************************
- static uint32_t register_r(voodoo_device *vd, offs_t offset);
+// ======================> generic_voodoo_device
+
+// generic_voodoo_device is a base class that can be used to represent any of the
+// specific voodoo devices below
+class generic_voodoo_device : public device_t, public device_video_interface
+{
+public:
+ // configuration
+ void set_fbmem(int value) { m_fbmem_in_mb = value; }
+ void set_tmumem(int value1, int value2) { m_tmumem0_in_mb = value1; m_tmumem1_in_mb = value2; }
+ void set_status_cycles(u32 value) { m_status_cycles = value; }
+ template <typename T> void set_cpu(T &&tag) { m_cpu.set_tag(std::forward<T>(tag)); }
+ auto vblank_callback() { return m_vblank_cb.bind(); }
+ auto stall_callback() { return m_stall_cb.bind(); }
+ auto pciint_callback() { return m_pciint_cb.bind(); }
- static void swap_buffers(voodoo_device *vd);
- int cmdfifo_compute_expected_depth(cmdfifo_info &f);
- static uint32_t cmdfifo_execute(voodoo_device *vd, cmdfifo_info *f);
- int32_t cmdfifo_execute_if_ready(cmdfifo_info &f);
- static void cmdfifo_w(voodoo_device *vd, cmdfifo_info *f, offs_t offset, uint32_t data);
+ // getters
+ voodoo::voodoo_model model() const { return m_model; }
- static void init_save_state(voodoo_device *vd);
+ // address map and read/write helpers
+ virtual void core_map(address_map &map) = 0;
+ virtual u32 read(offs_t offset, u32 mem_mask = ~0) = 0;
+ virtual void write(offs_t offset, u32 data, u32 mem_mask = ~0) = 0;
- static void raster_fastfill(void *dest, int32_t scanline, const poly_extent *extent, const void *extradata, int threadid);
- static void raster_generic_0tmu(void *dest, int32_t scanline, const poly_extent *extent, const void *extradata, int threadid);
- static void raster_generic_1tmu(void *dest, int32_t scanline, const poly_extent *extent, const void *extradata, int threadid);
- static void raster_generic_2tmu(void *dest, int32_t scanline, const poly_extent *extent, const void *extradata, int threadid);
+ // external control
+ virtual void set_init_enable(u32 newval) = 0;
-#define RASTERIZER_HEADER(name) \
- static void raster_##name(void *destbase, int32_t y, const poly_extent *extent, const void *extradata, int threadid);
-#define RASTERIZER_ENTRY(fbzcp, alpha, fog, fbz, tex0, tex1) \
- RASTERIZER_HEADER(fbzcp##_##alpha##_##fog##_##fbz##_##tex0##_##tex1)
-#include "voodoo_rast.ipp"
+ // video update
+ virtual int update(bitmap_rgb32 &bitmap, const rectangle &cliprect) = 0;
-#undef RASTERIZER_ENTRY
+protected:
+ // internal construction
+ generic_voodoo_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, voodoo::voodoo_model model);
- static bool chromaKeyTest(voodoo_device *vd, stats_block *stats, uint32_t fbzModeReg, rgbaint_t rgaIntColor);
- static bool alphaMaskTest(stats_block *stats, uint32_t fbzModeReg, uint8_t alpha);
- static bool alphaTest(uint8_t alpharef, stats_block *stats, uint32_t alphaModeReg, uint8_t alpha);
- static bool depthTest(uint16_t zaColorReg, stats_block *stats, int32_t destDepth, uint32_t fbzModeReg, int32_t biasdepth);
- static bool combineColor(voodoo_device *vd, stats_block *STATS, uint32_t FBZCOLORPATH, uint32_t FBZMODE, rgbaint_t TEXELARGB, int32_t ITERZ, int64_t ITERW, rgbaint_t &srcColor);
+ // device-level overrides
+ virtual void device_start() override;
-// FIXME: this stuff should not be public
-public:
- optional_device<screen_device> m_screen_finder; // the screen we are acting on
- optional_device<cpu_device> m_cpu_finder; // the CPU we interact with
+ // configuration
+ const voodoo::voodoo_model m_model; // which voodoo model
+ u8 m_fbmem_in_mb; // framebuffer memory, in MB
+ u8 m_tmumem0_in_mb; // TMU0 memory, in MB
+ u8 m_tmumem1_in_mb; // TMU1 memory, in MB
+ u32 m_status_cycles; // number of cycles to eat on status reads (optimization)
+ required_device<cpu_device> m_cpu; // the CPU we interact with
+ devcb_write_line m_vblank_cb; // VBLANK callback
+ devcb_write_line m_stall_cb; // stalling callback
+ devcb_write_line m_pciint_cb; // PCI interrupt callback
+};
- std::unique_ptr<uint8_t[]> m_fbmem_alloc;
- std::unique_ptr<uint8_t[]> m_tmumem_alloc[2];
- uint8_t index; // index of board
- screen_device * m_screen; // the screen we are acting on
- cpu_device * m_cpu; // the CPU we interact with
- const uint8_t vd_type; // type of system
- uint8_t chipmask; // mask for which chips are available
- uint32_t freq; // operating frequency
- attoseconds_t attoseconds_per_cycle; // attoseconds per cycle
- uint32_t extra_cycles; // extra cycles not yet accounted for
- int trigger; // trigger used for stalling
+//**************************************************************************
+// VOODOO 1 DEVICE
+//**************************************************************************
- voodoo_reg reg[0x400]; // raw registers
- const uint8_t * regaccess; // register access array
- const char *const * regnames; // register names array
- uint8_t alt_regmap; // enable alternate register map?
+DECLARE_DEVICE_TYPE(VOODOO_1, voodoo_1_device)
- pci_state pci; // PCI state
- dac_state dac; // DAC state
+// ======================> voodoo_1_device
- fbi_state fbi; // FBI states
- tmu_state tmu[MAX_TMU]; // TMU states
- tmu_shared_state tmushare; // TMU shared state
- banshee_info banshee; // Banshee state
+// voodoo_1_device represents the original generation of 3dfx Voodoo Graphics devices;
+// these devices have independent framebuffer and texture memory, and can be flexibly
+// configured with 1 or 2 TMUs
+class voodoo_1_device : public generic_voodoo_device
+{
+ friend class voodoo::register_table_entry;
- legacy_poly_manager_owner poly; // polygon manager
- std::unique_ptr<stats_block[]> thread_stats; // per-thread statistics
+ // enumeration describing reasons we might be stalled
+ enum stall_state : u8
+ {
+ NOT_STALLED = 0,
+ STALLED_UNTIL_FIFO_LWM,
+ STALLED_UNTIL_FIFO_EMPTY
+ };
- voodoo_stats stats; // internal statistics
+ // flags for LFB writes
+ static constexpr u8 LFB_RGB_PRESENT_0 = 0x01;
+ static constexpr u8 LFB_ALPHA_PRESENT_0 = 0x02;
+ static constexpr u8 LFB_DEPTH_PRESENT_0 = 0x04;
+ static constexpr u8 LFB_DEPTH_PRESENT_MSW_0 = 0x08;
+ static constexpr u8 LFB_PIXEL0_MASK = 0x0f;
- offs_t last_status_pc; // PC of last status description (for logging)
- uint32_t last_status_value; // value of last status read (for logging)
+ static constexpr u8 LFB_RGB_PRESENT_1 = 0x10;
+ static constexpr u8 LFB_ALPHA_PRESENT_1 = 0x20;
+ static constexpr u8 LFB_DEPTH_PRESENT_1 = 0x40;
+ static constexpr u8 LFB_PIXEL1_MASK = 0x70;
- int next_rasterizer; // next rasterizer index
- raster_info rasterizer[MAX_RASTERIZERS]; // array of rasterizers
- raster_info * raster_hash[RASTER_HASH_SIZE]; // hash table of rasterizers
+protected:
+ // number of clocks to set up a triangle (just a guess)
+ static constexpr u32 TRIANGLE_SETUP_CLOCKS = 100;
- bool send_config;
- uint32_t tmu_config;
-};
+ // internal construction
+ voodoo_1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, voodoo::voodoo_model model);
-class voodoo_1_device : public voodoo_device
-{
public:
- voodoo_1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-};
+ // nominal clock values
+ static constexpr u32 NOMINAL_CLOCK = 50'000'000;
+ // construction
+ voodoo_1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ voodoo_1_device(mconfig, VOODOO_1, tag, owner, clock, voodoo::voodoo_model::VOODOO_1) { }
-class voodoo_2_device : public voodoo_device
-{
-public:
- voodoo_2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-};
+ // destruction
+ virtual ~voodoo_1_device();
+ // 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;
-class voodoo_banshee_device : public voodoo_device
-{
-public:
- voodoo_banshee_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- u32 banshee_r(offs_t offset, u32 mem_mask = ~0);
- void banshee_w(offs_t offset, u32 data, u32 mem_mask = ~0);
- u32 banshee_fb_r(offs_t offset);
- void banshee_fb_w(offs_t offset, u32 data, u32 mem_mask = ~0);
- u32 banshee_io_r(offs_t offset, u32 mem_mask = ~0);
- void banshee_io_w(offs_t offset, u32 data, u32 mem_mask = ~0);
- u32 banshee_rom_r(offs_t offset);
- u8 banshee_vga_r(offs_t offset);
- void banshee_vga_w(offs_t offset, u8 data);
+ // external control
+ virtual void set_init_enable(u32 newval) override;
-protected:
- voodoo_banshee_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint8_t vdt);
+ // video update
+ virtual int update(bitmap_rgb32 &bitmap, const rectangle &cliprect) override;
+protected:
// device-level overrides
- u32 banshee_agp_r(offs_t offset);
- void banshee_agp_w(offs_t offset, u32 data, u32 mem_mask = ~0);
-};
+ virtual void device_start() override;
+ virtual void device_stop() override;
+ virtual void device_reset() override;
+ virtual void device_post_load() override;
+
+ // system management
+ virtual void soft_reset();
+ virtual void register_save(voodoo::save_proxy &save, u32 total_allocation);
+
+ // buffer accessors
+ virtual u16 *draw_buffer_indirect(int index);
+ virtual u16 *lfb_buffer_indirect(int index);
+ u16 *draw_buffer(int index) const { return (u16 *)(m_fbram + m_rgboffs[index]); }
+ u16 *front_buffer() const { return draw_buffer(m_frontbuf); }
+ u16 *back_buffer() const { return draw_buffer(m_backbuf); }
+ u16 *aux_buffer() const { return (m_auxoffs != ~0) ? (u16 *)(m_fbram + m_auxoffs) : nullptr; }
+ u16 *ram_end() const { return (u16 *)(m_fbram + m_fbmask + 1); }
+
+ // read/write and FIFO helpers
+ void prepare_for_read();
+ bool prepare_for_write();
+ void recompute_fbmem_fifo();
+ void add_to_fifo(u32 offset, u32 data, u32 mem_mask);
+ void flush_fifos(attotime current_time);
+ virtual u32 execute_fifos();
+
+ // mapped reads
+ u32 map_register_r(offs_t offset);
+ u32 map_lfb_r(offs_t offset);
+
+ // mapped writes
+ void map_register_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+ void map_lfb_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+ void map_texture_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+
+ // internal reads and writes
+ u32 internal_lfb_r(offs_t offset);
+ void internal_lfb_w(offs_t offset, u32 data, u32 mem_mask);
+ u32 expand_lfb_data(voodoo::reg_lfb_mode const lfbmode, u32 data, rgb_t src_color[2], u16 src_depth[2]);
+ virtual void internal_texture_w(offs_t offset, u32 data);
+
+ // register read accessors
+ u32 reg_invalid_r(u32 chipmask, u32 regnum);
+ u32 reg_passive_r(u32 chipmask, u32 regnum);
+ u32 reg_status_r(u32 chipmask, u32 regnum);
+ u32 reg_fbiinit2_r(u32 chipmask, u32 regnum);
+ u32 reg_vretrace_r(u32 chipmask, u32 regnum);
+ u32 reg_stats_r(u32 chipmask, u32 regnum);
+
+ // register write accessors
+ u32 reg_invalid_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_unimplemented_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_passive_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_fpassive_4_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_fpassive_12_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_starts_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_startt_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_dsdx_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_dtdx_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_dsdy_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_dtdy_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_fstarts_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_fstartt_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_fdsdx_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_fdtdx_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_fdsdy_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_fdtdy_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_startw_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_dwdx_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_dwdy_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_fstartw_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_fdwdx_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_fdwdy_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_triangle_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_nop_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_fastfill_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_swapbuffer_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_fogtable_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_fbiinit_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_video_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_clut_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_dac_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_texture_w(u32 chipmask, u32 regnum, u32 data);
+ u32 reg_palette_w(u32 chipmask, u32 regnum, u32 data);
+
+ // VBLANK timing
+ void adjust_vblank_start_timer();
+ virtual void vblank_start(void *ptr, s32 param);
+ virtual void vblank_stop(void *ptr, s32 param);
+ void swap_buffers();
+ virtual void rotate_buffers();
+
+ // video timing and updates
+ int update_common(bitmap_rgb32 &bitmap, const rectangle &cliprect, rgb_t const *pens);
+ void recompute_video_timing(u32 hsyncon, u32 hsyncoff, u32 hvis, u32 hbp, u32 vsyncon, u32 vsyncoff, u32 vvis, u32 vbp);
+ virtual void recompute_video_memory();
+ void recompute_video_memory_common(u32 config, u32 rowpixels);
+
+ // rendering
+ voodoo::voodoo_renderer &renderer() { return *m_renderer; }
+ s32 triangle();
+
+ // statistics
+ void accumulate_statistics(const voodoo::thread_stats_block &block);
+ void update_statistics(bool accumulate);
+ void reset_counters();
+
+ // stall management
+ bool operation_pending() const { return !m_operation_end.is_zero(); }
+ void clear_pending_operation() { m_operation_end = attotime::zero; }
+ void check_stalled_cpu(attotime current_time);
+ void stall_cpu(stall_state state);
+ void stall_resume_callback(void *ptr, s32 param);
+ // misc helpers
+ u32 chipmask_from_offset(u32 offset)
+ {
+ u32 chipmask = BIT(offset, 8, 4);
+ if (chipmask == 0)
+ chipmask = 0xf;
+ return chipmask & m_chipmask;
+ }
-class voodoo_3_device : public voodoo_banshee_device
-{
-public:
- voodoo_3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ // configuration
+ u8 m_chipmask; // mask for which chips are available
+
+ // PCI state/FIFOs
+ voodoo::reg_init_en m_init_enable; // initEnable value (set externally)
+ stall_state m_stall_state; // state of the system if we're stalled
+ int m_stall_trigger; // trigger used for stalling
+ attotime m_operation_end; // time when the pending operation ends
+ voodoo::memory_fifo m_pci_fifo; // PCI FIFO
+ voodoo::memory_fifo m_fbmem_fifo; // framebuffer memory fifo
+ bool m_flush_flag; // true if we are currently flushing FIFOs
+
+ // allocated memory
+ u8 *m_fbram; // pointer to aligned framebuffer
+ u32 m_fbmask; // mask to apply to pointers
+ std::unique_ptr<u8[]> m_memory; // allocated framebuffer/texture memory
+ std::unique_ptr<voodoo::shared_tables> m_shared; // shared tables
+ std::unique_ptr<voodoo::voodoo_renderer> m_renderer; // rendering helper
+
+ // video buffer configuration
+ u32 m_rgboffs[3]; // word offset to 3 RGB buffers
+ u32 m_auxoffs; // word offset to 1 aux buffer
+ u8 m_frontbuf; // front buffer index
+ u8 m_backbuf; // back buffer index
+ bool m_video_changed; // did the frontbuffer video change?
+
+ // linear frame buffer access configuration
+ u8 m_lfb_stride; // stride of LFB accesses in bits
+
+ // video configuration
+ u32 m_width; // width of current frame buffer
+ u32 m_height; // height of current frame buffer
+ u32 m_xoffs; // horizontal offset (back porch)
+ u32 m_yoffs; // vertical offset (back porch)
+ u32 m_vsyncstart; // vertical sync start scanline
+ u32 m_vsyncstop; // vertical sync stop
+
+ // VBLANK/swapping state
+ u8 m_swaps_pending; // number of pending swaps
+ u8 m_vblank; // VBLANK state
+ u8 m_vblank_count; // number of VBLANKs since last swap
+ u8 m_vblank_swap_pending; // a swap is pending, waiting for a vblank
+ u8 m_vblank_swap; // swap when we hit this count
+ u8 m_vblank_dont_swap; // don't actually swap when we hit this point
+
+ // register state
+ voodoo::voodoo_regs m_reg; // FBI registers
+ voodoo::register_table_entry m_regtable[256]; // generated register table
+ voodoo::tmu_state m_tmu[2]; // TMU states
+ u8 m_dac_reg[32]; // up to 32 DAC registers
+ u8 m_dac_read_result; // pending DAC read result
+
+ // timers
+ emu_timer *m_vsync_start_timer; // VBLANK timer
+ emu_timer *m_vsync_stop_timer; // VBLANK end timer
+ emu_timer *m_stall_resume_timer; // timer to resume processing after stall
+
+ // statistics
+ voodoo::debug_stats m_stats; // internal statistics
+ voodoo::thread_stats_block m_lfb_stats; // LFB access statistics
+
+ // tracking for logging
+ offs_t m_last_status_pc; // PC of last status description (for logging)
+ u32 m_last_status_value; // value of last status read (for logging)
+
+ // memory for PCI FIFO
+ u32 m_pci_fifo_mem[64*2]; // memory backing the PCI FIFO
+
+ // pens and CLUT
+ bool m_clut_dirty; // do we need to recompute?
+ std::vector<rgb_t> m_clut; // clut gamma data
+ std::vector<rgb_t> m_pen; // mapping from pixels to pens
+
+ // register table
+ static voodoo::static_register_table_entry<voodoo_1_device> const s_register_table[256];
};
-DECLARE_DEVICE_TYPE(VOODOO_1, voodoo_1_device)
-DECLARE_DEVICE_TYPE(VOODOO_2, voodoo_2_device)
-DECLARE_DEVICE_TYPE(VOODOO_BANSHEE, voodoo_banshee_device)
-DECLARE_DEVICE_TYPE(VOODOO_3, voodoo_3_device)
+//**************************************************************************
+// INLINE FUNCITIONS
+//**************************************************************************
-// use SSE on 64-bit implementations, where it can be assumed
-#if 1 && ((!defined(MAME_DEBUG) || defined(__OPTIMIZE__)) && (defined(__SSE2__) || defined(_MSC_VER)) && defined(PTR64))
-#include <emmintrin.h>
-#ifdef __SSE4_1__
-#include <smmintrin.h>
-#endif
-class voodoo_device::tmu_state::stw_t
+//-------------------------------------------------
+// write - handle a write through a register table
+// entry, performing any necessary logging
+//-------------------------------------------------
+
+inline u32 voodoo::register_table_entry::write(voodoo_1_device &device, u32 chipmask, u32 regnum, u32 data) const
{
-public:
- stw_t() { }
- stw_t(const stw_t& other) = default;
- stw_t &operator=(const stw_t& other) = default;
+ // statistics if enabled
+ if (DEBUG_STATS)
+ device.m_stats.m_reg_writes++;
- void set(s64 s, s64 t, s64 w) { m_st = _mm_set_pd(s << 8, t << 8); m_w = _mm_set1_pd(w); }
- int is_w_neg() const { return _mm_comilt_sd(m_w, _mm_set1_pd(0.0)); }
- void get_st_shiftr(s32 &s, s32 &t, const s32 &shift) const
- {
- s64 tmpS = _mm_cvtsd_si64(_mm_shuffle_pd(m_st, _mm_setzero_pd(), 1));
- s = tmpS >> shift;
- s64 tmpT = _mm_cvtsd_si64(m_st);
- t = tmpT >> shift;
- }
- void add(const stw_t& other)
+ // log if enabled
+ if (LOG_REGISTERS)
{
- m_st = _mm_add_pd(m_st, other.m_st);
- m_w = _mm_add_pd(m_w, other.m_w);
+ if (regnum < voodoo_regs::reg_fvertexAx || regnum > voodoo_regs::reg_fdWdY)
+ device.logerror("VOODOO.REG:%s(%d) write = %08X\n", m_name, chipmask, data);
+ else
+ device.logerror("VOODOO.REG:%s(%d) write = %f\n", m_name, chipmask, double(u2f(data)));
}
- void calc_stow(s32 &sow, s32 &tow, int32_t &oowlog) const
- {
- __m128d tmp = _mm_div_pd(m_st, m_w);
- // Allow for 8 bits of decimal in integer
- //tmp = _mm_mul_pd(tmp, _mm_set1_pd(256.0));
- __m128i tmp2 = _mm_cvttpd_epi32(tmp);
-#ifdef __SSE4_1__
- sow = _mm_extract_epi32(tmp2, 1);
- tow = _mm_extract_epi32(tmp2, 0);
-#else
- sow = _mm_cvtsi128_si32(_mm_shuffle_epi32(tmp2, _MM_SHUFFLE(0, 0, 0, 1)));
- tow = _mm_cvtsi128_si32(tmp2);
-#endif
- double dW = _mm_cvtsd_f64(m_w);
- oowlog = -new_log2(dW, 0);
- }
-private:
- __m128d m_st;
- __m128d m_w;
-};
-#else
-class voodoo_device::tmu_state::stw_t
+ return m_write(chipmask & m_chipmask_flags, regnum, data & m_mask);
+}
+
+
+//-------------------------------------------------
+// read - handle a read through a register table
+// entry, performing any necessary logging
+//-------------------------------------------------
+
+inline u32 voodoo::register_table_entry::read(voodoo_1_device &device, u32 chipmask, u32 regnum) const
{
-public:
- stw_t() {}
- stw_t(const stw_t& other) = default;
- stw_t &operator=(const stw_t& other) = default;
+ // statistics if enabled
+ if (DEBUG_STATS)
+ device.m_stats.m_reg_reads++;
- void set(s64 s, s64 t, s64 w) { m_s = s; m_t = t; m_w = w; }
- int is_w_neg() const { return (m_w < 0) ? 1 : 0; }
- void get_st_shiftr(s32 &s, s32 &t, const s32 &shift) const
- {
- s = m_s >> shift;
- t = m_t >> shift;
- }
- inline void add(const stw_t& other)
- {
- m_s += other.m_s;
- m_t += other.m_t;
- m_w += other.m_w;
- }
- // Computes s/w and t/w and returns log2 of 1/w
- // s, t and c are 16.32 values. The results are 24.8.
- inline void calc_stow(s32 &sow, s32 &tow, int32_t &oowlog) const
+ // get the result
+ u32 result = m_read(chipmask & m_chipmask_flags, regnum) & m_mask;
+
+ // log if enabled
+ if (LOG_REGISTERS)
{
- double recip = double(1ULL << (47 - 39)) / m_w;
- double resAD = m_s * recip;
- double resBD = m_t * recip;
- oowlog = new_log2(recip, 56);
- sow = resAD;
- tow = resBD;
+ // don't log multiple identical status reads from the same address
+ bool logit = true;
+ if (regnum == voodoo_regs::reg_vdstatus)
+ {
+ offs_t pc = device.m_cpu->pc();
+ if (pc == device.m_last_status_pc && result == device.m_last_status_value)
+ logit = false;
+ device.m_last_status_pc = pc;
+ device.m_last_status_value = result;
+ }
+ if (regnum == voodoo_regs::reg_cmdFifoRdPtr)
+ logit = false;
+
+ if (logit)
+ device.logerror("VOODOO.REG:%s read = %08X\n", m_name, result);
}
-private:
- s64 m_s, m_t, m_w;
-};
-#endif
+ return result;
+}
#endif // MAME_VIDEO_VOODOO_H