Next Generation Emulation banner

1 - 3 of 3 Posts

·
Registered
Joined
·
10 Posts
Discussion Starter #1
I was checking out cxbx's source and noticed that your OOVPA structs are redundant, and the definitions themselves had a lot of redundant comments which could be implied via named constants.

I also noticed that the SOVP/LOVP structs are defined in their respective template's class. Doing it this way causes those types to be instantiated with each template instance too. While this doesn't impact runtime performance, it could take a hit on the compiler (since it has to represent the types when compiling) and the .pdb (which can contain type information). There may be some instances where such information is stored in .obj files as well (esp. in LTCG builds, which MS uses proprietary/non-standard OBJ sections for)

Here are some changes I thought of, using IDirect3D8_CreateDevice_1_0_3925 as the example usage:
Code:
enum OOVPAType : uint16 {
	OOVPATypeSmall,
	OOVPATypeLarge,
};

enum : uint08 {
	XRefNotSaved = uint08(-1),
	XRefNotUsed = 0,
};

// ******************************************************************
// * Optimized (Order,Value)-Pair Array
// ******************************************************************
struct OOVPA
{
	OOVPAType Type : 1;
	uint16 Count : 15;

	uint08 XRefSaveIndex;
	uint08 XRefCount;

	// Defined these here to reduce type definition complexity
	// In the production repo, these are defined in the template classes,
	// meaning for each template instance, the type is redefined

	// Small (Offset,Value)-Pair(s)
	struct SOVP
	{
		uint08 Offset;
		uint08 Value;
	};
	// Large (Offset,Value)-Pair(s)
	struct LOVP
	{
		uint16 Offset;
		uint08 Value;
	};
};
#define OOVPA_HEADER(type, count, xref_save_index, xref_count)	\
	{OOVPAType##type, count, xref_save_index, xref_count}
// Define the OOVPA header, labeling the xref members as unused
#define OOVPA_HEADER_SANS_XREF(type, count)	\
	{OOVPAType##type, count, XRefNotSaved, XRefNotUsed}

// ******************************************************************
// * Large Optimized (Offset,Value)-Pair Array
// ******************************************************************
template <uint16 COUNT> struct LOOVPA
{
	OOVPA Header;

	// Large (Offset,Value)-Pair(s)
	OOVPA::LOVP Lovp[COUNT];
};

// ******************************************************************
// * Small Optimized (Offset,Value)-Pair Array
// ******************************************************************
template <uint16 COUNT> struct SOOVPA
{
	OOVPA Header;

	// Small (Offset,Value)-Pair(s)
	OOVPA::SOVP Sovp[COUNT];
};


SOOVPA<8> IDirect3D8_CreateDevice_1_0_3925 =
{
	OOVPA_HEADER_SANS_XREF(Small, 8),
	{
		// IDirect3D8_CreateDevice+0x07 : jnz +0x0A
		{ 0x07, 0x75 }, // (Offset,Value)-Pair #1
		{ 0x08, 0x0A }, // (Offset,Value)-Pair #2

		// IDirect3D8_CreateDevice+0x79 : mov eax, esi
		{ 0x79, 0x8B }, // (Offset,Value)-Pair #3
		{ 0x7A, 0xC6 }, // (Offset,Value)-Pair #4

		// IDirect3D8_CreateDevice+0x7C : retn 0x18
		{ 0x7C, 0xC2 }, // (Offset,Value)-Pair #5
		{ 0x7D, 0x18 }, // (Offset,Value)-Pair #6

		// IDirect3D8_CreateDevice+0x90 : retn 0x18
		{ 0x90, 0xC2 }, // (Offset,Value)-Pair #7
		{ 0x91, 0x18 }, // (Offset,Value)-Pair #8
	}
};
Note that in the OOVPA_HEADER macros, I use ## for gluing the type macro argument together. You could just remove that and require the full enumerator to be used (if intellisense is that big of a deal in these cases). So you would instead have 'OOVPA_HEADER_SANS_XREF(OOVPATypeSmall, 8),' in the example above.

And then you could simplify the OOVPA table definition process by a lot with a simple macro like such
Code:
#if _DEBUG
	#define OOVPA_TABLE_ENTRY(cxbx_def, oovpa_def)	\
		{&oovpa_def.Header, cxbx_def, #cxbx_def}
#else
	#define OOVPA_TABLE_ENTRY(cxbx_def, oovpa_def) \
		{&oovpa_def.Header, cxbx_def}
#endif

// Usage:
OOVPATable D3D8_1_0_3925[] =
{
    // IDirect3D8::CreateDevice
	OOVPA_TABLE_ENTRY(XTL::EmuIDirect3D8_CreateDevice, &IDirect3D8_CreateDevice_1_0_3925),
    // IDirect3DDevice8::IsBusy
	OOVPA_TABLE_ENTRY(XTL::EmuIDirect3DDevice8_IsBusy, &IDirect3DDevice8_IsBusy_1_0_3925),
    // IDirect3DDevice8::GetDeviceCaps
	OOVPA_TABLE_ENTRY(XTL::EmuIDirect3DDevice8_GetDeviceCaps, &IDirect3DDevice8_GetDeviceCaps_1_0_3925),

	// ...
};
Note: If only the last part of the 'oopva_def' is changing, you could potentially simplify the process more by defining a macro that defines '3925' and then you would glue that with 'oopva_def' to resolve the actual definition. Then you would only need to have one .inl for the table which you then include how ever many times you need to redefine the version number macro.

I know some C++ programmers seem to think macros are the devil, but in situations like these where you're repeatedly defining structured data which you really don't ever go back and look at again, they should be viewed as a godsend IMO.
 

·
Premium Member
Joined
·
6,071 Posts
OOVPA wasn't my idea. :)
 
1 - 3 of 3 Posts
Top