pcsx2/pcsx2/Vif.h

252 lines
6.6 KiB
C

/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "MemoryTypes.h"
#include "R5900.h"
enum vif0_stat_flags
{
VIF0_STAT_VPS_W = (1),
VIF0_STAT_VPS_D = (2),
VIF0_STAT_VPS_T = (3),
VIF0_STAT_VPS = (3),
VIF0_STAT_VEW = (1<<2),
VIF0_STAT_MRK = (1<<6),
VIF0_STAT_DBF = (1<<7),
VIF0_STAT_VSS = (1<<8),
VIF0_STAT_VFS = (1<<9),
VIF0_STAT_VIS = (1<<10),
VIF0_STAT_INT = (1<<11),
VIF0_STAT_ER0 = (1<<12),
VIF0_STAT_ER1 = (1<<13),
VIF0_STAT_FQC = (15<<24)
};
enum vif1_stat_flags
{
VIF1_STAT_VPS_W = (1),
VIF1_STAT_VPS_D = (2),
VIF1_STAT_VPS_T = (3),
VIF1_STAT_VPS = (3),
VIF1_STAT_VEW = (1<<2),
VIF1_STAT_VGW = (1<<3),
VIF1_STAT_MRK = (1<<6),
VIF1_STAT_DBF = (1<<7),
VIF1_STAT_VSS = (1<<8),
VIF1_STAT_VFS = (1<<9),
VIF1_STAT_VIS = (1<<10),
VIF1_STAT_INT = (1<<11),
VIF1_STAT_ER0 = (1<<12),
VIF1_STAT_ER1 = (1<<13),
VIF1_STAT_FDR = (1<<23),
VIF1_STAT_FQC = (31<<24)
};
// These are the stat flags that are the same for vif0 & vif1,
// for occassions where we don't neccessarily know which we are using.
enum vif_stat_flags
{
VIF_STAT_VPS_W = (1),
VIF_STAT_VPS_D = (2),
VIF_STAT_VPS_T = (3),
VIF_STAT_VPS = (3),
VIF_STAT_VEW = (1<<2),
VIF_STAT_MRK = (1<<6),
VIF_STAT_DBF = (1<<7),
VIF_STAT_VSS = (1<<8),
VIF_STAT_VFS = (1<<9),
VIF_STAT_VIS = (1<<10),
VIF_STAT_INT = (1<<11),
VIF_STAT_ER0 = (1<<12),
VIF_STAT_ER1 = (1<<13)
};
enum vif_status
{
VPS_IDLE = 0,
VPS_WAITING = 1,
VPS_DECODING = 2,
VPS_TRANSFERRING = 3 // And decompressing.
};
enum vif_stallreasons
{
VIF_TIMING_BREAK = 1,
VIF_IRQ_STALL = 2
};
//
// Bitfield Structure
//
union tVIF_STAT {
struct {
u32 VPS : 2; // Vif(0/1) status; 00 - idle, 01 - waiting for data following vifcode, 10 - decoding vifcode, 11 - decompressing/trasferring data follwing vifcode.
u32 VEW : 1; // E-bit wait (1 - wait, 0 - don't wait)
u32 VGW : 1; // Status waiting for the end of gif transfer (Vif1 only)
u32 _reserved : 2;
u32 MRK : 1; // Mark Detect
u32 DBF : 1; // Double Buffer Flag
u32 VSS : 1; // Stopped by STOP
u32 VFS : 1; // Stopped by ForceBreak
u32 VIS : 1; // Vif Interrupt Stall
u32 INT : 1; // Intereupt by the i bit.
u32 ER0 : 1; // DmaTag Mismatch error.
u32 ER1 : 1; // VifCode error
u32 _reserved2 : 9;
u32 FDR : 1; // VIF/FIFO transfer direction. (false - memory -> Vif, true - Vif -> memory)
u32 FQC : 5; // Amount of data. Up to 8 qwords on Vif0, 16 on Vif1.
};
u32 _u32;
tVIF_STAT() {}
tVIF_STAT(u32 val) { _u32 = val; }
bool test(u32 flags) const { return !!(_u32 & flags); }
void set_flags (u32 flags) { _u32 |= flags; }
void clear_flags(u32 flags) { _u32 &= ~flags; }
void reset() { _u32 = 0; }
wxString desc() const { return wxsFormat(L"Stat: 0x%x", _u32); }
};
#define VIF_STAT(value) ((tVIF_STAT)(value))
union tVIF_FBRST {
struct {
u32 RST : 1; // Resets Vif(0/1) when written.
u32 FBK : 1; // Causes a Forcebreak to Vif((0/1) when true. (Stall)
u32 STP : 1; // Stops after the end of the Vifcode in progress when true. (Stall)
u32 STC : 1; // Cancels the Vif(0/1) stall and clears Vif Stats VSS, VFS, VIS, INT, ER0 & ER1.
u32 _reserved : 28;
};
u32 _u32;
tVIF_FBRST(u32 val) { _u32 = val; }
bool test (u32 flags) const { return !!(_u32 & flags); }
void set_flags (u32 flags) { _u32 |= flags; }
void clear_flags(u32 flags) { _u32 &= ~flags; }
void reset() { _u32 = 0; }
wxString desc() const { return wxsFormat(L"Fbrst: 0x%x", _u32); }
};
#define FBRST(value) ((tVIF_FBRST)(value))
union tVIF_ERR {
struct {
u32 MII : 1; // Masks Stat INT.
u32 ME0 : 1; // Masks Stat Err0.
u32 ME1 : 1; // Masks Stat Err1.
u32 _reserved : 29;
};
u32 _u32;
tVIF_ERR() {}
tVIF_ERR (u32 val) { _u32 = val; }
void write(u32 val) { _u32 = val; }
bool test (u32 flags) const { return !!(_u32 & flags); }
void set_flags (u32 flags) { _u32 |= flags; }
void clear_flags(u32 flags) { _u32 &= ~flags; }
void reset() { _u32 = 0; }
wxString desc() const { return wxsFormat(L"Err: 0x%x", _u32); }
};
struct vifCycle
{
u8 cl, wl;
u8 pad[2];
};
struct VIFregisters {
tVIF_STAT stat;
u32 _pad0[3];
u32 fbrst;
u32 _pad1[3];
tVIF_ERR err;
u32 _pad2[3];
u32 mark;
u32 _pad3[3];
vifCycle cycle; //data write cycle
u32 _pad4[3];
u32 mode;
u32 _pad5[3];
u32 num;
u32 _pad6[3];
u32 mask;
u32 _pad7[3];
u32 code;
u32 _pad8[3];
u32 itops;
u32 _pad9[3];
u32 base; // Not used in VIF0
u32 _pad10[3];
u32 ofst; // Not used in VIF0
u32 _pad11[3];
u32 tops; // Not used in VIF0
u32 _pad12[3];
u32 itop;
u32 _pad13[3];
u32 top; // Not used in VIF0
u32 _pad14[3];
u32 mskpath3;
u32 _pad15[3];
u32 r0; // row0 register
u32 _pad16[3];
u32 r1; // row1 register
u32 _pad17[3];
u32 r2; // row2 register
u32 _pad18[3];
u32 r3; // row3 register
u32 _pad19[3];
u32 c0; // col0 register
u32 _pad20[3];
u32 c1; // col1 register
u32 _pad21[3];
u32 c2; // col2 register
u32 _pad22[3];
u32 c3; // col3 register
u32 _pad23[3];
u32 offset; // internal UNPACK offset
u32 addr;
};
struct VIFregistersMTVU {
vifCycle cycle; //data write cycle
u32 mode;
u32 num;
u32 mask;
u32 itop;
u32 top; // Not used in VIF0
};
static VIFregisters& vif0Regs = (VIFregisters&)eeHw[0x3800];
static VIFregisters& vif1Regs = (VIFregisters&)eeHw[0x3C00];
#define _vifT template <int idx>
#define GetVifX (idx ? (vif1) : (vif0))
#define vifXch (idx ? (vif1ch) : (vif0ch))
#define vifXRegs (idx ? (vif1Regs) : (vif0Regs))
#define MTVU_VifX (idx ? ((THREAD_VU1) ? vu1Thread.vif : vif1) : (vif0))
#define MTVU_VifXRegs (idx ? ((THREAD_VU1) ? vu1Thread.vifRegs : vif1Regs) : (vif0Regs))
#define VifStallEnable(vif) (vif.chcr.STR);
extern void dmaVIF0();
extern void dmaVIF1();
extern void mfifoVIF1transfer();
extern bool VIF0transfer(u32 *data, int size, bool TTE=0);
extern bool VIF1transfer(u32 *data, int size, bool TTE=0);
extern void vifMFIFOInterrupt();