mirror of
https://github.com/dolphin-emu/fifoplayer.git
synced 2026-01-31 01:05:16 +01:00
Import lots of stuff from Dolphin's VideoCommon.
This commit is contained in:
1011
source/BPMemory.h
Normal file
1011
source/BPMemory.h
Normal file
File diff suppressed because it is too large
Load Diff
257
source/CPMemory.h
Normal file
257
source/CPMemory.h
Normal file
@@ -0,0 +1,257 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#ifndef _CPMEMORY_H
|
||||
#define _CPMEMORY_H
|
||||
|
||||
//#include "Common.h"
|
||||
|
||||
// Vertex array numbers
|
||||
enum
|
||||
{
|
||||
ARRAY_POSITION = 0,
|
||||
ARRAY_NORMAL = 1,
|
||||
ARRAY_COLOR = 2,
|
||||
ARRAY_COLOR2 = 3,
|
||||
ARRAY_TEXCOORD0 = 4,
|
||||
};
|
||||
|
||||
// Vertex components
|
||||
enum
|
||||
{
|
||||
NOT_PRESENT = 0,
|
||||
DIRECT = 1,
|
||||
INDEX8 = 2,
|
||||
INDEX16 = 3,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
FORMAT_UBYTE = 0, // 2 Cmp
|
||||
FORMAT_BYTE = 1, // 3 Cmp
|
||||
FORMAT_USHORT = 2,
|
||||
FORMAT_SHORT = 3,
|
||||
FORMAT_FLOAT = 4,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
FORMAT_16B_565 = 0, // NA
|
||||
FORMAT_24B_888 = 1,
|
||||
FORMAT_32B_888x = 2,
|
||||
FORMAT_16B_4444 = 3,
|
||||
FORMAT_24B_6666 = 4,
|
||||
FORMAT_32B_8888 = 5,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
VAT_0_FRACBITS = 0x3e0001f0,
|
||||
VAT_1_FRACBITS = 0x07c3e1f0,
|
||||
VAT_2_FRACBITS = 0xf87c3e1f,
|
||||
};
|
||||
|
||||
#pragma pack(4)
|
||||
union TVtxDesc
|
||||
{
|
||||
u64 Hex;
|
||||
struct
|
||||
{
|
||||
// 0: not present
|
||||
// 1: present
|
||||
u32 PosMatIdx : 1;
|
||||
u32 Tex0MatIdx : 1;
|
||||
u32 Tex1MatIdx : 1;
|
||||
u32 Tex2MatIdx : 1;
|
||||
u32 Tex3MatIdx : 1;
|
||||
u32 Tex4MatIdx : 1;
|
||||
u32 Tex5MatIdx : 1;
|
||||
u32 Tex6MatIdx : 1;
|
||||
u32 Tex7MatIdx : 1;
|
||||
|
||||
// 00: not present
|
||||
// 01: direct
|
||||
// 10: 8 bit index
|
||||
// 11: 16 bit index
|
||||
u32 Position : 2;
|
||||
u32 Normal : 2;
|
||||
u32 Color0 : 2;
|
||||
u32 Color1 : 2;
|
||||
u32 Tex0Coord : 2;
|
||||
u32 Tex1Coord : 2;
|
||||
u32 Tex2Coord : 2;
|
||||
u32 Tex3Coord : 2;
|
||||
u32 Tex4Coord : 2;
|
||||
u32 Tex5Coord : 2;
|
||||
u32 Tex6Coord : 2;
|
||||
u32 Tex7Coord : 2;
|
||||
u32 :31;
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
u32 Hex0, Hex1;
|
||||
};
|
||||
};
|
||||
|
||||
union UVAT_group0
|
||||
{
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
// 0:8
|
||||
u32 PosElements : 1;
|
||||
u32 PosFormat : 3;
|
||||
u32 PosFrac : 5;
|
||||
// 9:12
|
||||
u32 NormalElements : 1;
|
||||
u32 NormalFormat : 3;
|
||||
// 13:16
|
||||
u32 Color0Elements : 1;
|
||||
u32 Color0Comp : 3;
|
||||
// 17:20
|
||||
u32 Color1Elements : 1;
|
||||
u32 Color1Comp : 3;
|
||||
// 21:29
|
||||
u32 Tex0CoordElements : 1;
|
||||
u32 Tex0CoordFormat : 3;
|
||||
u32 Tex0Frac : 5;
|
||||
// 30:31
|
||||
u32 ByteDequant : 1;
|
||||
u32 NormalIndex3 : 1;
|
||||
};
|
||||
};
|
||||
|
||||
union UVAT_group1
|
||||
{
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
// 0:8
|
||||
u32 Tex1CoordElements : 1;
|
||||
u32 Tex1CoordFormat : 3;
|
||||
u32 Tex1Frac : 5;
|
||||
// 9:17
|
||||
u32 Tex2CoordElements : 1;
|
||||
u32 Tex2CoordFormat : 3;
|
||||
u32 Tex2Frac : 5;
|
||||
// 18:26
|
||||
u32 Tex3CoordElements : 1;
|
||||
u32 Tex3CoordFormat : 3;
|
||||
u32 Tex3Frac : 5;
|
||||
// 27:30
|
||||
u32 Tex4CoordElements : 1;
|
||||
u32 Tex4CoordFormat : 3;
|
||||
//
|
||||
u32 : 1;
|
||||
};
|
||||
};
|
||||
|
||||
union UVAT_group2
|
||||
{
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
// 0:4
|
||||
u32 Tex4Frac : 5;
|
||||
// 5:13
|
||||
u32 Tex5CoordElements : 1;
|
||||
u32 Tex5CoordFormat : 3;
|
||||
u32 Tex5Frac : 5;
|
||||
// 14:22
|
||||
u32 Tex6CoordElements : 1;
|
||||
u32 Tex6CoordFormat : 3;
|
||||
u32 Tex6Frac : 5;
|
||||
// 23:31
|
||||
u32 Tex7CoordElements : 1;
|
||||
u32 Tex7CoordFormat : 3;
|
||||
u32 Tex7Frac : 5;
|
||||
};
|
||||
};
|
||||
|
||||
struct ColorAttr
|
||||
{
|
||||
u8 Elements;
|
||||
u8 Comp;
|
||||
};
|
||||
|
||||
struct TexAttr
|
||||
{
|
||||
u8 Elements;
|
||||
u8 Format;
|
||||
u8 Frac;
|
||||
};
|
||||
|
||||
struct TVtxAttr
|
||||
{
|
||||
u8 PosElements;
|
||||
u8 PosFormat;
|
||||
u8 PosFrac;
|
||||
u8 NormalElements;
|
||||
u8 NormalFormat;
|
||||
ColorAttr color[2];
|
||||
TexAttr texCoord[8];
|
||||
u8 ByteDequant;
|
||||
u8 NormalIndex3;
|
||||
};
|
||||
|
||||
// Matrix indices
|
||||
union TMatrixIndexA
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 PosNormalMtxIdx : 6;
|
||||
u32 Tex0MtxIdx : 6;
|
||||
u32 Tex1MtxIdx : 6;
|
||||
u32 Tex2MtxIdx : 6;
|
||||
u32 Tex3MtxIdx : 6;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 Hex : 30;
|
||||
u32 unused : 2;
|
||||
};
|
||||
};
|
||||
|
||||
union TMatrixIndexB
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 Tex4MtxIdx : 6;
|
||||
u32 Tex5MtxIdx : 6;
|
||||
u32 Tex6MtxIdx : 6;
|
||||
u32 Tex7MtxIdx : 6;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 Hex : 24;
|
||||
u32 unused : 8;
|
||||
};
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
extern u32 arraybases[16];
|
||||
extern u8 *cached_arraybases[16];
|
||||
extern u32 arraystrides[16];
|
||||
extern TMatrixIndexA MatrixIndexA;
|
||||
extern TMatrixIndexB MatrixIndexB;
|
||||
|
||||
struct VAT
|
||||
{
|
||||
UVAT_group0 g0;
|
||||
UVAT_group1 g1;
|
||||
UVAT_group2 g2;
|
||||
};
|
||||
|
||||
extern TVtxDesc g_VtxDesc;
|
||||
extern VAT g_VtxAttr[8];
|
||||
|
||||
// Might move this into its own file later.
|
||||
//void LoadCPReg(u32 SubCmd, u32 Value);
|
||||
|
||||
// Fills memory with data from CP regs
|
||||
//void FillCPMemoryArray(u32 *memory);
|
||||
|
||||
#endif // _CPMEMORY_H
|
||||
224
source/FifoAnalyzer.h
Normal file
224
source/FifoAnalyzer.h
Normal file
@@ -0,0 +1,224 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
//#include "FifoAnalyzer.h"
|
||||
|
||||
//#include "Core.h"
|
||||
|
||||
#include "VertexLoader.h"
|
||||
#include "VertexLoader_Position.h"
|
||||
#include "VertexLoader_Normal.h"
|
||||
#include "VertexLoader_TextCoord.h"
|
||||
|
||||
struct CPMemory
|
||||
{
|
||||
TVtxDesc vtxDesc;
|
||||
VAT vtxAttr[8];
|
||||
u32 arrayBases[16];
|
||||
u32 arrayStrides[16];
|
||||
};
|
||||
/*void Init()
|
||||
{
|
||||
VertexLoader_Normal::Init();
|
||||
VertexLoader_Position::Init();
|
||||
VertexLoader_TextCoord::Init();
|
||||
}*/
|
||||
|
||||
u8 ReadFifo8(u8 *&data)
|
||||
{
|
||||
u8 value = data[0];
|
||||
data += 1;
|
||||
return value;
|
||||
}
|
||||
|
||||
u16 ReadFifo16(u8 *&data)
|
||||
{
|
||||
u16 value = be16toh(*(u16*)data);
|
||||
data += 2;
|
||||
return value;
|
||||
}
|
||||
|
||||
u32 ReadFifo32(u8 *&data)
|
||||
{
|
||||
u32 value = be32toh(*(u32*)data);
|
||||
data += 4;
|
||||
return value;
|
||||
}
|
||||
|
||||
/*void InitBPMemory(BPMemory *bpMem)
|
||||
{
|
||||
memset(bpMem, 0, sizeof(BPMemory));
|
||||
bpMem->bpMask = 0x00FFFFFF;
|
||||
}
|
||||
|
||||
BPCmd DecodeBPCmd(u32 value, const BPMemory &bpMem)
|
||||
{
|
||||
//handle the mask register
|
||||
int opcode = value >> 24;
|
||||
int oldval = ((u32*)&bpMem)[opcode];
|
||||
int newval = (oldval & ~bpMem.bpMask) | (value & bpMem.bpMask);
|
||||
int changes = (oldval ^ newval) & 0xFFFFFF;
|
||||
|
||||
BPCmd bp = {opcode, changes, newval};
|
||||
|
||||
return bp;
|
||||
}
|
||||
|
||||
void LoadBPReg(const BPCmd &bp, BPMemory &bpMem)
|
||||
{
|
||||
((u32*)&bpMem)[bp.address] = bp.newvalue;
|
||||
|
||||
//reset the mask register
|
||||
if (bp.address != 0xFE)
|
||||
bpMem.bpMask = 0xFFFFFF;
|
||||
}
|
||||
|
||||
void GetTlutLoadData(u32 &tlutAddr, u32 &memAddr, u32 &tlutXferCount, BPMemory &bpMem)
|
||||
{
|
||||
tlutAddr = (bpMem.tmem_config.tlut_dest & 0x3FF) << 9;
|
||||
tlutXferCount = (bpMem.tmem_config.tlut_dest & 0x1FFC00) >> 5;
|
||||
|
||||
// TODO - figure out a cleaner way.
|
||||
if (Core::g_CoreStartupParameter.bWii)
|
||||
memAddr = bpMem.tmem_config.tlut_src << 5;
|
||||
else
|
||||
memAddr = (bpMem.tmem_config.tlut_src & 0xFFFFF) << 5;
|
||||
}
|
||||
*/
|
||||
void LoadCPReg(u32 subCmd, u32 value, CPMemory &cpMem)
|
||||
{
|
||||
switch (subCmd & 0xF0)
|
||||
{
|
||||
case 0x50:
|
||||
cpMem.vtxDesc.Hex &= ~0x1FFFF; // keep the Upper bits
|
||||
cpMem.vtxDesc.Hex |= value;
|
||||
break;
|
||||
|
||||
case 0x60:
|
||||
cpMem.vtxDesc.Hex &= 0x1FFFF; // keep the lower 17Bits
|
||||
cpMem.vtxDesc.Hex |= (u64)value << 17;
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
// _assert_((subCmd & 0x0F) < 8);
|
||||
cpMem.vtxAttr[subCmd & 7].g0.Hex = value;
|
||||
break;
|
||||
|
||||
case 0x80:
|
||||
// _assert_((subCmd & 0x0F) < 8);
|
||||
cpMem.vtxAttr[subCmd & 7].g1.Hex = value;
|
||||
break;
|
||||
|
||||
case 0x90:
|
||||
// _assert_((subCmd & 0x0F) < 8);
|
||||
cpMem.vtxAttr[subCmd & 7].g2.Hex = value;
|
||||
break;
|
||||
|
||||
case 0xA0:
|
||||
cpMem.arrayBases[subCmd & 0xF] = value;
|
||||
break;
|
||||
|
||||
case 0xB0:
|
||||
cpMem.arrayStrides[subCmd & 0xF] = value & 0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CalculateVertexElementSizes(int sizes[], int vatIndex, const CPMemory &cpMem)
|
||||
{
|
||||
const TVtxDesc &vtxDesc = cpMem.vtxDesc;
|
||||
const VAT &vtxAttr = cpMem.vtxAttr[vatIndex];
|
||||
|
||||
// Colors
|
||||
const u32 colDesc[2] = {vtxDesc.Color0, vtxDesc.Color1};
|
||||
const u32 colComp[2] = {vtxAttr.g0.Color0Comp, vtxAttr.g0.Color1Comp};
|
||||
|
||||
const u32 tcElements[8] =
|
||||
{
|
||||
vtxAttr.g0.Tex0CoordElements, vtxAttr.g1.Tex1CoordElements, vtxAttr.g1.Tex2CoordElements,
|
||||
vtxAttr.g1.Tex3CoordElements, vtxAttr.g1.Tex4CoordElements, vtxAttr.g2.Tex5CoordElements,
|
||||
vtxAttr.g2.Tex6CoordElements, vtxAttr.g2.Tex7CoordElements
|
||||
};
|
||||
|
||||
const u32 tcFormat[8] =
|
||||
{
|
||||
vtxAttr.g0.Tex0CoordFormat, vtxAttr.g1.Tex1CoordFormat, vtxAttr.g1.Tex2CoordFormat,
|
||||
vtxAttr.g1.Tex3CoordFormat, vtxAttr.g1.Tex4CoordFormat, vtxAttr.g2.Tex5CoordFormat,
|
||||
vtxAttr.g2.Tex6CoordFormat, vtxAttr.g2.Tex7CoordFormat
|
||||
};
|
||||
|
||||
// Add position and texture matrix indices
|
||||
u64 vtxDescHex = cpMem.vtxDesc.Hex;
|
||||
for (int i = 0; i < 9; ++i)
|
||||
{
|
||||
sizes[i] = vtxDescHex & 1;
|
||||
vtxDescHex >>= 1;
|
||||
}
|
||||
|
||||
// Position
|
||||
sizes[9] = VertexLoader_Position::GetSize(vtxDesc.Position, vtxAttr.g0.PosFormat, vtxAttr.g0.PosElements);
|
||||
|
||||
// Normals
|
||||
if (vtxDesc.Normal != NOT_PRESENT)
|
||||
{
|
||||
sizes[10] = VertexLoader_Normal::GetSize(vtxDesc.Normal, vtxAttr.g0.NormalFormat, vtxAttr.g0.NormalElements, vtxAttr.g0.NormalIndex3);
|
||||
}
|
||||
else
|
||||
{
|
||||
sizes[10] = 0;
|
||||
}
|
||||
|
||||
// Colors
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
int size = 0;
|
||||
|
||||
switch (colDesc[i])
|
||||
{
|
||||
case NOT_PRESENT:
|
||||
break;
|
||||
case DIRECT:
|
||||
switch (colComp[i])
|
||||
{
|
||||
case FORMAT_16B_565: size = 2; break;
|
||||
case FORMAT_24B_888: size = 3; break;
|
||||
case FORMAT_32B_888x: size = 4; break;
|
||||
case FORMAT_16B_4444: size = 2; break;
|
||||
case FORMAT_24B_6666: size = 3; break;
|
||||
case FORMAT_32B_8888: size = 4; break;
|
||||
default: /*_assert_(0);*/ break;
|
||||
}
|
||||
break;
|
||||
case INDEX8:
|
||||
size = 1;
|
||||
break;
|
||||
case INDEX16:
|
||||
size = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
sizes[11 + i] = size;
|
||||
}
|
||||
|
||||
// Texture coordinates
|
||||
vtxDescHex = vtxDesc.Hex >> 17;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
sizes[13 + i] = VertexLoader_TextCoord::GetSize(vtxDescHex & 3, tcFormat[i], tcElements[i]);
|
||||
vtxDescHex >>= 2;
|
||||
}
|
||||
}
|
||||
|
||||
u32 CalculateVertexSize(int vatIndex, const CPMemory &cpMem)
|
||||
{
|
||||
u32 vertexSize = 0;
|
||||
|
||||
int sizes[21];
|
||||
CalculateVertexElementSizes(sizes, vatIndex, cpMem);
|
||||
|
||||
for (int i = 0; i < 21; ++i)
|
||||
vertexSize += sizes[i];
|
||||
|
||||
return vertexSize;
|
||||
}
|
||||
42
source/OpcodeDecoding.h
Normal file
42
source/OpcodeDecoding.h
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#ifndef _OPCODE_DECODING_H
|
||||
#define _OPCODE_DECODING_H
|
||||
|
||||
#define GX_NOP 0x00
|
||||
|
||||
#define GX_LOAD_BP_REG 0x61
|
||||
#define GX_LOAD_CP_REG 0x08
|
||||
#define GX_LOAD_XF_REG 0x10
|
||||
#define GX_LOAD_INDX_A 0x20
|
||||
#define GX_LOAD_INDX_B 0x28
|
||||
#define GX_LOAD_INDX_C 0x30
|
||||
#define GX_LOAD_INDX_D 0x38
|
||||
|
||||
#define GX_CMD_CALL_DL 0x40
|
||||
#define GX_CMD_UNKNOWN_METRICS 0x44
|
||||
#define GX_CMD_INVL_VC 0x48
|
||||
|
||||
#define GX_PRIMITIVE_MASK 0x78
|
||||
#define GX_PRIMITIVE_SHIFT 3
|
||||
#define GX_VAT_MASK 0x07
|
||||
|
||||
//these are defined 1/8th of their real values and without their top bit
|
||||
#define GX_DRAW_QUADS 0x0 // 0x80
|
||||
#define GX_DRAW_TRIANGLES 0x2 // 0x90
|
||||
#define GX_DRAW_TRIANGLE_STRIP 0x3 // 0x98
|
||||
#define GX_DRAW_TRIANGLE_FAN 0x4 // 0xA0
|
||||
#define GX_DRAW_LINES 0x5 // 0xA8
|
||||
#define GX_DRAW_LINE_STRIP 0x6 // 0xB0
|
||||
#define GX_DRAW_POINTS 0x7 // 0xB8
|
||||
#define GX_DRAW_NONE 0x1; // This is a fake value to used in the backends
|
||||
|
||||
extern bool g_bRecordFifoData;
|
||||
|
||||
void OpcodeDecoder_Init();
|
||||
void OpcodeDecoder_Shutdown();
|
||||
u32 OpcodeDecoder_Run(bool skipped_frame);
|
||||
void ExecuteDisplayList(u32 address, u32 size);
|
||||
#endif // _OPCODE_DECODING_H
|
||||
146
source/VertexLoader.h
Normal file
146
source/VertexLoader.h
Normal file
@@ -0,0 +1,146 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#ifndef _VERTEXLOADER_H
|
||||
#define _VERTEXLOADER_H
|
||||
|
||||
// Top vertex loaders
|
||||
// Metroid Prime: P I16-flt N I16-s16 T0 I16-u16 T1 i16-flt
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
//#include "Common.h"
|
||||
|
||||
#include "CPMemory.h"
|
||||
//#include "DataReader.h"
|
||||
//#include "NativeVertexFormat.h"
|
||||
|
||||
//#include "x64Emitter.h"
|
||||
|
||||
class VertexLoaderUID
|
||||
{
|
||||
u32 vid[5];
|
||||
size_t hash;
|
||||
public:
|
||||
VertexLoaderUID()
|
||||
{
|
||||
}
|
||||
|
||||
void InitFromCurrentState(int vtx_attr_group)
|
||||
{
|
||||
vid[0] = g_VtxDesc.Hex & 0xFFFFFFFF;
|
||||
vid[1] = g_VtxDesc.Hex >> 32;
|
||||
vid[2] = g_VtxAttr[vtx_attr_group].g0.Hex & ~VAT_0_FRACBITS;
|
||||
vid[3] = g_VtxAttr[vtx_attr_group].g1.Hex & ~VAT_1_FRACBITS;
|
||||
vid[4] = g_VtxAttr[vtx_attr_group].g2.Hex & ~VAT_2_FRACBITS;
|
||||
hash = CalculateHash();
|
||||
}
|
||||
|
||||
bool operator < (const VertexLoaderUID &other) const
|
||||
{
|
||||
// This is complex because of speed.
|
||||
if (vid[0] < other.vid[0])
|
||||
return true;
|
||||
else if (vid[0] > other.vid[0])
|
||||
return false;
|
||||
|
||||
for (int i = 1; i < 5; ++i)
|
||||
{
|
||||
if (vid[i] < other.vid[i])
|
||||
return true;
|
||||
else if (vid[i] > other.vid[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator == (const VertexLoaderUID& rh) const
|
||||
{
|
||||
return hash == rh.hash && std::equal(vid, vid + sizeof(vid) / sizeof(vid[0]), rh.vid);
|
||||
}
|
||||
|
||||
size_t GetHash() const
|
||||
{
|
||||
return hash;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
size_t CalculateHash()
|
||||
{
|
||||
size_t h = -1;
|
||||
|
||||
for (unsigned int i = 0; i < sizeof(vid) / sizeof(vid[0]); ++i)
|
||||
{
|
||||
h = h * 137 + vid[i];
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
// ARMTODO: This should be done in a better way
|
||||
#define _M_GENERIC
|
||||
#ifndef _M_GENERIC
|
||||
class VertexLoader : public Gen::XCodeBlock, NonCopyable
|
||||
#else
|
||||
class VertexLoader
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr);
|
||||
~VertexLoader();
|
||||
|
||||
int GetVertexSize() const {return m_VertexSize;}
|
||||
|
||||
int SetupRunVertices(int vtx_attr_group, int primitive, int const count);
|
||||
void RunVertices(int vtx_attr_group, int primitive, int count);
|
||||
void RunCompiledVertices(int vtx_attr_group, int primitive, int count, u8* Data);
|
||||
|
||||
// For debugging / profiling
|
||||
void AppendToString(std::string *dest) const;
|
||||
int GetNumLoadedVerts() const { return m_numLoadedVertices; }
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
NRM_ZERO = 0,
|
||||
NRM_ONE = 1,
|
||||
NRM_THREE = 3,
|
||||
};
|
||||
|
||||
int m_VertexSize; // number of bytes of a raw GC vertex. Computed by CompileVertexTranslator.
|
||||
|
||||
// GC vertex format
|
||||
TVtxAttr m_VtxAttr; // VAT decoded into easy format
|
||||
TVtxDesc m_VtxDesc; // Not really used currently - or well it is, but could be easily avoided.
|
||||
|
||||
// PC vertex format
|
||||
// NativeVertexFormat *m_NativeFmt;
|
||||
// int native_stride;
|
||||
|
||||
// Pipeline. To be JIT compiled in the future.
|
||||
// TPipelineFunction m_PipelineStages[64]; // TODO - figure out real max. it's lower.
|
||||
// int m_numPipelineStages;
|
||||
|
||||
const u8 *m_compiledCode;
|
||||
|
||||
int m_numLoadedVertices;
|
||||
|
||||
void SetVAT(u32 _group0, u32 _group1, u32 _group2);
|
||||
|
||||
void CompileVertexTranslator();
|
||||
void ConvertVertices(int count);
|
||||
|
||||
// void WriteCall(TPipelineFunction);
|
||||
|
||||
#ifndef _M_GENERIC
|
||||
void WriteGetVariable(int bits, Gen::OpArg dest, void *address);
|
||||
void WriteSetVariable(int bits, void *address, Gen::OpArg dest);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
112
source/VertexLoader_Normal.h
Normal file
112
source/VertexLoader_Normal.h
Normal file
@@ -0,0 +1,112 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#ifndef _VERTEXLOADER_NORMAL_H
|
||||
#define _VERTEXLOADER_NORMAL_H
|
||||
|
||||
//#include "Common.h"
|
||||
//#include "CommonTypes.h"
|
||||
|
||||
class VertexLoader_Normal
|
||||
{
|
||||
public:
|
||||
|
||||
// Init
|
||||
static void Init(void);
|
||||
|
||||
// GetFunction
|
||||
// static TPipelineFunction GetFunction(unsigned int _type,
|
||||
// unsigned int _format, unsigned int _elements, unsigned int _index3);
|
||||
|
||||
private:
|
||||
enum ENormalType
|
||||
{
|
||||
NRM_NOT_PRESENT = 0,
|
||||
NRM_DIRECT = 1,
|
||||
NRM_INDEX8 = 2,
|
||||
NRM_INDEX16 = 3,
|
||||
NUM_NRM_TYPE
|
||||
};
|
||||
|
||||
enum ENormalFormat
|
||||
{
|
||||
FORMAT_UBYTE = 0,
|
||||
FORMAT_BYTE = 1,
|
||||
FORMAT_USHORT = 2,
|
||||
FORMAT_SHORT = 3,
|
||||
FORMAT_FLOAT = 4,
|
||||
NUM_NRM_FORMAT
|
||||
};
|
||||
|
||||
static int FormatBaseSize(int format)
|
||||
{
|
||||
if (format == FORMAT_UBYTE) return 1;
|
||||
else if (format == FORMAT_BYTE) return 1;
|
||||
else if (format == FORMAT_USHORT) return 2;
|
||||
else if (format == FORMAT_SHORT) return 2;
|
||||
else if (format == FORMAT_FLOAT) return sizeof(float);
|
||||
else return 0;
|
||||
}
|
||||
|
||||
enum ENormalElements
|
||||
{
|
||||
NRM_NBT = 0,
|
||||
NRM_NBT3 = 1,
|
||||
NUM_NRM_ELEMENTS
|
||||
};
|
||||
|
||||
enum ENormalIndices
|
||||
{
|
||||
NRM_INDICES1 = 0,
|
||||
NRM_INDICES3 = 1,
|
||||
NUM_NRM_INDICES
|
||||
};
|
||||
|
||||
/* struct Set
|
||||
{
|
||||
template <typename T>
|
||||
void operator=(const T&)
|
||||
{
|
||||
gc_size = T::size;
|
||||
function = T::function;
|
||||
}
|
||||
|
||||
int gc_size;
|
||||
// TPipelineFunction function;
|
||||
};*/
|
||||
|
||||
// static Set m_Table[NUM_NRM_TYPE][NUM_NRM_INDICES][NUM_NRM_ELEMENTS][NUM_NRM_FORMAT];
|
||||
|
||||
public:
|
||||
// GetSize
|
||||
static unsigned int GetSize(unsigned int _type, unsigned int _format,
|
||||
unsigned int _elements, unsigned int _index3)
|
||||
{
|
||||
if (_type == NRM_DIRECT)
|
||||
{
|
||||
int base_size = FormatBaseSize(_format);
|
||||
int num = (_elements == NRM_NBT) ? 1 : 3;
|
||||
|
||||
return base_size * num * 3;
|
||||
}
|
||||
else if (_type == NRM_INDEX8 || _type == NRM_INDEX16)
|
||||
{
|
||||
int base_size = (_type == NRM_INDEX8) ? 1 : 2;
|
||||
if (_index3 == NRM_INDICES1)
|
||||
return base_size;
|
||||
else
|
||||
{
|
||||
if ( _elements == NRM_NBT)
|
||||
return base_size;
|
||||
else
|
||||
return 3 * base_size;
|
||||
}
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
39
source/VertexLoader_Position.h
Normal file
39
source/VertexLoader_Position.h
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#ifndef VERTEXLOADER_POSITION_H
|
||||
#define VERTEXLOADER_POSITION_H
|
||||
|
||||
class VertexLoader_Position {
|
||||
public:
|
||||
|
||||
// Init
|
||||
static void Init(void);
|
||||
|
||||
// GetSize
|
||||
static unsigned int GetSize(unsigned int _type, unsigned int _format, unsigned int _elements)
|
||||
{
|
||||
const int tableReadPositionVertexSize[4][8][2] =
|
||||
{
|
||||
{
|
||||
{0, 0,}, {0, 0,}, {0, 0,}, {0, 0,}, {0, 0,},
|
||||
},
|
||||
{
|
||||
{2, 3,}, {2, 3,}, {4, 6,}, {4, 6,}, {8, 12,},
|
||||
},
|
||||
{
|
||||
{1, 1,}, {1, 1,}, {1, 1,}, {1, 1,}, {1, 1,},
|
||||
},
|
||||
{
|
||||
{2, 2,}, {2, 2,}, {2, 2,}, {2, 2,}, {2, 2,},
|
||||
},
|
||||
};
|
||||
return tableReadPositionVertexSize[_type][_format][_elements];
|
||||
}
|
||||
|
||||
// GetFunction
|
||||
// static TPipelineFunction GetFunction(unsigned int _type, unsigned int _format, unsigned int _elements);
|
||||
};
|
||||
|
||||
#endif
|
||||
46
source/VertexLoader_TextCoord.h
Normal file
46
source/VertexLoader_TextCoord.h
Normal file
@@ -0,0 +1,46 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#ifndef VERTEXLOADER_TEXCOORD_H
|
||||
#define VERTEXLOADER_TEXCOORD_H
|
||||
|
||||
//#include "NativeVertexFormat.h"
|
||||
|
||||
class VertexLoader_TextCoord
|
||||
{
|
||||
public:
|
||||
|
||||
// Init
|
||||
static void Init(void);
|
||||
|
||||
// GetSize
|
||||
static unsigned int GetSize(unsigned int _type, unsigned int _format, unsigned int _elements)
|
||||
{
|
||||
const int tableReadTexCoordVertexSize[4][8][2] =
|
||||
{
|
||||
{
|
||||
{0, 0,}, {0, 0,}, {0, 0,}, {0, 0,}, {0, 0,},
|
||||
},
|
||||
{
|
||||
{1, 2,}, {1, 2,}, {2, 4,}, {2, 4,}, {4, 8,},
|
||||
},
|
||||
{
|
||||
{1, 1,}, {1, 1,}, {1, 1,}, {1, 1,}, {1, 1,},
|
||||
},
|
||||
{
|
||||
{2, 2,}, {2, 2,}, {2, 2,}, {2, 2,}, {2, 2,},
|
||||
},
|
||||
};
|
||||
return tableReadTexCoordVertexSize[_type][_format][_elements];
|
||||
}
|
||||
|
||||
// GetFunction
|
||||
// static TPipelineFunction GetFunction(unsigned int _type, unsigned int _format, unsigned int _elements);
|
||||
|
||||
// GetDummyFunction
|
||||
// It is important to synchronize tcIndex.
|
||||
// static TPipelineFunction GetDummyFunction();
|
||||
};
|
||||
|
||||
#endif
|
||||
199
source/main.cpp
199
source/main.cpp
@@ -93,6 +93,20 @@ uint16_t le16toh(uint16_t val)
|
||||
return ((val&0xff)<<8)|((val&0xff00)>>8);
|
||||
}
|
||||
|
||||
uint64_t be64toh(uint64_t val)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
uint32_t be32toh(uint32_t val)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
uint16_t be16toh(uint16_t val)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
#elif BYTE_ORDER==LITTLE_ENDIAN
|
||||
#error other stuff
|
||||
@@ -252,25 +266,26 @@ struct FifoData
|
||||
wgPipe->U32 = (i<<24)|(le32toh(bpmem[i])&0xffffff);
|
||||
}
|
||||
|
||||
#define LoadCPReg(addr, val) { wgPipe->U8 = 0x08; wgPipe->U8 = addr; wgPipe->U32 = val; }
|
||||
#define MLoadCPReg(addr, val) { wgPipe->U8 = 0x08; wgPipe->U8 = addr; wgPipe->U32 = val; }
|
||||
|
||||
LoadCPReg(0x30, le32toh(cpmem[0x30]));
|
||||
LoadCPReg(0x40, le32toh(cpmem[0x40]));
|
||||
LoadCPReg(0x50, le32toh(cpmem[0x50]));
|
||||
LoadCPReg(0x60, le32toh(cpmem[0x60]));
|
||||
MLoadCPReg(0x30, le32toh(cpmem[0x30]));
|
||||
MLoadCPReg(0x40, le32toh(cpmem[0x40]));
|
||||
MLoadCPReg(0x50, le32toh(cpmem[0x50]));
|
||||
MLoadCPReg(0x60, le32toh(cpmem[0x60]));
|
||||
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
LoadCPReg(0x70 + i, le32toh(cpmem[0x70 + i]));
|
||||
LoadCPReg(0x80 + i, le32toh(cpmem[0x80 + i]));
|
||||
LoadCPReg(0x90 + i, le32toh(cpmem[0x90 + i]));
|
||||
MLoadCPReg(0x70 + i, le32toh(cpmem[0x70 + i]));
|
||||
MLoadCPReg(0x80 + i, le32toh(cpmem[0x80 + i]));
|
||||
MLoadCPReg(0x90 + i, le32toh(cpmem[0x90 + i]));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
LoadCPReg(0xa0 + i, le32toh(cpmem[0xa0 + i]));
|
||||
LoadCPReg(0xb0 + i, le32toh(cpmem[0xb0 + i]));
|
||||
MLoadCPReg(0xa0 + i, le32toh(cpmem[0xa0 + i]));
|
||||
MLoadCPReg(0xb0 + i, le32toh(cpmem[0xb0 + i]));
|
||||
}
|
||||
#undef MLoadCPReg
|
||||
|
||||
for (unsigned int i = 0; i < xfmem.size(); i += 16)
|
||||
{
|
||||
@@ -345,6 +360,160 @@ void LoadDffData(FifoData& out)
|
||||
out.xfregs.insert(out.xfregs.begin(), xf_regs_ptr, xf_regs_ptr + xf_regs_size);
|
||||
}
|
||||
|
||||
struct AnalyzedFrameInfo
|
||||
{
|
||||
std::vector<u32> object_starts;
|
||||
std::vector<u32> object_ends;
|
||||
// std::vector<MemoryUpdate> memory_updates;
|
||||
};
|
||||
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "BPMemory.h"
|
||||
#include "FifoAnalyzer.h"
|
||||
|
||||
class FifoDataAnalyzer
|
||||
{
|
||||
public:
|
||||
void AnalyzeFrames(FifoData& data, std::vector<AnalyzedFrameInfo>& frame_info)
|
||||
{
|
||||
// TODO: Load BP mem
|
||||
|
||||
u32 *cpMem = &data.cpmem[0];
|
||||
LoadCPReg(0x50, cpMem[0x50], m_cpmem);
|
||||
LoadCPReg(0x60, cpMem[0x60], m_cpmem);
|
||||
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
LoadCPReg(0x70 + i, cpMem[0x70 + i], m_cpmem);
|
||||
LoadCPReg(0x80 + i, cpMem[0x80 + i], m_cpmem);
|
||||
LoadCPReg(0x90 + i, cpMem[0x90 + i], m_cpmem);
|
||||
}
|
||||
|
||||
frame_info.clear();
|
||||
frame_info.resize(data.frames.size());
|
||||
|
||||
m_drawingObject = false;
|
||||
|
||||
for (unsigned int frame_idx = 0; frame_idx < data.frames.size(); ++frame_idx)
|
||||
{
|
||||
FifoFrameData& src_frame = data.frames[frame_idx];
|
||||
AnalyzedFrameInfo& dst_frame = frame_info[frame_idx];
|
||||
|
||||
u32 cmd_start = 0;
|
||||
|
||||
while (cmd_start < src_frame.fifoData.size())
|
||||
{
|
||||
bool was_drawing = m_drawingObject;
|
||||
u32 cmd_size = DecodeCommand(&src_frame.fifoData[cmd_start]);
|
||||
|
||||
// TODO: Check that cmd_size != 0
|
||||
|
||||
if (was_drawing != m_drawingObject)
|
||||
{
|
||||
if (m_drawingObject)
|
||||
dst_frame.object_starts.push_back(cmd_start);
|
||||
else
|
||||
dst_frame.object_ends.push_back(cmd_start);
|
||||
}
|
||||
cmd_start += cmd_size;
|
||||
}
|
||||
if (dst_frame.object_ends.size() < dst_frame.object_starts.size())
|
||||
dst_frame.object_ends.push_back(cmd_start);
|
||||
}
|
||||
}
|
||||
|
||||
u32 DecodeCommand(u8* data)
|
||||
{
|
||||
u8* data_start = data;
|
||||
|
||||
u8 cmd = ReadFifo8(data);
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case GX_NOP:
|
||||
case 0x44:
|
||||
case GX_CMD_INVL_VC:
|
||||
break;
|
||||
|
||||
case GX_LOAD_CP_REG:
|
||||
{
|
||||
m_drawingObject = false;
|
||||
|
||||
u32 cmd2 = ReadFifo8(data);
|
||||
u32 value = ReadFifo32(data);
|
||||
LoadCPReg(cmd2, value, m_cpmem);
|
||||
break;
|
||||
}
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
m_drawingObject = false;
|
||||
|
||||
u32 cmd2 = ReadFifo32(data);
|
||||
u8 stream_size = ((cmd2 >> 16) & 0xf) + 1; // TODO: Check if this works!
|
||||
|
||||
data += stream_size * 4;
|
||||
break;
|
||||
}
|
||||
|
||||
case GX_LOAD_INDX_A:
|
||||
case GX_LOAD_INDX_B:
|
||||
case GX_LOAD_INDX_C:
|
||||
case GX_LOAD_INDX_D:
|
||||
m_drawingObject = false;
|
||||
data += 4;
|
||||
break;
|
||||
|
||||
case GX_CMD_CALL_DL:
|
||||
// The recorder should have expanded display lists into the fifo stream and skipped the call to start them
|
||||
// That is done to make it easier to track where memory is updated
|
||||
//_assert_(false);
|
||||
printf("Shouldn't have a DL here...\n");
|
||||
data += 8;
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG:
|
||||
{
|
||||
m_drawingObject = false;
|
||||
|
||||
u32 cmd2 = ReadFifo32(data);
|
||||
//BPCmd bp = FifoAnalyzer::DecodeBPCmd(cmd2, m_BpMem); // TODO
|
||||
|
||||
//FifoAnalyzer::LoadBPReg(bp, m_BpMem);
|
||||
// TODO: Load BP reg..
|
||||
|
||||
// TODO
|
||||
// if (bp.address == BPMEM_TRIGGER_EFB_COPY)
|
||||
// StoreEfbCopyRegion();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
if (cmd & 0x80)
|
||||
{
|
||||
m_drawingObject = true;
|
||||
u32 vtxAttrGroup = cmd & GX_VAT_MASK;
|
||||
int vertex_size = CalculateVertexSize(vtxAttrGroup, m_cpmem);
|
||||
|
||||
u16 stream_size = ReadFifo16(data);
|
||||
data += stream_size * vertex_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Invalid fifo command 0x%x\n", cmd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return data - data_start;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_drawingObject;
|
||||
|
||||
CPMemory m_cpmem;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#define DEFAULT_FIFO_SIZE (256*1024)
|
||||
@@ -398,6 +567,10 @@ int main()
|
||||
FifoData fifo_data;
|
||||
LoadDffData(fifo_data);
|
||||
|
||||
FifoDataAnalyzer analyzer;
|
||||
std::vector<AnalyzedFrameInfo> analyzed_frames;
|
||||
analyzer.AnalyzeFrames(fifo_data, analyzed_frames);
|
||||
|
||||
for (unsigned int i = 0; i < fifo_data.frames[0].fifoData.size(); ++i)
|
||||
{
|
||||
printf("%02x", fifo_data.frames[0].fifoData[i]);
|
||||
@@ -417,10 +590,6 @@ int main()
|
||||
fifo_data.ApplyInitialState();
|
||||
|
||||
for (unsigned int i = 0; i < fifo_data.frames[cur_frame].fifoData.size(); ++i)
|
||||
wgPipe->U8 = fifo_data.frames[cur_frame].fifoData[i];
|
||||
#endif
|
||||
|
||||
// for (element = frame_elements[cur_frame])
|
||||
{
|
||||
// switch (element.type)
|
||||
{
|
||||
@@ -447,10 +616,10 @@ int main()
|
||||
// memcpy (GetPointer(element.start_addr), element.data, element.size);
|
||||
// break;
|
||||
}
|
||||
wgPipe->U8 = fifo_data.frames[cur_frame].fifoData[i];
|
||||
}
|
||||
|
||||
// finish frame...
|
||||
#if ENABLE_CONSOLE!=1
|
||||
GX_CopyDisp(frameBuffer[fb],GX_TRUE);
|
||||
|
||||
VIDEO_SetNextFramebuffer(frameBuffer[fb]);
|
||||
|
||||
Reference in New Issue
Block a user