// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team // SPDX-License-Identifier: GPL-3.0+ #pragma once #include "MemoryTypes.h" #include "common/StringUtil.h" #define COPY_GS_PACKET_TO_MTGS 0 #define PRINT_GIF_PACKET 0 //#define GUNIT_LOG DevCon.WriteLn #define GUNIT_LOG(...) do {} while(0) //#define GUNIT_WARN DevCon.WriteLn #define GUNIT_WARN(...) do {} while(0) enum GIF_PATH { GIF_PATH_1 = 0, GIF_PATH_2, GIF_PATH_3, }; // Lower byte contains path minus 1 enum GIF_TRANSFER_TYPE { GIF_TRANS_INVALID = 0x000, // Invalid GIF_TRANS_XGKICK = 0x100, // Path 1 GIF_TRANS_MTVU = 0x200, // Path 1 GIF_TRANS_DIRECT = 0x301, // Path 2 GIF_TRANS_DIRECTHL = 0x401, // Path 2 GIF_TRANS_DMA = 0x502, // Path 3 GIF_TRANS_FIFO = 0x602 // Path 3 }; static const char Gif_TransferStr[7][32] = { "Invalid Transfer Type", "GIF_TRANS_XGKICK", "GIF_TRANS_MTVU", "GIF_TRANS_DIRECT", "GIF_TRANS_DIRECTHL", "GIF_TRANS_DMA", "GIF_TRANS_FIFO" }; enum GIF_PATH_STATE { GIF_PATH_IDLE = 0, // Path is idle (hasn't started a GS packet) GIF_PATH_PACKED = 1, // Path is on a PACKED gif tag GIF_PATH_REGLIST = 2, // Path is on a REGLIST gif tag GIF_PATH_IMAGE = 3, // Path is on a IMAGE gif tag GIF_PATH_WAIT = 4 // Used only by PATH3 to simulate packet length (Path 3 Masking) }; enum gifstate_t { GIF_STATE_READY = 0, GIF_STATE_EMPTY = 0x10 }; struct gifStruct { int gifstate; bool gspath3done; u32 gscycles; u32 prevcycles; u32 mfifocycles; u32 gifqwc; bool gifmfifoirq; }; alignas(16) extern gifStruct gif; struct GIF_Fifo { unsigned int data[64]; //16 QW FIFO unsigned int fifoSize; int write_fifo(u32* pMem, int size); int read_fifo(); void init(); }; extern GIF_Fifo gif_fifo; union tGIF_CTRL { struct { u32 RST : 1; u32 reserved1 : 2; u32 PSE : 1; u32 reserved2 : 28; }; u32 _u32; tGIF_CTRL(u32 val) { _u32 = val; } void write(u32 val) { _u32 = val; } bool test(u32 flags) { return !!(_u32 & flags); } void set_flags(u32 flags) { _u32 |= flags; } void clear_flags(u32 flags) { _u32 &= ~flags; } void reset() { _u32 = 0; } std::string desc() { return StringUtil::StdStringFromFormat("Ctrl: 0x%x", _u32); } }; union tGIF_MODE { struct { u32 M3R : 1; u32 reserved1 : 1; u32 IMT : 1; u32 reserved2 : 29; }; u32 _u32; tGIF_MODE(u32 val) { _u32 = val; } void write(u32 val) { _u32 = val; } bool test(u32 flags) { return !!(_u32 & flags); } void set_flags(u32 flags) { _u32 |= flags; } void clear_flags(u32 flags) { _u32 &= ~flags; } void reset() { _u32 = 0; } std::string desc() { return StringUtil::StdStringFromFormat("Mode: 0x%x", _u32); } }; union tGIF_STAT { struct { u32 M3R : 1; // GIF_MODE Mask u32 M3P : 1; // VIF PATH3 Mask u32 IMT : 1; // Intermittent Transfer Mode u32 PSE : 1; // Temporary Transfer Stop u32 reserved1 : 1; // ... u32 IP3 : 1; // Interrupted PATH3 u32 P3Q : 1; // PATH3 request Queued u32 P2Q : 1; // PATH2 request Queued u32 P1Q : 1; // PATH1 request Queued u32 OPH : 1; // Output Path (Outputting Data) u32 APATH : 2; // Data Transfer Path (In progress) u32 DIR : 1; // Transfer Direction u32 reserved2 : 11; // ... u32 FQC : 5; // QWC in GIF-FIFO u32 reserved3 : 3; // ... }; u32 _u32; tGIF_STAT(u32 val) { _u32 = val; } void write(u32 val) { _u32 = val; } bool test(u32 flags) { return !!(_u32 & flags); } void set_flags(u32 flags) { _u32 |= flags; } void clear_flags(u32 flags) { _u32 &= ~flags; } void reset() { _u32 = 0; } std::string desc() { return StringUtil::StdStringFromFormat("Stat: 0x%x", _u32); } }; union tGIF_TAG0 { struct { u32 NLOOP : 15; u32 EOP : 1; u32 TAG : 16; }; u32 _u32; tGIF_TAG0(u32 val) { _u32 = val; } bool test(u32 flags) { return !!(_u32 & flags); } void set_flags(u32 flags) { _u32 |= flags; } void clear_flags(u32 flags) { _u32 &= ~flags; } void reset() { _u32 = 0; } std::string desc() { return StringUtil::StdStringFromFormat("Tag0: 0x%x", _u32); } }; union tGIF_TAG1 { struct { u32 TAG : 14; u32 PRE : 1; u32 PRIM : 11; u32 FLG : 2; u32 NREG : 4; }; u32 _u32; tGIF_TAG1(u32 val) { _u32 = val; } bool test(u32 flags) { return !!(_u32 & flags); } void set_flags(u32 flags) { _u32 |= flags; } void clear_flags(u32 flags) { _u32 &= ~flags; } void reset() { _u32 = 0; } std::string desc() { return StringUtil::StdStringFromFormat("Tag1: 0x%x", _u32); } }; union tGIF_CNT { struct { u32 LOOPCNT : 15; u32 reserved1 : 1; u32 REGCNT : 4; u32 VUADDR : 2; u32 reserved2 : 10; }; u32 _u32; tGIF_CNT(u32 val) { _u32 = val; } bool test(u32 flags) { return !!(_u32 & flags); } void set_flags(u32 flags) { _u32 |= flags; } void clear_flags(u32 flags) { _u32 &= ~flags; } void reset() { _u32 = 0; } std::string desc() { return StringUtil::StdStringFromFormat("CNT: 0x%x", _u32); } }; union tGIF_P3CNT { struct { u32 P3CNT : 15; u32 reserved1 : 17; }; u32 _u32; tGIF_P3CNT(u32 val) { _u32 = val; } void reset() { _u32 = 0; } std::string desc() { return StringUtil::StdStringFromFormat("P3CNT: 0x%x", _u32); } }; union tGIF_P3TAG { struct { u32 LOOPCNT : 15; u32 EOP : 1; u32 reserved1 : 16; }; u32 _u32; tGIF_P3TAG(u32 val) { _u32 = val; } bool test(u32 flags) { return !!(_u32 & flags); } void set_flags(u32 flags) { _u32 |= flags; } void clear_flags(u32 flags) { _u32 &= ~flags; } void reset() { _u32 = 0; } std::string desc() { return StringUtil::StdStringFromFormat("P3Tag: 0x%x", _u32); } }; struct GIFregisters { tGIF_CTRL ctrl; u32 padding[3]; tGIF_MODE mode; u32 padding1[3]; tGIF_STAT stat; u32 padding2[7]; tGIF_TAG0 tag0; u32 padding3[3]; tGIF_TAG1 tag1; u32 padding4[3]; u32 tag2; u32 padding5[3]; u32 tag3; u32 padding6[3]; tGIF_CNT cnt; u32 padding7[3]; tGIF_P3CNT p3cnt; u32 padding8[3]; tGIF_P3TAG p3tag; u32 padding9[3]; }; static GIFregisters& gifRegs = (GIFregisters&)eeHw[0x3000]; extern void gifInterrupt(); extern void GIFdma(); extern void dmaGIF(); extern void mfifoGIFtransfer(); extern void gifMFIFOInterrupt(); extern void clearFIFOstuff(bool full); extern void gifCheckPathStatus(bool calledFromGIF);