Initial megacommit.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,666 @@
|
||||
#include "D3DBase.h"
|
||||
|
||||
#include "Globals.h"
|
||||
#include "Common.h"
|
||||
#include "BPStructs.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "TextureCache.h"
|
||||
#include "TextureDecoder.h"
|
||||
#include "VertexHandler.h"
|
||||
#include "PixelShader.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#include "main.h" //for the plugin interface
|
||||
|
||||
//BP state
|
||||
BPMemory bpmem;
|
||||
|
||||
bool textureChanged[8];
|
||||
|
||||
#define BPMEM_GENMODE 0x00
|
||||
#define BPMEM_ZMODE 0x40
|
||||
#define BPMEM_BLENDMODE 0x41
|
||||
#define BPMEM_CONSTANTALPHA 0x42
|
||||
#define BPMEM_ALPHACOMPARE 0xF3
|
||||
#define BPMEM_LINEPTWIDTH 0x22
|
||||
#define BPMEM_TEXINVALIDATE 0x66
|
||||
#define BPMEM_SCISSORTL 0x20
|
||||
#define BPMEM_SCISSORBR 0x21
|
||||
#define BPMEM_SCISSOROFFSET 0x59
|
||||
#define BPMEM_CLEARBBOX1 0x55 // let's hope not many games use bboxes..
|
||||
#define BPMEM_CLEARBBOX2 0x56 // TODO(ector): add something that watches bboxes
|
||||
#define BPMEM_TEXMODE0_1 0x80
|
||||
#define BPMEM_TEXMODE0_2 0xA0
|
||||
#define BPMEM_FOGPARAM0 0xEE
|
||||
#define BPMEM_FOGBMAGNITUDE 0xEF
|
||||
#define BPMEM_FOGBEXPONENT 0xF0
|
||||
#define BPMEM_FOGPARAM3 0xF1
|
||||
#define BPMEM_FOGCOLOR 0xF2
|
||||
#define BPMEM_ZTEX1 0xF4
|
||||
#define BPMEM_ZTEX2 0xF5
|
||||
#define BPMEM_DRAWDONE 0x45
|
||||
|
||||
#define BPMEM_PE_TOKEN_ID 0x47
|
||||
#define BPMEM_PE_TOKEN_INT_ID 0x48
|
||||
|
||||
// State translation lookup tables
|
||||
const D3DBLEND d3dSrcFactors[8] =
|
||||
{
|
||||
D3DBLEND_ZERO,
|
||||
D3DBLEND_ONE,
|
||||
D3DBLEND_DESTCOLOR,
|
||||
D3DBLEND_INVDESTCOLOR,
|
||||
D3DBLEND_SRCALPHA,
|
||||
D3DBLEND_INVSRCALPHA,
|
||||
D3DBLEND_DESTALPHA,
|
||||
D3DBLEND_INVDESTALPHA
|
||||
};
|
||||
|
||||
const D3DBLEND d3dDestFactors[8] =
|
||||
{
|
||||
D3DBLEND_ZERO,
|
||||
D3DBLEND_ONE,
|
||||
D3DBLEND_SRCCOLOR,
|
||||
D3DBLEND_INVSRCCOLOR,
|
||||
D3DBLEND_SRCALPHA,
|
||||
D3DBLEND_INVSRCALPHA,
|
||||
D3DBLEND_DESTALPHA,
|
||||
D3DBLEND_INVDESTALPHA
|
||||
};
|
||||
|
||||
const D3DCULL d3dCullModes[4] =
|
||||
{
|
||||
D3DCULL_NONE,
|
||||
D3DCULL_CCW,
|
||||
D3DCULL_CW,
|
||||
D3DCULL_CCW
|
||||
};
|
||||
|
||||
const D3DCMPFUNC d3dCmpFuncs[8] =
|
||||
{
|
||||
D3DCMP_NEVER,
|
||||
D3DCMP_LESS,
|
||||
D3DCMP_EQUAL,
|
||||
D3DCMP_LESSEQUAL,
|
||||
D3DCMP_GREATER,
|
||||
D3DCMP_NOTEQUAL,
|
||||
D3DCMP_GREATEREQUAL,
|
||||
D3DCMP_ALWAYS
|
||||
};
|
||||
|
||||
const D3DTEXTUREFILTERTYPE d3dMipFilters[4] =
|
||||
{
|
||||
D3DTEXF_NONE,
|
||||
D3DTEXF_POINT,
|
||||
D3DTEXF_ANISOTROPIC,
|
||||
D3DTEXF_LINEAR, //reserved
|
||||
};
|
||||
|
||||
const D3DTEXTUREADDRESS d3dClamps[4] =
|
||||
{
|
||||
D3DTADDRESS_CLAMP,
|
||||
D3DTADDRESS_WRAP,
|
||||
D3DTADDRESS_MIRROR,
|
||||
D3DTADDRESS_WRAP //reserved
|
||||
};
|
||||
|
||||
|
||||
void BPInit()
|
||||
{
|
||||
memset(&bpmem, 0, sizeof(bpmem));
|
||||
bpmem.bpMask = 0xFFFFFF;
|
||||
}
|
||||
|
||||
using namespace D3D;
|
||||
// __________________________________________________________________________________________________
|
||||
// BPWritten
|
||||
//
|
||||
void BPWritten(int addr, int changes, int newval)
|
||||
{
|
||||
switch(addr)
|
||||
{
|
||||
case BPMEM_GENMODE:
|
||||
if (changes)
|
||||
{
|
||||
CVertexHandler::Flush();
|
||||
((u32*)&bpmem)[addr] = newval;
|
||||
dev->SetRenderState(D3DRS_CULLMODE, d3dCullModes[bpmem.genMode.cullmode]);
|
||||
if (bpmem.genMode.cullmode == 3)
|
||||
dev->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
|
||||
else
|
||||
{
|
||||
DWORD write = 0;
|
||||
if (bpmem.blendmode.alphaupdate)
|
||||
write = D3DCOLORWRITEENABLE_ALPHA;
|
||||
if (bpmem.blendmode.colorupdate)
|
||||
write |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE;
|
||||
dev->SetRenderState(D3DRS_COLORWRITEENABLE, write);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case BPMEM_ZMODE:
|
||||
if (changes)
|
||||
{
|
||||
CVertexHandler::Flush();
|
||||
((u32*)&bpmem)[addr] = newval;
|
||||
if (bpmem.zmode.testenable)
|
||||
{
|
||||
dev->SetRenderState(D3DRS_ZENABLE, TRUE);
|
||||
dev->SetRenderState(D3DRS_ZWRITEENABLE, bpmem.zmode.updateenable);
|
||||
dev->SetRenderState(D3DRS_ZFUNC,d3dCmpFuncs[bpmem.zmode.func]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if the test is disabled write is disabled too
|
||||
dev->SetRenderState(D3DRS_ZENABLE, FALSE);
|
||||
dev->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case BPMEM_ALPHACOMPARE:
|
||||
if (changes)
|
||||
{
|
||||
CVertexHandler::Flush();
|
||||
((u32*)&bpmem)[addr] = newval;
|
||||
float f[4] =
|
||||
{
|
||||
bpmem.alphaFunc.ref0/255.0f,
|
||||
bpmem.alphaFunc.ref1/255.0f,
|
||||
0,0
|
||||
};
|
||||
dev->SetPixelShaderConstantF(PS_CONST_ALPHAREF,f,1);
|
||||
|
||||
if (D3D::GetShaderVersion() == PSNONE)
|
||||
{
|
||||
dev->SetRenderState(D3DRS_ALPHATESTENABLE, (Compare)bpmem.alphaFunc.comp0 != COMPARE_ALWAYS);
|
||||
dev->SetRenderState(D3DRS_ALPHAREF, bpmem.alphaFunc.ref0*4);
|
||||
dev->SetRenderState(D3DRS_ALPHAFUNC, d3dCmpFuncs[bpmem.alphaFunc.comp0]);
|
||||
}
|
||||
// Normally, use texkill in pixel shader to emulate alpha test
|
||||
}
|
||||
break;
|
||||
|
||||
case BPMEM_CONSTANTALPHA:
|
||||
if (changes)
|
||||
{
|
||||
CVertexHandler::Flush();
|
||||
((u32*)&bpmem)[addr] = newval;
|
||||
float f[4] = {
|
||||
bpmem.dstalpha.alpha/255.0f,0,0,0
|
||||
};
|
||||
dev->SetPixelShaderConstantF(PS_CONST_CONSTALPHA,f,1);
|
||||
}
|
||||
break;
|
||||
|
||||
case BPMEM_LINEPTWIDTH:
|
||||
// glPointSize(1); //bpmem.lineptwidth.pointsize);
|
||||
// glLineWidth(1); //bpmem.lineptwidth.linesize);
|
||||
break;
|
||||
|
||||
case BPMEM_BLENDMODE:
|
||||
if (changes & 0xFFFF)
|
||||
{
|
||||
CVertexHandler::Flush();
|
||||
((u32*)&bpmem)[addr] = newval;
|
||||
if (changes & 1) dev->SetRenderState(D3DRS_ALPHABLENDENABLE,bpmem.blendmode.blendenable);
|
||||
if (changes & 4) dev->SetRenderState(D3DRS_DITHERENABLE,bpmem.blendmode.dither);
|
||||
D3DBLEND src = d3dSrcFactors[bpmem.blendmode.srcfactor];
|
||||
D3DBLEND dst = d3dDestFactors[bpmem.blendmode.dstfactor];
|
||||
if (changes & 0x700) dev->SetRenderState(D3DRS_SRCBLEND, src);
|
||||
if (changes & 0xE0) dev->SetRenderState(D3DRS_DESTBLEND, dst);
|
||||
if (changes & 0x800)
|
||||
dev->SetRenderState(D3DRS_BLENDOP,bpmem.blendmode.subtract?D3DBLENDOP_SUBTRACT:D3DBLENDOP_ADD);
|
||||
|
||||
//if (bpmem.blendmode.logicopenable) // && bpmem.blendmode.logicmode == 4)
|
||||
// MessageBox(0,"LOGIC",0,0);
|
||||
|
||||
if (changes & 0x18)
|
||||
{
|
||||
DWORD write = 0;
|
||||
if (bpmem.blendmode.alphaupdate)
|
||||
write = D3DCOLORWRITEENABLE_ALPHA;
|
||||
if (bpmem.blendmode.colorupdate)
|
||||
write |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE;
|
||||
dev->SetRenderState(D3DRS_COLORWRITEENABLE,write);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case BPMEM_FOGPARAM0:
|
||||
{
|
||||
u32 fogATemp = bpmem.fog.a<<12;
|
||||
float fogA = *(float*)(&fogATemp);
|
||||
}
|
||||
break;
|
||||
|
||||
case BPMEM_FOGBEXPONENT:
|
||||
{
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case BPMEM_FOGBMAGNITUDE:
|
||||
{
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case BPMEM_FOGPARAM3:
|
||||
//fog settings
|
||||
{
|
||||
u32 fogCTemp = bpmem.fog.c_proj_fsel.cShifted12 << 12;
|
||||
float fogC = *(float*)(&fogCTemp);
|
||||
}
|
||||
break;
|
||||
|
||||
case BPMEM_FOGCOLOR:
|
||||
if (changes)
|
||||
{
|
||||
CVertexHandler::Flush();
|
||||
((u32*)&bpmem)[addr] = newval;
|
||||
dev->SetRenderState(D3DRS_FOGCOLOR,bpmem.fog.color);
|
||||
}
|
||||
break;
|
||||
|
||||
case BPMEM_TEXINVALIDATE:
|
||||
//TexCache_Invalidate();
|
||||
break;
|
||||
|
||||
case BPMEM_SCISSOROFFSET: //TODO: investigate
|
||||
{
|
||||
CVertexHandler::Flush();
|
||||
((u32*)&bpmem)[addr] = newval;
|
||||
int x=bpmem.scissorOffset.x*2-342;
|
||||
int y=bpmem.scissorOffset.y*2-342;
|
||||
char temp[256];
|
||||
sprintf(temp,"ScissorOffset: %i %i",x,y);
|
||||
g_VideoInitialize.pLog(temp, FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
case BPMEM_SCISSORTL:
|
||||
case BPMEM_SCISSORBR:
|
||||
{
|
||||
CVertexHandler::Flush();
|
||||
((u32*)&bpmem)[addr] = newval;
|
||||
int xoff = bpmem.scissorOffset.x*2-342;
|
||||
int yoff = bpmem.scissorOffset.y*2-342;
|
||||
RECT rc;
|
||||
rc.left=bpmem.scissorTL.x + xoff - 342 -1;
|
||||
if (rc.left<0) rc.left=0;
|
||||
rc.top=bpmem.scissorTL.y + yoff - 342 -1;
|
||||
if (rc.top<0) rc.top=0;
|
||||
rc.right=bpmem.scissorBR.x + xoff - 342 +2;
|
||||
if (rc.right>640) rc.right=640;
|
||||
rc.bottom=bpmem.scissorBR.y + yoff - 342 +2;
|
||||
if (rc.bottom>480) rc.bottom=480;
|
||||
char temp[256];
|
||||
sprintf(temp,"ScissorRect: %i %i %i %i",rc.left,rc.top,rc.right,rc.bottom);
|
||||
g_VideoInitialize.pLog(temp, FALSE);
|
||||
dev->SetRenderState(D3DRS_SCISSORTESTENABLE,TRUE);
|
||||
Renderer::SetScissorBox(rc);
|
||||
}
|
||||
break;
|
||||
case BPMEM_ZTEX1:
|
||||
break;
|
||||
case BPMEM_ZTEX2:
|
||||
break;
|
||||
default:
|
||||
switch(addr & 0xF8) //texture sampler filter
|
||||
{
|
||||
case 0x80: // TEX MODE 0
|
||||
case 0xA0:
|
||||
if (changes)
|
||||
{
|
||||
CVertexHandler::Flush();
|
||||
((u32*)&bpmem)[addr] = newval;
|
||||
FourTexUnits &tex = bpmem.tex[(addr&0xE0)==0xA0];
|
||||
int stage = (addr&3);//(addr>>4)&2;
|
||||
TexMode0 &tm0 = tex.texMode0[stage];
|
||||
|
||||
D3DTEXTUREFILTERTYPE min, mag, mip;
|
||||
if (g_Config.bForceFiltering)
|
||||
{
|
||||
min = mag = mip = D3DTEXF_LINEAR;
|
||||
}
|
||||
else
|
||||
{
|
||||
min = (tm0.min_filter&4) ? D3DTEXF_LINEAR : D3DTEXF_POINT;
|
||||
mag = tm0.mag_filter ? D3DTEXF_LINEAR : D3DTEXF_POINT;
|
||||
mip = d3dMipFilters[tm0.min_filter&3];
|
||||
}
|
||||
if ((addr & 0xE0) == 0xA0)
|
||||
stage += 4;
|
||||
|
||||
if (g_Config.bForceMaxAniso)
|
||||
{
|
||||
mag = D3DTEXF_ANISOTROPIC;
|
||||
mip = D3DTEXF_ANISOTROPIC;
|
||||
min = D3DTEXF_ANISOTROPIC;
|
||||
}
|
||||
dev->SetSamplerState(stage, D3DSAMP_MINFILTER, min);
|
||||
dev->SetSamplerState(stage, D3DSAMP_MAGFILTER, mag);
|
||||
dev->SetSamplerState(stage, D3DSAMP_MIPFILTER, mip);
|
||||
|
||||
dev->SetSamplerState(stage, D3DSAMP_MAXANISOTROPY,16);
|
||||
dev->SetSamplerState(stage, D3DSAMP_ADDRESSU,d3dClamps[tm0.wrap_s]);
|
||||
dev->SetSamplerState(stage, D3DSAMP_ADDRESSV,d3dClamps[tm0.wrap_t]);
|
||||
//wip
|
||||
//dev->SetSamplerState(stage,D3DSAMP_MIPMAPLODBIAS,tm0.lod_bias/4.0f);
|
||||
//char temp[256];
|
||||
//sprintf(temp,"lod %f",tm0.lod_bias/4.0f);
|
||||
//g_VideoInitialize.pLog(temp);
|
||||
}
|
||||
break;
|
||||
case 0x84://TEX MODE 1
|
||||
case 0xA4:
|
||||
break;
|
||||
case 0x88://TEX IMAGE 0
|
||||
case 0xA8:
|
||||
if (changes)
|
||||
{
|
||||
textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true;
|
||||
CVertexHandler::Flush();
|
||||
}
|
||||
break;
|
||||
case 0x8C://TEX IMAGE 1
|
||||
case 0xAC:
|
||||
if (changes)
|
||||
{
|
||||
textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true;
|
||||
CVertexHandler::Flush();
|
||||
}
|
||||
break;
|
||||
case 0x90://TEX IMAGE 2
|
||||
case 0xB0:
|
||||
if (changes)
|
||||
{
|
||||
textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true;
|
||||
CVertexHandler::Flush();
|
||||
}
|
||||
break;
|
||||
case 0x94://TEX IMAGE 3
|
||||
case 0xB4:
|
||||
if (changes)
|
||||
{
|
||||
textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true;
|
||||
CVertexHandler::Flush();
|
||||
}
|
||||
break;
|
||||
case 0x98://TEX TLUT
|
||||
case 0xB8:
|
||||
if (changes)
|
||||
{
|
||||
textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true;
|
||||
CVertexHandler::Flush();
|
||||
}
|
||||
break;
|
||||
case 0x9C://TEX UNKNOWN
|
||||
case 0xBC:
|
||||
break;
|
||||
default:
|
||||
switch(addr&0xF0) {
|
||||
case 0x30:
|
||||
{
|
||||
int tc = addr&0x1;
|
||||
int stage = (addr>>1)&0x7;
|
||||
TCoordInfo &tci = bpmem.texcoords[stage];
|
||||
//TCInfo &t = (tc?tci.s:tc.t);
|
||||
// cylindric wrapping here
|
||||
//dev->SetRenderState(D3DRS_WRAP0+stage, D3DWRAPCOORD_0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xE0:
|
||||
if (addr<0xe8)
|
||||
{
|
||||
if (addr&1)
|
||||
{
|
||||
CVertexHandler::Flush();
|
||||
((u32*)&bpmem)[addr] = newval;
|
||||
static int lastRGBA[2][4] = {
|
||||
{0xEEEEEEEE,0xEEEEEEEE,0xEEEEEEEE,0xEEEEEEEE},
|
||||
{0xEEEEEEEE,0xEEEEEEEE,0xEEEEEEEE,0xEEEEEEEE}
|
||||
};
|
||||
//Terrible hack
|
||||
//The reason is that there are two sets of registers
|
||||
//overloaded here...
|
||||
int num=(addr>>1)&0x3;
|
||||
int type = bpmem.tevregs[num].high.type;
|
||||
int colorbase = type ? PS_CONST_KCOLORS : PS_CONST_COLORS;
|
||||
int r=bpmem.tevregs[num].low.a, a=bpmem.tevregs[num].low.b;
|
||||
int b=bpmem.tevregs[num].high.a, g=bpmem.tevregs[num].high.b;
|
||||
int rgba = ((a<<24) | (r << 16) | (g << 8) | b) & 0xFCFCFCFC; //let's not detect minimal changes
|
||||
if (rgba != lastRGBA[type][num])
|
||||
{
|
||||
CVertexHandler::Flush();
|
||||
lastRGBA[type][num] = rgba;
|
||||
float temp[4] = {
|
||||
r/255.0f,g/255.0f,b/255.0f,a/255.0f
|
||||
};
|
||||
D3D::dev->SetPixelShaderConstantF(colorbase+num,temp,1);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x20:
|
||||
case 0xC0:
|
||||
case 0xD0:
|
||||
case 0x80:
|
||||
case 0x90:
|
||||
case 0xA0:
|
||||
case 0xB0:
|
||||
default:
|
||||
if (changes)
|
||||
{
|
||||
CVertexHandler::Flush();
|
||||
((u32*)&bpmem)[addr] = newval;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// LoadBPReg
|
||||
//
|
||||
void LoadBPReg(u32 value0)
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
|
||||
//handle the mask register
|
||||
int opcode = value0 >> 24;
|
||||
int oldval = ((u32*)&bpmem)[opcode];
|
||||
int newval = (((u32*)&bpmem)[opcode] & ~bpmem.bpMask) | (value0 & bpmem.bpMask);
|
||||
int changes = (oldval ^ newval) & 0xFFFFFF;
|
||||
//reset the mask register
|
||||
if(opcode != 0xFE)
|
||||
bpmem.bpMask = 0xFFFFFF;
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
case 0x45: //GXSetDrawDone
|
||||
CVertexHandler::Flush();
|
||||
switch (value0 & 0xFF)
|
||||
{
|
||||
case 0x02:
|
||||
g_VideoInitialize.pSetPEFinish(); // may generate interrupt
|
||||
DebugLog("GXSetDrawDone SetPEFinish (value: 0x%02X)", (value0 & 0xFFFF));
|
||||
break;
|
||||
|
||||
default:
|
||||
DebugLog("GXSetDrawDone ??? (value 0x%02X)", (value0 & 0xFFFF));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case BPMEM_PE_TOKEN_ID:
|
||||
g_VideoInitialize.pSetPEToken(static_cast<WORD>(value0 & 0xFFFF), FALSE);
|
||||
DebugLog("SetPEToken 0x%04x", (value0 & 0xFFFF));
|
||||
break;
|
||||
|
||||
case BPMEM_PE_TOKEN_INT_ID:
|
||||
g_VideoInitialize.pSetPEToken(static_cast<WORD>(value0 & 0xFFFF), TRUE);
|
||||
DebugLog("SetPEToken + INT 0x%04x", (value0 & 0xFFFF));
|
||||
break;
|
||||
|
||||
case 0x67:
|
||||
{
|
||||
// char test[256];
|
||||
// sprintf(test, "Setgpmetric: 0x%08x", value0);
|
||||
// MessageBox(0, test, "Setgpmetric", 0);
|
||||
}
|
||||
//Setgpmetric
|
||||
break;
|
||||
|
||||
case 0x52:
|
||||
{
|
||||
CVertexHandler::Flush();
|
||||
|
||||
((u32*)&bpmem)[opcode] = newval;
|
||||
RECT rc = {
|
||||
(LONG)(bpmem.copyTexSrcXY.x*Renderer::GetXScale()),
|
||||
(LONG)(bpmem.copyTexSrcXY.y*Renderer::GetYScale()),
|
||||
(LONG)((bpmem.copyTexSrcXY.x+bpmem.copyTexSrcWH.x)*Renderer::GetXScale()),
|
||||
(LONG)((bpmem.copyTexSrcXY.y+bpmem.copyTexSrcWH.y)*Renderer::GetYScale())
|
||||
};
|
||||
|
||||
UPE_Copy PE_copy;
|
||||
PE_copy.Hex = bpmem.triggerEFBCopy;
|
||||
|
||||
// clamp0
|
||||
// clamp1
|
||||
// target_pixel_format
|
||||
// gamma
|
||||
// scale_something
|
||||
// clear
|
||||
// frame_to_field
|
||||
// copy_to_xfb
|
||||
|
||||
// ???: start Mem to/from EFB transfer
|
||||
/* bool bMip = false; // ignored
|
||||
if (bpmem.triggerEFBCopy & EFBCOPY_GENERATEMIPS)
|
||||
bMip = true;*/
|
||||
|
||||
if (PE_copy.copy_to_xfb == 0) // bpmem.triggerEFBCopy & EFBCOPY_EFBTOTEXTURE)
|
||||
{
|
||||
// EFB to texture
|
||||
TextureCache::CopyEFBToRenderTarget(bpmem.copyTexDest<<5, &rc);
|
||||
}
|
||||
else
|
||||
{
|
||||
// EFB to XFB
|
||||
// MessageBox(0, "WASDF", 0, 0);
|
||||
Renderer::SwapBuffers();
|
||||
DebugLog("Renderer::SwapBuffers()");
|
||||
g_VideoInitialize.pCopiedToXFB();
|
||||
}
|
||||
|
||||
// clearing
|
||||
if (PE_copy.clear) // bpmem.triggerEFBCopy & EFBCOPY_CLEAR)
|
||||
{
|
||||
// it seems that the GC is able to alpha blend on color-fill
|
||||
// we cant do that so if alpha is != 255 we skip it
|
||||
|
||||
// clear color
|
||||
u32 clearColor = (bpmem.clearcolorAR<<16)|bpmem.clearcolorGB;
|
||||
if (bpmem.blendmode.colorupdate)
|
||||
{
|
||||
D3DRECT drc;
|
||||
drc.x1 = rc.left;
|
||||
drc.x2 = rc.right;
|
||||
drc.y1 = rc.top;
|
||||
drc.y2 = rc.bottom;
|
||||
//D3D::dev->Clear(1, &drc, D3DCLEAR_STENCIL|D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,clearColor,1.0f,0);
|
||||
//if ((clearColor>>24) == 255)
|
||||
D3D::dev->ColorFill(D3D::GetBackBufferSurface(), &rc, clearColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO:
|
||||
// bpmem.blendmode.alphaupdate
|
||||
// bpmem.blendmode.colorupdate
|
||||
// i dunno how to implement a clear on alpha only or color only
|
||||
}
|
||||
|
||||
// clear z-buffer
|
||||
if (bpmem.zmode.updateenable)
|
||||
{
|
||||
float clearZ = (float)bpmem.clearZValue / float(0xFFFFFF);
|
||||
if (clearZ > 1.0f) clearZ = 1.0f;
|
||||
if (clearZ < 0.0f) clearZ = 0.0f;
|
||||
|
||||
D3D::dev->Clear(0, 0, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0, clearZ, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x65: //GXLoadTlut
|
||||
{
|
||||
CVertexHandler::Flush();
|
||||
((u32*)&bpmem)[opcode] = newval;
|
||||
|
||||
u32 tlutTMemAddr = (value0&0x3FF)<<9;
|
||||
u32 tlutXferCount = (value0&0x1FFC00)>>5;
|
||||
//do the transfer!!
|
||||
memcpy(texMem + tlutTMemAddr, g_VideoInitialize.pGetMemoryPointer((bpmem.tlutXferSrc&0xFFFFF)<<5), tlutXferCount);
|
||||
// TODO(ector) : kill all textures that use this palette
|
||||
// Not sure if it's a good idea, though. For now, we hash texture palettes
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//notify the video handling so it can update render states
|
||||
BPWritten(opcode, changes, newval);
|
||||
((u32*)&bpmem)[opcode] = newval;
|
||||
}
|
||||
|
||||
void BPReload()
|
||||
{
|
||||
for (int i=0; i<254; i++)
|
||||
BPWritten(i, 0xFFFFFF, ((u32*)&bpmem)[i]);
|
||||
}
|
||||
|
||||
|
||||
size_t BPSaveLoadState(char *ptr, BOOL save)
|
||||
{
|
||||
/*
|
||||
BEGINSAVELOAD;
|
||||
SAVELOAD(&bpmem,sizeof(BPMemory));
|
||||
if (!save)
|
||||
BPReload();
|
||||
char temp[256];
|
||||
sprintf(temp,"MOJS %08x",(bpmem.clearcolorAR<<16)|(bpmem.clearcolorGB));
|
||||
g_VideoInitialize.pLog(temp, FALSE);
|
||||
ENDSAVELOAD;*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ActivateTextures()
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
//TODO(ector): this should be a speedup
|
||||
//if (textureChanged[i] || ASK TEXCACHE ABOUT SENTINEL VALUE)
|
||||
{
|
||||
FourTexUnits &tex = bpmem.tex[i>>2];
|
||||
TextureCache::Load(i,
|
||||
(tex.texImage3[i&3].image_base) << 5,
|
||||
tex.texImage0[i&3].width+1,
|
||||
tex.texImage0[i&3].height+1,
|
||||
tex.texImage0[i&3].format,
|
||||
tex.texTlut[i&3].tmem_offset<<9,
|
||||
tex.texTlut[i&3].tlut_format);
|
||||
}
|
||||
textureChanged[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,530 @@
|
||||
#ifndef _BPSTRUCTS_H
|
||||
#define _BPSTRUCTS_H
|
||||
|
||||
#pragma pack(4)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Tev/combiner things
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
enum TevBias
|
||||
{
|
||||
TB_ZERO = 0,
|
||||
TB_ADDHALF = 1,
|
||||
TB_SUBHALF = 2,
|
||||
TB_COMPARE = 3,
|
||||
};
|
||||
|
||||
|
||||
enum AlphaOp
|
||||
{
|
||||
ALPHAOP_AND = 0,
|
||||
ALPHAOP_OR,
|
||||
ALPHAOP_XOR,
|
||||
ALPHAOP_XNOR,
|
||||
};
|
||||
|
||||
enum Compare
|
||||
{
|
||||
COMPARE_NEVER,
|
||||
COMPARE_LESS,
|
||||
COMPARE_EQUAL,
|
||||
COMPARE_LEQUAL,
|
||||
COMPARE_GREATER,
|
||||
COMPARE_NEQUAL,
|
||||
COMPARE_GEQUAL,
|
||||
COMPARE_ALWAYS
|
||||
};
|
||||
|
||||
//color chan above:
|
||||
// rasterized color selections
|
||||
#define RAS1_CC_0 0x00000000 /* color channel 0 */
|
||||
#define RAS1_CC_1 0x00000001 /* color channel 1 */
|
||||
#define RAS1_CC_B 0x00000005 /* indirect texture bump alpha */
|
||||
#define RAS1_CC_BN 0x00000006 /* ind tex bump alpha, normalized 0-255 */
|
||||
#define RAS1_CC_Z 0x00000007 /* set color value to zero */
|
||||
|
||||
// Z-texture types (formats)
|
||||
#define TEV_Z_TYPE_U8 0x00000000
|
||||
#define TEV_Z_TYPE_U16 0x00000001
|
||||
#define TEV_Z_TYPE_U24 0x00000002
|
||||
|
||||
|
||||
struct TevStageCombiner
|
||||
{
|
||||
union ColorCombiner
|
||||
{
|
||||
struct //abc=8bit,d=10bit
|
||||
{
|
||||
unsigned d : 4;
|
||||
unsigned c : 4;
|
||||
unsigned b : 4;
|
||||
unsigned a : 4;
|
||||
|
||||
unsigned bias : 2;
|
||||
unsigned op : 1;
|
||||
unsigned clamp : 1;
|
||||
|
||||
unsigned scale : 2;
|
||||
unsigned outreg : 2; //1,2,3
|
||||
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
union AlphaCombiner
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned rswap : 2;
|
||||
unsigned tswap : 2;
|
||||
unsigned d : 3;
|
||||
unsigned c : 3;
|
||||
unsigned b : 3;
|
||||
unsigned a : 3;
|
||||
|
||||
unsigned bias : 2;
|
||||
unsigned op : 1;
|
||||
unsigned clamp : 1;
|
||||
|
||||
unsigned scale : 2;
|
||||
unsigned outreg : 2; //1,2,3
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
|
||||
ColorCombiner colorC;
|
||||
AlphaCombiner alphaC;
|
||||
};
|
||||
|
||||
union TwoTevStageOrders
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned texmap0 : 3;
|
||||
unsigned texcoord0 : 3;
|
||||
unsigned enable0 : 1;
|
||||
unsigned colorchan0 : 3;
|
||||
|
||||
unsigned pad0 : 2;
|
||||
|
||||
unsigned texmap1 : 3;
|
||||
unsigned texcoord1 : 3;
|
||||
unsigned enable1 : 1;
|
||||
unsigned colorchan1 : 3;
|
||||
|
||||
unsigned pad1 : 2;
|
||||
};
|
||||
u32 hex;
|
||||
int getTexMap(int i){return i?texmap1:texmap0;}
|
||||
int getTexCoord(int i){return i?texcoord1:texcoord0;}
|
||||
int getEnable(int i){return i?enable1:enable0;}
|
||||
int getColorChan(int i){return i?colorchan1:colorchan0;}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Texture structs
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
union TexMode0
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned wrap_s : 2;
|
||||
unsigned wrap_t : 2;
|
||||
unsigned mag_filter : 1;
|
||||
unsigned min_filter : 3;
|
||||
unsigned diag_lod : 1;
|
||||
signed lod_bias : 8;
|
||||
unsigned max_aniso : 2;
|
||||
unsigned lod_clamp : 1;
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
union TexMode1
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned min_lod : 8;
|
||||
unsigned max_lod : 8;
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
union TexImage0
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned width : 10; //actually w-1
|
||||
unsigned height : 10; //actually h-1
|
||||
unsigned format : 4;
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
union TexImage1
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned tmem_offset : 15; // we ignore texture caching for now, we do it ourselves
|
||||
unsigned cache_width : 3;
|
||||
unsigned cache_height : 3;
|
||||
unsigned image_type : 1;
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
|
||||
union TexImage2
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned tmem_offset : 15; // we ignore texture caching for now, we do it ourselves
|
||||
unsigned cache_width : 3;
|
||||
unsigned cache_height : 3;
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
|
||||
union TexImage3
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned image_base: 24; //address in memory >> 5
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
union TexTLUT
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned tmem_offset : 10;
|
||||
unsigned tlut_format : 2;
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
|
||||
union ZTex1
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned bias : 24;
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
|
||||
union ZTex2
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned type : 2;
|
||||
unsigned op : 2;
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
|
||||
// Z-texture types (formats)
|
||||
#define TEV_ZTEX_TYPE_U8 0x00000000
|
||||
#define TEV_ZTEX_TYPE_U16 0x00000001
|
||||
#define TEV_ZTEX_TYPE_U24 0x00000002
|
||||
|
||||
#define TEV_ZTEX_DISABLE 0
|
||||
#define TEV_ZTEX_ADD 1
|
||||
#define TEV_ZTEX_REPLACE 2
|
||||
|
||||
|
||||
struct FourTexUnits
|
||||
{
|
||||
TexMode0 texMode0[4];
|
||||
TexMode1 texMode1[4];
|
||||
TexImage0 texImage0[4];
|
||||
TexImage1 texImage1[4];
|
||||
TexImage2 texImage2[4];
|
||||
TexImage3 texImage3[4];
|
||||
TexTLUT texTlut[4];
|
||||
u32 unknown[4];
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Geometry/other structs
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
union GenMode
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned numtexgens : 4; // 0xF
|
||||
unsigned numcolchans : 5; // 0x1E0
|
||||
unsigned ms_en : 1; // 0x200
|
||||
unsigned numtevstages : 4; // 0x3C00
|
||||
unsigned cullmode : 2; // 0xC000
|
||||
unsigned numindstages : 3; // 0x30000
|
||||
unsigned zfreeze : 5; //0x3C0000
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
|
||||
union LPSize
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned linesize : 8;
|
||||
unsigned pointsize : 8;
|
||||
unsigned lineoff : 3;
|
||||
unsigned pointoff : 3;
|
||||
unsigned lineaspect : 1;
|
||||
unsigned padding : 1;
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
|
||||
|
||||
union X12Y12
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned y : 12;
|
||||
unsigned x : 12;
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
union X10Y10
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned x : 10;
|
||||
unsigned y : 10;
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Framebuffer/pixel stuff (incl fog)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
union BlendMode
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned blendenable : 1;
|
||||
unsigned logicopenable : 1;
|
||||
unsigned dither : 1;
|
||||
unsigned colorupdate : 1;
|
||||
unsigned alphaupdate : 1;
|
||||
unsigned dstfactor : 3; //BLEND_ONE, BLEND_INV_SRc etc
|
||||
unsigned srcfactor : 3;
|
||||
unsigned subtract : 1;
|
||||
unsigned logicmode : 4;
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
|
||||
|
||||
union FogParam0
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned mantissa : 11;
|
||||
unsigned exponent : 8;
|
||||
unsigned sign : 1;
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
union FogParam3
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned cShifted12 : 20;
|
||||
unsigned proj : 1;
|
||||
unsigned fsel : 3;
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
struct FogParams
|
||||
{
|
||||
u32 a;
|
||||
u32 b_magnitude;
|
||||
u32 b_exponent;
|
||||
FogParam3 c_proj_fsel;
|
||||
u32 color; //0:b 8:g 16:r - nice!
|
||||
};
|
||||
|
||||
union ZMode
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned testenable : 1;
|
||||
unsigned func : 3;
|
||||
unsigned updateenable : 1; //size?
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
|
||||
union ConstantAlpha
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned alpha : 8;
|
||||
unsigned enable : 1;
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Texture coordinate stuff
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
union TCInfo
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned scale_minus_1 : 16;
|
||||
unsigned range_bias : 1;
|
||||
unsigned cylindric_wrap : 1;
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
struct TCoordInfo
|
||||
{
|
||||
TCInfo s;
|
||||
TCInfo t;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// All of BP memory
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
union ColReg
|
||||
{
|
||||
u32 hex;
|
||||
struct
|
||||
{
|
||||
signed a : 11;
|
||||
unsigned : 1;
|
||||
signed b : 11;
|
||||
unsigned type : 1;
|
||||
};
|
||||
};
|
||||
|
||||
struct TevReg
|
||||
{
|
||||
ColReg low;
|
||||
ColReg high;
|
||||
};
|
||||
|
||||
union TevKSel
|
||||
{
|
||||
struct {
|
||||
unsigned swap1 : 2;
|
||||
unsigned swap2 : 2;
|
||||
unsigned kcsel0 : 5;
|
||||
unsigned kasel0 : 5;
|
||||
unsigned kcsel1 : 5;
|
||||
unsigned kasel1 : 5;
|
||||
};
|
||||
u32 hex;
|
||||
|
||||
int getKC(int i) {return i?kcsel1:kcsel0;}
|
||||
int getKA(int i) {return i?kasel1:kasel0;}
|
||||
};
|
||||
|
||||
union AlphaFunc
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned ref0 : 8;
|
||||
unsigned ref1 : 8;
|
||||
unsigned comp0 : 3;
|
||||
unsigned comp1 : 3;
|
||||
unsigned logic : 2;
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
|
||||
union UPE_Copy
|
||||
{
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
unsigned clamp0 : 1;
|
||||
unsigned clamp1 : 1;
|
||||
unsigned target_pixel_format : 3;
|
||||
unsigned : 2;
|
||||
unsigned gamma : 2;
|
||||
unsigned : 1;
|
||||
unsigned scale_something : 1;
|
||||
unsigned clear : 1;
|
||||
unsigned frame_to_field : 2;
|
||||
unsigned copy_to_xfb : 1;
|
||||
unsigned : 17;
|
||||
};
|
||||
};
|
||||
|
||||
#define EFBCOPY_EFBTOTEXTURE 0x10000
|
||||
#define EFBCOPY_CLEAR 0x800
|
||||
#define EFBCOPY_GENERATEMIPS 0x200
|
||||
|
||||
struct BPMemory
|
||||
{
|
||||
GenMode genMode;
|
||||
u32 unknown[15]; //0f = flushtexturestate
|
||||
u32 tevind[16];
|
||||
X12Y12 scissorTL; //20
|
||||
X12Y12 scissorBR; //21
|
||||
LPSize lineptwidth; //22 line and point width
|
||||
u32 unknown1[2]; //23-24
|
||||
u32 unknown2[3]; //25-27
|
||||
TwoTevStageOrders tevorders[8]; //28-2F
|
||||
TCoordInfo texcoords[8]; //0x30 s,t,s,t,s,t,s,t...
|
||||
ZMode zmode; //40
|
||||
BlendMode blendmode; //41
|
||||
ConstantAlpha dstalpha; //42
|
||||
u32 unknown4; //43 // GXSetZCompLoc, GXPixModeSync
|
||||
u32 fieldmask; //44
|
||||
u32 drawdone; //45
|
||||
u32 unknown5; //46
|
||||
u32 drawsync1; //47
|
||||
u32 drawsync2; //48
|
||||
X10Y10 copyTexSrcXY; //49
|
||||
X10Y10 copyTexSrcWH; //4a
|
||||
u32 copyTexDest; //4b// 4b == CopyAddress (GXDispCopy and GXTexCopy use it)
|
||||
u32 unknown6[2]; //4c, 4d
|
||||
u32 dispcopyyscale; //4e
|
||||
u32 clearcolorAR; //4f
|
||||
u32 clearcolorGB; //50
|
||||
u32 clearZValue; //51
|
||||
u32 triggerEFBCopy; //52
|
||||
u32 copyfilter[2]; //53,54
|
||||
u32 boundbox0;//55
|
||||
u32 boundbox1;//56
|
||||
u32 unknown7[2];//57,58
|
||||
X10Y10 scissorOffset; //59
|
||||
u32 unknown8[10]; //5a,5b,5c,5d, 5e,5f,60,61, 62, 63 (GXTexModeSync),
|
||||
u32 tlutXferSrc; //64
|
||||
u32 tlutXferDest; //65
|
||||
u32 texinvalidate;//66
|
||||
u32 unknown9; //67
|
||||
u32 unknown10[8];//68-6F
|
||||
u32 unknown11[16];//70-7F
|
||||
FourTexUnits tex[2]; //80-bf
|
||||
TevStageCombiner combiners[16]; //0xC0-0xDF
|
||||
TevReg tevregs[4]; //0xE0
|
||||
u32 fogRangeAdj; //0xE8
|
||||
u32 unknown15[5]; //0xe9,0xea,0xeb,0xec,0xed
|
||||
FogParams fog; //0xEE,0xEF,0xF0,0xF1,0xF2
|
||||
AlphaFunc alphaFunc; //0xF3
|
||||
ZTex1 ztex1; //0xf4,0xf5
|
||||
ZTex2 ztex2;
|
||||
TevKSel tevksel[8];//0xf6,0xf7,f8,f9,fa,fb,fc,fd
|
||||
u32 bpMask; //0xFE
|
||||
u32 unknown18; //ff
|
||||
};
|
||||
|
||||
void BPInit();
|
||||
size_t BPSaveLoadState(char *ptr, BOOL save);
|
||||
//bool BPWritten(int addr, int changes);
|
||||
void LoadBPReg(u32 value0);
|
||||
|
||||
void ActivateTextures();
|
||||
|
||||
extern BPMemory bpmem;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,82 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "CPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
#include "TransformEngine.h"
|
||||
#include "VertexHandler.h"
|
||||
#include "VertexLoader.h"
|
||||
|
||||
// CP state
|
||||
u32 arraybases[16];
|
||||
u32 arraystrides[16];
|
||||
|
||||
TMatrixIndexA MatrixIndexA;
|
||||
TMatrixIndexB MatrixIndexB;
|
||||
|
||||
// PROBLEM - matrix switching within vbuffers may be stateful!
|
||||
|
||||
void CPUpdateMatricesA()
|
||||
{
|
||||
float *flipmem = (float *)xfmem;
|
||||
CTransformEngine::SetPosNormalMatrix(
|
||||
flipmem + MatrixIndexA.PosNormalMtxIdx * 4, //CHECK
|
||||
flipmem + 0x400 + 3 * (MatrixIndexA.PosNormalMtxIdx & 31)); //CHECK
|
||||
CTransformEngine::SetTexMatrix(0,flipmem + MatrixIndexA.Tex0MtxIdx * 4);
|
||||
CTransformEngine::SetTexMatrix(1,flipmem + MatrixIndexA.Tex1MtxIdx * 4);
|
||||
CTransformEngine::SetTexMatrix(2,flipmem + MatrixIndexA.Tex2MtxIdx * 4);
|
||||
CTransformEngine::SetTexMatrix(3,flipmem + MatrixIndexA.Tex3MtxIdx * 4);
|
||||
}
|
||||
|
||||
void CPUpdateMatricesB()
|
||||
{
|
||||
float *flipmem = (float *)xfmem;
|
||||
CTransformEngine::SetTexMatrix(4,flipmem + MatrixIndexB.Tex4MtxIdx * 4);
|
||||
CTransformEngine::SetTexMatrix(5,flipmem + MatrixIndexB.Tex5MtxIdx * 4);
|
||||
CTransformEngine::SetTexMatrix(6,flipmem + MatrixIndexB.Tex6MtxIdx * 4);
|
||||
CTransformEngine::SetTexMatrix(7,flipmem + MatrixIndexB.Tex7MtxIdx * 4);
|
||||
}
|
||||
|
||||
void LoadCPReg(u32 SubCmd, u32 Value)
|
||||
{
|
||||
switch (SubCmd & 0xF0)
|
||||
{
|
||||
case 0x30:
|
||||
MatrixIndexA.Hex = Value;
|
||||
CPUpdateMatricesA();
|
||||
break;
|
||||
case 0x40:
|
||||
MatrixIndexB.Hex = Value;
|
||||
CPUpdateMatricesB();
|
||||
break;
|
||||
|
||||
case 0x50: CVertexHandler::Flush(); VertexLoader::SetVtxDesc_Lo(Value); break;
|
||||
case 0x60: CVertexHandler::Flush(); VertexLoader::SetVtxDesc_Hi(Value); break;
|
||||
|
||||
case 0x70: g_VertexLoaders[SubCmd & 7].SetVAT_group0(Value); _assert_((SubCmd & 0x0F) < 8); break;
|
||||
case 0x80: g_VertexLoaders[SubCmd & 7].SetVAT_group1(Value); _assert_((SubCmd & 0x0F) < 8); break;
|
||||
case 0x90: g_VertexLoaders[SubCmd & 7].SetVAT_group2(Value); _assert_((SubCmd & 0x0F) < 8); break;
|
||||
|
||||
case 0xA0: arraybases[SubCmd & 0xF] = Value & 0xFFFFFFFF; break;
|
||||
case 0xB0: arraystrides[SubCmd & 0xF] = Value & 0xFF; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define BEGINSAVELOAD char *optr=ptr;
|
||||
#define SAVELOAD(what,size) memcpy((void*)((save)?(void*)(ptr):(void*)(what)),(void*)((save)?(void*)(what):(void*)(ptr)),(size)); ptr+=(size);
|
||||
#define ENDSAVELOAD return ptr-optr;
|
||||
|
||||
size_t CPSaveLoadState(char *ptr, BOOL save)
|
||||
{
|
||||
BEGINSAVELOAD;
|
||||
SAVELOAD(arraybases,16*sizeof(u32));
|
||||
SAVELOAD(arraystrides,16*sizeof(u32));
|
||||
SAVELOAD(&MatrixIndexA,sizeof(TMatrixIndexA));
|
||||
SAVELOAD(&MatrixIndexB,sizeof(TMatrixIndexB));
|
||||
if (!save)
|
||||
{
|
||||
CPUpdateMatricesA();
|
||||
CPUpdateMatricesB();
|
||||
}
|
||||
ENDSAVELOAD;
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
#ifndef _CPSTRUCTS_H
|
||||
#define _CPSTRUCTS_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,
|
||||
};
|
||||
|
||||
#pragma pack(4)
|
||||
|
||||
union TVtxDesc
|
||||
{
|
||||
u64 Hex;
|
||||
struct
|
||||
{
|
||||
// 0: not present
|
||||
// 1: present
|
||||
unsigned PosMatIdx : 1;
|
||||
unsigned Tex0MatIdx : 1;
|
||||
unsigned Tex1MatIdx : 1;
|
||||
unsigned Tex2MatIdx : 1;
|
||||
unsigned Tex3MatIdx : 1;
|
||||
unsigned Tex4MatIdx : 1;
|
||||
unsigned Tex5MatIdx : 1;
|
||||
unsigned Tex6MatIdx : 1;
|
||||
unsigned Tex7MatIdx : 1;
|
||||
|
||||
// 00: not present
|
||||
// 01: direct
|
||||
// 10: 8 bit index
|
||||
// 11: 16 bit index
|
||||
unsigned Position : 2;
|
||||
unsigned Normal : 2;
|
||||
unsigned Color0 : 2;
|
||||
unsigned Color1 : 2;
|
||||
unsigned Tex0Coord : 2;
|
||||
unsigned Tex1Coord : 2;
|
||||
unsigned Tex2Coord : 2;
|
||||
unsigned Tex3Coord : 2;
|
||||
unsigned Tex4Coord : 2;
|
||||
unsigned Tex5Coord : 2;
|
||||
unsigned Tex6Coord : 2;
|
||||
unsigned Tex7Coord : 2;
|
||||
unsigned :31;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
union UVAT_group0
|
||||
{
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
// 0:8
|
||||
unsigned PosElements : 1;
|
||||
unsigned PosFormat : 3;
|
||||
unsigned PosFrac : 5;
|
||||
// 9:12
|
||||
unsigned NormalElements : 1;
|
||||
unsigned NormalFormat : 3;
|
||||
// 13:16
|
||||
unsigned Color0Elements : 1;
|
||||
unsigned Color0Comp : 3;
|
||||
// 17:20
|
||||
unsigned Color1Elements : 1;
|
||||
unsigned Color1Comp : 3;
|
||||
// 21:29
|
||||
unsigned Tex0CoordElements : 1;
|
||||
unsigned Tex0CoordFormat : 3;
|
||||
unsigned Tex0Frac : 5;
|
||||
// 30:31
|
||||
unsigned ByteDequant: 1;
|
||||
unsigned NormalIndex3: 1;
|
||||
};
|
||||
};
|
||||
|
||||
union UVAT_group1
|
||||
{
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
// 0:8
|
||||
unsigned Tex1CoordElements : 1;
|
||||
unsigned Tex1CoordFormat : 3;
|
||||
unsigned Tex1Frac : 5;
|
||||
// 9:17
|
||||
unsigned Tex2CoordElements : 1;
|
||||
unsigned Tex2CoordFormat : 3;
|
||||
unsigned Tex2Frac : 5;
|
||||
// 18:26
|
||||
unsigned Tex3CoordElements : 1;
|
||||
unsigned Tex3CoordFormat : 3;
|
||||
unsigned Tex3Frac : 5;
|
||||
// 27:30
|
||||
unsigned Tex4CoordElements : 1;
|
||||
unsigned Tex4CoordFormat : 3;
|
||||
//
|
||||
unsigned : 1;
|
||||
};
|
||||
};
|
||||
|
||||
union UVAT_group2
|
||||
{
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
// 0:4
|
||||
unsigned Tex4Frac : 5;
|
||||
// 5:13
|
||||
unsigned Tex5CoordElements : 1;
|
||||
unsigned Tex5CoordFormat : 3;
|
||||
unsigned Tex5Frac : 5;
|
||||
// 14:22
|
||||
unsigned Tex6CoordElements : 1;
|
||||
unsigned Tex6CoordFormat : 3;
|
||||
unsigned Tex6Frac : 5;
|
||||
// 23:31
|
||||
unsigned Tex7CoordElements : 1;
|
||||
unsigned Tex7CoordFormat : 3;
|
||||
unsigned 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
|
||||
{
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
unsigned PosNormalMtxIdx : 6;
|
||||
unsigned Tex0MtxIdx : 6;
|
||||
unsigned Tex1MtxIdx : 6;
|
||||
unsigned Tex2MtxIdx : 6;
|
||||
unsigned Tex3MtxIdx : 6;
|
||||
};
|
||||
};
|
||||
|
||||
union TMatrixIndexB
|
||||
{
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
unsigned Tex4MtxIdx : 6;
|
||||
unsigned Tex5MtxIdx : 6;
|
||||
unsigned Tex6MtxIdx : 6;
|
||||
unsigned Tex7MtxIdx : 6;
|
||||
};
|
||||
};
|
||||
|
||||
#pragma pack ()
|
||||
|
||||
extern TMatrixIndexA MatrixIndexA;
|
||||
extern TMatrixIndexB MatrixIndexB;
|
||||
extern u32 arraybases[16];
|
||||
extern u32 arraystrides[16];
|
||||
|
||||
void CPUpdateMatricesA();
|
||||
void CPUpdateMatricesB();
|
||||
size_t CPSaveLoadState(char *ptr, BOOL save);
|
||||
void LoadCPReg(u32 SubCmd, u32 Value);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,354 @@
|
||||
#include "D3DBase.h"
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
bool fullScreen = false, nextFullScreen=false;
|
||||
LPDIRECT3D9 D3D = NULL; // Used to create the D3DDevice
|
||||
LPDIRECT3DDEVICE9 dev = NULL; // Our rendering device
|
||||
LPDIRECT3DSURFACE9 backBuffer;
|
||||
D3DCAPS9 caps;
|
||||
int multisample;
|
||||
int resolution;
|
||||
|
||||
#define VENDOR_NVIDIA 4318
|
||||
|
||||
RECT client;
|
||||
HWND hWnd;
|
||||
int xres, yres;
|
||||
int cur_adapter;
|
||||
int psMajor;
|
||||
int psMinor;
|
||||
int vsMajor;
|
||||
int vsMinor;
|
||||
|
||||
bool bFrameInProgress = false;
|
||||
|
||||
//enum shit
|
||||
Adapter adapters[4];
|
||||
int numAdapters;
|
||||
|
||||
void Enumerate();
|
||||
|
||||
int GetNumAdapters()
|
||||
{
|
||||
return numAdapters;
|
||||
}
|
||||
|
||||
const Adapter &GetAdapter(int i)
|
||||
{
|
||||
return adapters[i];
|
||||
}
|
||||
|
||||
const Adapter &GetCurAdapter()
|
||||
{
|
||||
return adapters[cur_adapter];
|
||||
}
|
||||
|
||||
HRESULT Init()
|
||||
{
|
||||
// Create the D3D object, which is needed to create the D3DDevice.
|
||||
if( NULL == ( D3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
|
||||
return E_FAIL;
|
||||
|
||||
Enumerate();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void EnableAlphaToCoverage()
|
||||
{
|
||||
dev->SetRenderState(D3DRS_ADAPTIVETESS_Y, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C'));
|
||||
}
|
||||
|
||||
void InitPP(int adapter, int resolution, int aa_mode, D3DPRESENT_PARAMETERS *pp)
|
||||
{
|
||||
int FSResX = adapters[adapter].resolutions[resolution].xres;
|
||||
int FSResY = adapters[adapter].resolutions[resolution].yres;
|
||||
|
||||
ZeroMemory(pp, sizeof(D3DPRESENT_PARAMETERS));
|
||||
pp->hDeviceWindow = hWnd;
|
||||
pp->EnableAutoDepthStencil = TRUE;
|
||||
pp->AutoDepthStencilFormat = D3DFMT_D24S8;
|
||||
pp->BackBufferFormat = D3DFMT_A8R8G8B8;
|
||||
if (aa_mode >= (int)adapters[adapter].aa_levels.size())
|
||||
aa_mode = 0;
|
||||
|
||||
pp->MultiSampleType = adapters[adapter].aa_levels[aa_mode].ms_setting;
|
||||
pp->MultiSampleQuality = adapters[adapter].aa_levels[aa_mode].qual_setting;
|
||||
pp->Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
|
||||
|
||||
//D3DPRESENTFLAG_LOCKABLE_BACKBUFFER
|
||||
|
||||
if (fullScreen)
|
||||
{
|
||||
xres = pp->BackBufferWidth = FSResX;
|
||||
yres = pp->BackBufferHeight = FSResY;
|
||||
pp->SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
pp->Windowed = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
GetClientRect(hWnd, &client);
|
||||
xres = pp->BackBufferWidth = client.right - client.left;
|
||||
yres = pp->BackBufferHeight = client.bottom - client.top;
|
||||
pp->SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
pp->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||
pp->Windowed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void Enumerate()
|
||||
{
|
||||
numAdapters = D3D::D3D->GetAdapterCount();
|
||||
|
||||
for (int i=0; i<numAdapters; i++)
|
||||
{
|
||||
Adapter &a = adapters[i];
|
||||
D3D::D3D->GetAdapterIdentifier(i, 0, &a.ident);
|
||||
|
||||
bool isNvidia = a.ident.VendorId == VENDOR_NVIDIA;
|
||||
|
||||
// Add multisample modes
|
||||
a.aa_levels.push_back(AALevel("None", D3DMULTISAMPLE_NONE, 0));
|
||||
|
||||
DWORD qlevels = 0;
|
||||
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &qlevels))
|
||||
if (qlevels > 0)
|
||||
a.aa_levels.push_back(AALevel("2x MSAA", D3DMULTISAMPLE_2_SAMPLES, 0));
|
||||
|
||||
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &qlevels))
|
||||
if (qlevels > 0)
|
||||
a.aa_levels.push_back(AALevel("4x MSAA", D3DMULTISAMPLE_4_SAMPLES, 0));
|
||||
|
||||
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_8_SAMPLES, &qlevels))
|
||||
if (qlevels > 0)
|
||||
a.aa_levels.push_back(AALevel("8x MSAA", D3DMULTISAMPLE_8_SAMPLES, 0));
|
||||
|
||||
if (isNvidia)
|
||||
{
|
||||
// CSAA support
|
||||
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_4_SAMPLES, &qlevels))
|
||||
{
|
||||
if (qlevels > 2)
|
||||
{
|
||||
// 8x, 8xQ are available
|
||||
// See http://developer.nvidia.com/object/coverage-sampled-aa.html
|
||||
a.aa_levels.push_back(AALevel("8x CSAA", D3DMULTISAMPLE_4_SAMPLES, 2));
|
||||
a.aa_levels.push_back(AALevel("8xQ CSAA", D3DMULTISAMPLE_8_SAMPLES, 0));
|
||||
}
|
||||
}
|
||||
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_8_SAMPLES, &qlevels))
|
||||
{
|
||||
if (qlevels > 2)
|
||||
{
|
||||
// 8x, 8xQ are available
|
||||
// See http://developer.nvidia.com/object/coverage-sampled-aa.html
|
||||
a.aa_levels.push_back(AALevel("16x CSAA", D3DMULTISAMPLE_4_SAMPLES, 4));
|
||||
a.aa_levels.push_back(AALevel("16xQ CSAA", D3DMULTISAMPLE_8_SAMPLES, 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (a.aa_levels.size() == 1)
|
||||
{
|
||||
strcpy(a.aa_levels[0].name, "(Not supported on this device)");
|
||||
}
|
||||
|
||||
int numModes = D3D::D3D->GetAdapterModeCount(i, D3DFMT_X8R8G8B8);
|
||||
|
||||
for (int m = 0; m < numModes; m++)
|
||||
{
|
||||
D3DDISPLAYMODE mode;
|
||||
D3D::D3D->EnumAdapterModes(i, D3DFMT_X8R8G8B8, m, &mode);
|
||||
|
||||
int found = -1;
|
||||
for (int x = 0; x < (int)a.resolutions.size(); x++)
|
||||
{
|
||||
if (a.resolutions[x].xres == mode.Width && a.resolutions[x].yres == mode.Height)
|
||||
{
|
||||
found = x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Resolution temp;
|
||||
Resolution &r = found==-1 ? temp : a.resolutions[found];
|
||||
|
||||
sprintf(r.name, "%ix%i", mode.Width, mode.Height);
|
||||
r.bitdepths.insert(mode.Format);
|
||||
r.refreshes.insert(mode.RefreshRate);
|
||||
if (found == -1 && mode.Width >= 640 && mode.Height >= 480)
|
||||
{
|
||||
r.xres = mode.Width;
|
||||
r.yres = mode.Height;
|
||||
a.resolutions.push_back(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT Create(int adapter, HWND wnd, bool _fullscreen, int _resolution, int aa_mode)
|
||||
{
|
||||
hWnd = wnd;
|
||||
fullScreen = _fullscreen;
|
||||
nextFullScreen = _fullscreen;
|
||||
multisample = aa_mode;
|
||||
resolution = _resolution;
|
||||
cur_adapter = adapter;
|
||||
D3DPRESENT_PARAMETERS d3dpp;
|
||||
InitPP(adapter, resolution, aa_mode, &d3dpp);
|
||||
|
||||
if( FAILED( D3D->CreateDevice(
|
||||
adapter,
|
||||
D3DDEVTYPE_HAL,
|
||||
wnd,
|
||||
D3DCREATE_HARDWARE_VERTEXPROCESSING|D3DCREATE_MULTITHREADED,
|
||||
// |D3DCREATE_MULTITHREADED /* | D3DCREATE_PUREDEVICE*/,
|
||||
//D3DCREATE_SOFTWARE_VERTEXPROCESSING ,
|
||||
&d3dpp, &dev ) ) )
|
||||
{
|
||||
MessageBox(wnd,
|
||||
"Direct3D Device creation failed!\n"
|
||||
"Your device does not support the desired settings.",
|
||||
"D3D error", MB_OK|MB_ICONERROR);
|
||||
return E_FAIL;
|
||||
}
|
||||
dev->GetDeviceCaps(&caps);
|
||||
dev->GetRenderTarget(0,&backBuffer);
|
||||
|
||||
psMajor = (D3D::caps.PixelShaderVersion >> 8) & 0xFF;
|
||||
psMinor = (D3D::caps.PixelShaderVersion) & 0xFF;
|
||||
vsMajor = (D3D::caps.VertexShaderVersion >>8) & 0xFF;
|
||||
vsMinor = (D3D::caps.VertexShaderVersion) & 0xFF;
|
||||
|
||||
|
||||
// Device state would normally be set here
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
ShaderVersion GetShaderVersion()
|
||||
{
|
||||
if (psMajor < 2)
|
||||
return PSNONE;
|
||||
else
|
||||
//good enough estimate - we really only
|
||||
//care about zero shader vs ps20
|
||||
return (ShaderVersion)psMajor;
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
dev->Release();
|
||||
dev = 0;
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
D3D->Release();
|
||||
D3D = 0;
|
||||
}
|
||||
|
||||
const D3DCAPS9 &GetCaps()
|
||||
{
|
||||
return caps;
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 GetBackBufferSurface()
|
||||
{
|
||||
return backBuffer;
|
||||
}
|
||||
|
||||
void ShowD3DError(HRESULT err)
|
||||
{
|
||||
switch (err)
|
||||
{
|
||||
case D3DERR_DEVICELOST:
|
||||
MessageBox(0, "Device Lost", "D3D ERROR", 0);
|
||||
break;
|
||||
case D3DERR_INVALIDCALL:
|
||||
MessageBox(0, "Invalid Call", "D3D ERROR", 0);
|
||||
break;
|
||||
case D3DERR_DRIVERINTERNALERROR:
|
||||
MessageBox(0, "Driver Internal Error", "D3D ERROR", 0);
|
||||
break;
|
||||
case D3DERR_OUTOFVIDEOMEMORY:
|
||||
MessageBox(0, "Out of vid mem", "D3D ERROR", 0);
|
||||
break;
|
||||
default:
|
||||
// MessageBox(0,"Other error or success","ERROR",0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
if (dev)
|
||||
{
|
||||
D3DPRESENT_PARAMETERS d3dpp;
|
||||
InitPP(cur_adapter, resolution, multisample, &d3dpp);
|
||||
HRESULT hr = dev->Reset(&d3dpp);
|
||||
ShowD3DError(hr);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsFullscreen()
|
||||
{
|
||||
return fullScreen;
|
||||
}
|
||||
|
||||
int GetDisplayWidth()
|
||||
{
|
||||
return xres;
|
||||
}
|
||||
int GetDisplayHeight()
|
||||
{
|
||||
return yres;
|
||||
}
|
||||
void SwitchFullscreen(bool fullscreen)
|
||||
{
|
||||
nextFullScreen = fullscreen;
|
||||
}
|
||||
|
||||
bool BeginFrame(bool clear, u32 color, float z)
|
||||
{
|
||||
if (bFrameInProgress)
|
||||
return false;
|
||||
|
||||
bFrameInProgress = true;
|
||||
|
||||
if (dev)
|
||||
{
|
||||
if (clear)
|
||||
dev->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, (DWORD)color, z, 0 );
|
||||
dev->BeginScene();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void EndFrame()
|
||||
{
|
||||
if (!bFrameInProgress)
|
||||
return;
|
||||
|
||||
bFrameInProgress = false;
|
||||
|
||||
if (dev)
|
||||
{
|
||||
dev->EndScene();
|
||||
dev->Present( NULL, NULL, NULL, NULL );
|
||||
}
|
||||
|
||||
if (fullScreen != nextFullScreen)
|
||||
{
|
||||
fullScreen = nextFullScreen;
|
||||
Reset();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
#ifndef _D3DBASE_H
|
||||
#define _D3DBASE_H
|
||||
|
||||
#include <d3d9.h>
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#ifndef SAFE_RELEASE
|
||||
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
|
||||
#endif
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
enum ShaderVersion
|
||||
{
|
||||
PSNONE=0,
|
||||
PS20=2,
|
||||
PS30,
|
||||
PS40,
|
||||
};
|
||||
|
||||
HRESULT Init();
|
||||
HRESULT Create(int adapter, HWND wnd, bool fullscreen, int resolution, int aa_mode);
|
||||
void Close();
|
||||
void Shutdown();
|
||||
|
||||
void Reset();
|
||||
bool BeginFrame(bool clear=true, u32 color=0, float z=1.0f);
|
||||
void EndFrame();
|
||||
void SwitchFullscreen(bool fullscreen);
|
||||
bool IsFullscreen();
|
||||
int GetDisplayWidth();
|
||||
int GetDisplayHeight();
|
||||
ShaderVersion GetShaderVersion();
|
||||
LPDIRECT3DSURFACE9 GetBackBufferSurface();
|
||||
const D3DCAPS9 &GetCaps();
|
||||
extern IDirect3DDevice9 *dev;
|
||||
void ShowD3DError(HRESULT err);
|
||||
void EnableAlphaToCoverage();
|
||||
|
||||
extern int psMajor;
|
||||
extern int psMinor;
|
||||
extern int vsMajor;
|
||||
extern int vsMinor;
|
||||
|
||||
struct Resolution
|
||||
{
|
||||
char name[32];
|
||||
int xres;
|
||||
int yres;
|
||||
std::set<D3DFORMAT> bitdepths;
|
||||
std::set<int> refreshes;
|
||||
};
|
||||
|
||||
struct AALevel
|
||||
{
|
||||
AALevel(const char *n, D3DMULTISAMPLE_TYPE m, int q) {strcpy(name, n); ms_setting=m; qual_setting=q;}
|
||||
char name[32];
|
||||
D3DMULTISAMPLE_TYPE ms_setting;
|
||||
int qual_setting;
|
||||
};
|
||||
|
||||
struct Adapter
|
||||
{
|
||||
D3DADAPTER_IDENTIFIER9 ident;
|
||||
std::vector<Resolution> resolutions;
|
||||
std::vector<AALevel> aa_levels;
|
||||
bool supports_alpha_to_coverage;
|
||||
};
|
||||
|
||||
const Adapter &GetAdapter(int i);
|
||||
const Adapter &GetCurAdapter();
|
||||
int GetNumAdapters();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,238 @@
|
||||
#include "Common.h"
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "D3DTexture.h"
|
||||
#include "D3DUtil.h"
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
using namespace D3D;
|
||||
|
||||
namespace Postprocess
|
||||
{
|
||||
LPDIRECT3DSURFACE9 displayColorBuffer;
|
||||
LPDIRECT3DSURFACE9 displayZStencilBuffer;
|
||||
|
||||
LPDIRECT3DTEXTURE9 mainColorBufferTexture;
|
||||
LPDIRECT3DSURFACE9 mainColorBuffer;
|
||||
LPDIRECT3DSURFACE9 mainZStencilBuffer;
|
||||
|
||||
const int numScratch = 2;
|
||||
LPDIRECT3DTEXTURE9 scratch[numScratch];
|
||||
LPDIRECT3DSURFACE9 scratchSurface[numScratch];
|
||||
|
||||
const int mainWidth = 640, mainHeight=480;
|
||||
const int scratchWidth = 256, scratchHeight=256;
|
||||
|
||||
int displayWidth, displayHeight;
|
||||
|
||||
bool initialized;
|
||||
|
||||
int GetWidth() {
|
||||
return initialized ? mainWidth : displayWidth;
|
||||
}
|
||||
|
||||
int GetHeight() {
|
||||
return initialized ? mainHeight : displayHeight;
|
||||
}
|
||||
|
||||
|
||||
void CreateStuff()
|
||||
{
|
||||
mainColorBufferTexture = D3D::CreateRenderTarget(mainWidth,mainHeight);
|
||||
mainColorBufferTexture->GetSurfaceLevel(0,&mainColorBuffer);
|
||||
mainZStencilBuffer = D3D::CreateDepthStencilSurface(mainWidth,mainHeight);
|
||||
|
||||
for (int i=0; i<numScratch; i++)
|
||||
{
|
||||
scratch[i]=D3D::CreateRenderTarget(scratchWidth,scratchHeight);
|
||||
scratch[i]->GetSurfaceLevel(0,&(scratchSurface[i]));
|
||||
}
|
||||
|
||||
initialized=true;
|
||||
}
|
||||
|
||||
void DestroyStuff()
|
||||
{
|
||||
SAFE_RELEASE(mainColorBuffer);
|
||||
SAFE_RELEASE(mainColorBufferTexture);
|
||||
SAFE_RELEASE(mainZStencilBuffer);
|
||||
|
||||
for (int i=0; i<numScratch; i++)
|
||||
{
|
||||
SAFE_RELEASE(scratch[i]);
|
||||
SAFE_RELEASE(scratchSurface[i]);
|
||||
}
|
||||
initialized=false;
|
||||
}
|
||||
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
dev->GetRenderTarget(0,&displayColorBuffer);
|
||||
dev->GetDepthStencilSurface(&displayZStencilBuffer);
|
||||
|
||||
D3DSURFACE_DESC desc;
|
||||
displayColorBuffer->GetDesc(&desc);
|
||||
displayWidth = desc.Width;
|
||||
displayHeight = desc.Height;
|
||||
|
||||
if (g_Config.iPostprocessEffect)
|
||||
CreateStuff();
|
||||
}
|
||||
|
||||
void Cleanup()
|
||||
{
|
||||
DestroyStuff();
|
||||
SAFE_RELEASE(displayColorBuffer);
|
||||
SAFE_RELEASE(displayZStencilBuffer);
|
||||
}
|
||||
|
||||
|
||||
void BeginFrame()
|
||||
{
|
||||
if (g_Config.iPostprocessEffect)
|
||||
{
|
||||
if (!initialized)
|
||||
CreateStuff();
|
||||
dev->SetRenderTarget(0,mainColorBuffer);
|
||||
dev->SetDepthStencilSurface(mainZStencilBuffer);
|
||||
dev->SetRenderState(D3DRS_ZENABLE,TRUE);
|
||||
dev->Clear(0,0,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,0,1,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (initialized)
|
||||
{
|
||||
dev->SetRenderTarget(0,displayColorBuffer);
|
||||
dev->SetDepthStencilSurface(displayZStencilBuffer);
|
||||
DestroyStuff();
|
||||
}
|
||||
dev->SetRenderState(D3DRS_ZENABLE,TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int filterKernel[8] = {0x40,0x80,0xc0,0xFF,0xFF,0xc0,0x80,0x40}; //goodlooking almostgaussian
|
||||
|
||||
//int filterKernel[8] = {0xFF,0xc0,0x80,0x40,0x40,0x80,0xc0,0xFF,}; //crazy filter
|
||||
|
||||
void NightGlow(bool intense, bool original)
|
||||
{
|
||||
dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_SUBTRACT);
|
||||
|
||||
dev->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
|
||||
dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);
|
||||
dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);
|
||||
|
||||
dev->SetDepthStencilSurface(0);
|
||||
|
||||
dev->SetTexture(0,mainColorBufferTexture);
|
||||
dev->SetRenderTarget(0,scratchSurface[0]);
|
||||
dev->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_CLAMP);
|
||||
dev->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_CLAMP);
|
||||
dev->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
|
||||
dev->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);
|
||||
dev->SetSamplerState(0,D3DSAMP_MIPFILTER,D3DTEXF_LINEAR);
|
||||
dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0);
|
||||
|
||||
POINT pt;
|
||||
GetCursorPos(&pt);
|
||||
|
||||
//dev->SetSamplerState(0,D3DSAMP_MIPMAPLODBIAS,1.0f);
|
||||
#define QOFF(xoff,yoff,col) quad2d(-0.0f,-0.0f,scratchWidth-0.0f,scratchHeight-0.0f,col,0+xoff,0+yoff,1+xoff,1+yoff);
|
||||
float f=0.008f;
|
||||
QOFF(0,0,0xa0a0a0a0);
|
||||
|
||||
dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
|
||||
|
||||
dev->SetTexture(0,scratch[0]);
|
||||
dev->SetRenderTarget(0,scratchSurface[1]);
|
||||
dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0);
|
||||
|
||||
float yMul = 1.33333333333f;
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
DWORD c=filterKernel[i]/2;
|
||||
c|=c<<8;
|
||||
c|=c<<16;
|
||||
QOFF(0,(i-3.5f) * f * yMul,c);
|
||||
}
|
||||
|
||||
dev->SetTexture(0,scratch[1]);
|
||||
dev->SetRenderTarget(0,scratchSurface[0]);
|
||||
dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0);
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
DWORD c=filterKernel[i]/(intense?3:2);
|
||||
c|=c<<8;
|
||||
c|=c<<16;
|
||||
QOFF((i-3.5f) * f,0,c);
|
||||
}
|
||||
|
||||
dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
|
||||
|
||||
if (intense)
|
||||
{
|
||||
dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);
|
||||
dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_SRCALPHA);
|
||||
}
|
||||
else
|
||||
{
|
||||
dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_INVDESTCOLOR);
|
||||
dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);
|
||||
}
|
||||
|
||||
dev->SetTexture(0,scratch[0]);
|
||||
dev->SetRenderTarget(0,mainColorBuffer);
|
||||
quad2d(0,0,(float)mainWidth,(float)mainHeight,original?0xCFFFFFFF:0xFFFFFFFF,0,0,1,1);
|
||||
dev->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE);
|
||||
dev->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_WRAP);
|
||||
dev->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_WRAP);
|
||||
//dev->SetSamplerState(0,D3DSAMP_MIPMAPLODBIAS,0);
|
||||
}
|
||||
|
||||
const char **GetPostprocessingNames()
|
||||
{
|
||||
static const char *names[] = {
|
||||
"None",
|
||||
"Night Glow 1",
|
||||
"Night Glow 2",
|
||||
"Night Glow 3",
|
||||
0,
|
||||
};
|
||||
return names;
|
||||
}
|
||||
|
||||
void FinalizeFrame()
|
||||
{
|
||||
if (initialized)
|
||||
{
|
||||
dev->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
|
||||
dev->SetRenderState(D3DRS_ZENABLE,FALSE);
|
||||
dev->SetRenderState(D3DRS_FOGENABLE,FALSE);
|
||||
dev->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
|
||||
dev->SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE);
|
||||
dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
|
||||
dev->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE);
|
||||
dev->SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_DIFFUSE);
|
||||
dev->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG2);
|
||||
|
||||
switch(g_Config.iPostprocessEffect) {
|
||||
case 1:
|
||||
NightGlow(true,true);
|
||||
case 2:
|
||||
NightGlow(false,true);
|
||||
break;
|
||||
case 3:
|
||||
NightGlow(false,false);
|
||||
break;
|
||||
}
|
||||
|
||||
dev->SetRenderTarget(0,displayColorBuffer);
|
||||
dev->SetDepthStencilSurface(displayZStencilBuffer);
|
||||
dev->SetTexture(0,mainColorBufferTexture);
|
||||
quad2d(0, 0, (float)displayWidth, (float)displayHeight, 0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
namespace Postprocess
|
||||
{
|
||||
|
||||
void Initialize();
|
||||
void Cleanup();
|
||||
|
||||
void BeginFrame();
|
||||
void FinalizeFrame();
|
||||
|
||||
int GetWidth();
|
||||
int GetHeight();
|
||||
|
||||
const char **GetPostprocessingNames();
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
#include <d3dx9.h>
|
||||
|
||||
#include "Globals.h"
|
||||
#include "D3DShader.h"
|
||||
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
LPDIRECT3DVERTEXSHADER9 CompileVShader(const char *code, int len)
|
||||
{
|
||||
//try to compile
|
||||
LPD3DXBUFFER shaderBuffer=0,errorBuffer=0;
|
||||
LPDIRECT3DVERTEXSHADER9 vShader = 0;
|
||||
HRESULT hr = D3DXCompileShader(code,len,0,0,"main","vs_1_1",0,&shaderBuffer,&errorBuffer,0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
//let's try 2.0
|
||||
hr = D3DXCompileShader(code,len,0,0,"main","vs_2_0",0,&shaderBuffer,&errorBuffer,0);
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
//compilation error, damnit
|
||||
if (g_Config.bShowShaderErrors)
|
||||
MessageBox(0,(char*)errorBuffer->GetBufferPointer(),"VS compilation error",MB_ICONERROR);
|
||||
vShader=0;
|
||||
}
|
||||
else if (SUCCEEDED(hr))
|
||||
{
|
||||
//create it
|
||||
HRESULT hr = E_FAIL;
|
||||
if (shaderBuffer)
|
||||
hr = D3D::dev->CreateVertexShader((DWORD *)shaderBuffer->GetBufferPointer(), &vShader);
|
||||
if (FAILED(hr) || vShader == 0)
|
||||
{
|
||||
if (g_Config.bShowShaderErrors)
|
||||
MessageBox(0,code,(char*)errorBuffer->GetBufferPointer(),MB_ICONERROR);
|
||||
}
|
||||
}
|
||||
|
||||
//cleanup
|
||||
if (shaderBuffer)
|
||||
shaderBuffer->Release();
|
||||
if (errorBuffer)
|
||||
errorBuffer->Release();
|
||||
|
||||
return vShader;
|
||||
}
|
||||
LPDIRECT3DVERTEXSHADER9 LoadVShader(const char *filename)
|
||||
{
|
||||
//alloc a temp buffer for code
|
||||
char *temp = new char[65536];
|
||||
|
||||
//open and read the file
|
||||
FILE *f = fopen(filename,"rb");
|
||||
if (!f)
|
||||
{
|
||||
MessageBox(0,"FATAL ERROR Vertex Shader file not found",filename,0);
|
||||
return 0;
|
||||
}
|
||||
fseek(f,0,SEEK_END);
|
||||
int len = ftell(f);
|
||||
fseek(f,0,SEEK_SET);
|
||||
fread(temp,len,1,f);
|
||||
fclose(f);
|
||||
LPDIRECT3DVERTEXSHADER9 vShader = CompileVShader(temp,len);
|
||||
//kill off our temp code buffer
|
||||
delete [] temp;
|
||||
//return the compiled shader, or null
|
||||
return vShader;
|
||||
}
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 CompilePShader(const char *code, int len)
|
||||
{
|
||||
LPD3DXBUFFER shaderBuffer=0,errorBuffer=0;
|
||||
LPDIRECT3DPIXELSHADER9 pShader = 0;
|
||||
static char *versions[6] = {"ERROR","ps_1_1","ps_1_4","ps_2_0","ps_3_0","ps_4_0"};
|
||||
HRESULT hr = D3DXCompileShader(code,len,0,0,
|
||||
"main","ps_2_0", // Pixel Shader 2.0 is enough for all we do
|
||||
0,&shaderBuffer,&errorBuffer,0);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// We should not be getting these
|
||||
MessageBox(0,code,(char*)errorBuffer->GetBufferPointer(),MB_ICONERROR);
|
||||
|
||||
pShader=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//create it
|
||||
HRESULT hr = D3D::dev->CreatePixelShader((DWORD *)shaderBuffer->GetBufferPointer(), &pShader);
|
||||
if (FAILED(hr) || pShader == 0)
|
||||
{
|
||||
if (g_Config.bShowShaderErrors)
|
||||
MessageBox(0,"damn","error creating pixelshader",MB_ICONERROR);
|
||||
}
|
||||
}
|
||||
|
||||
//cleanup
|
||||
if (shaderBuffer)
|
||||
shaderBuffer->Release();
|
||||
if (errorBuffer)
|
||||
errorBuffer->Release();
|
||||
|
||||
return pShader;
|
||||
}
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 LoadPShader(const char *filename)
|
||||
{
|
||||
//open and read the file
|
||||
FILE *f = fopen(filename,"rb");
|
||||
if (!f)
|
||||
{
|
||||
MessageBox(0,"FATAL ERROR Pixel Shader file not found",filename,0);
|
||||
return 0;
|
||||
}
|
||||
fseek(f,0,SEEK_END);
|
||||
int len = ftell(f);
|
||||
char *temp = new char[len];
|
||||
fseek(f,0,SEEK_SET);
|
||||
fread(temp,len,1,f);
|
||||
fclose(f);
|
||||
LPDIRECT3DPIXELSHADER9 pShader = CompilePShader(temp,len);
|
||||
//kill off our temp code buffer
|
||||
delete [] temp;
|
||||
//return the compiled shader, or null
|
||||
return pShader;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "D3DBase.h"
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
LPDIRECT3DVERTEXSHADER9 CompileVShader(const char *code, int len);
|
||||
LPDIRECT3DVERTEXSHADER9 LoadVShader(const char *filename);
|
||||
LPDIRECT3DPIXELSHADER9 CompilePShader(const char *code, int len);
|
||||
LPDIRECT3DPIXELSHADER9 LoadPShader(const char *filename);
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
#include "D3DBase.h"
|
||||
#include "D3DTexture.h"
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 CreateTexture2D(const BYTE* buffer, const int width, const int height,const int pitch, D3DFORMAT fmt)
|
||||
{
|
||||
DWORD *pBuffer = (DWORD *)buffer;
|
||||
LPDIRECT3DTEXTURE9 pTexture;
|
||||
|
||||
// crazy bitmagic
|
||||
bool isPow2 = !((width&(width-1)) || (height&(height-1)));
|
||||
|
||||
HRESULT hr;
|
||||
// TODO(ector): allow mipmaps for non-pow textures on newer cards?
|
||||
if (!isPow2)
|
||||
hr = dev->CreateTexture(width, height, 1, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
|
||||
else
|
||||
hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
|
||||
|
||||
if(FAILED(hr))
|
||||
return 0;
|
||||
|
||||
int level = 0;
|
||||
|
||||
D3DLOCKED_RECT Lock;
|
||||
pTexture->LockRect(level, &Lock, NULL, 0 );
|
||||
|
||||
DWORD* pIn = pBuffer;
|
||||
switch(fmt)
|
||||
{
|
||||
case D3DFMT_A8R8G8B8:
|
||||
{
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
DWORD* pBits = (DWORD*)((BYTE*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits,pIn, width * 4);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_DXT1:
|
||||
memcpy(Lock.pBits,buffer,(width/4)*(height/4)*8);
|
||||
break;
|
||||
}
|
||||
pTexture->UnlockRect(level);
|
||||
return pTexture;
|
||||
}
|
||||
|
||||
void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const BYTE* buffer, const int width, const int height,const int pitch, D3DFORMAT fmt)
|
||||
{
|
||||
DWORD *pBuffer = (DWORD *)buffer;
|
||||
int level=0;
|
||||
D3DLOCKED_RECT Lock;
|
||||
pTexture->LockRect(level, &Lock, NULL, 0 );
|
||||
DWORD* pIn = pBuffer;
|
||||
switch(fmt)
|
||||
{
|
||||
case D3DFMT_A8R8G8B8:
|
||||
{
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
DWORD* pBits = (DWORD*)((BYTE*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits,pIn, width*4);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_DXT1:
|
||||
memcpy(Lock.pBits,buffer,(width/4)*(height/4)*8);
|
||||
break;
|
||||
}
|
||||
pTexture->UnlockRect(level);
|
||||
}
|
||||
|
||||
LPDIRECT3DTEXTURE9 CreateRenderTarget(const int width, const int height)
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 tex;
|
||||
HRESULT hr = dev->CreateTexture(width,height,0,D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP,D3DFMT_A8R8G8B8,D3DPOOL_DEFAULT,&tex,NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
return 0;
|
||||
else
|
||||
return tex;
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 CreateDepthStencilSurface(const int width, const int height)
|
||||
{
|
||||
LPDIRECT3DSURFACE9 surf;
|
||||
HRESULT hr = dev->CreateDepthStencilSurface(width,height,D3DFMT_D24S8,D3DMULTISAMPLE_NONE,0,0,&surf,0);
|
||||
|
||||
if (FAILED(hr))
|
||||
return 0;
|
||||
else
|
||||
return surf;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "D3DBase.h"
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//Simple box filter mipmap generator: should in theory be replaced with say a
|
||||
//gaussian or something, but even this makes textures look great, especially
|
||||
//with anisotropic filtering enabled
|
||||
void FilterDown(DWORD *buffer, int w, int h, const int pitch);
|
||||
// __________________________________________________________________________________________________
|
||||
// calls filterdown which will trash _pBuffer as temp storage for mips
|
||||
LPDIRECT3DTEXTURE9 CreateTexture2D(const BYTE* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt = D3DFMT_A8R8G8B8);
|
||||
void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const BYTE* buffer, const int width, const int height,const int pitch, D3DFORMAT fmt);
|
||||
LPDIRECT3DTEXTURE9 CreateRenderTarget(const int width, const int height);
|
||||
LPDIRECT3DSURFACE9 CreateDepthStencilSurface(const int width, const int height);
|
||||
}
|
||||
@@ -0,0 +1,316 @@
|
||||
#include "Common.h"
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "D3DUtil.h"
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
CD3DFont font;
|
||||
|
||||
#define MAX_NUM_VERTICES 50*6
|
||||
struct FONT2DVERTEX {
|
||||
float x,y,z;
|
||||
float rhw;
|
||||
int color;
|
||||
float tu, tv;
|
||||
};
|
||||
|
||||
#define D3DFVF_FONT2DVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
|
||||
#define D3DFVF_FONT3DVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_NORMAL|D3DFVF_TEX1)
|
||||
|
||||
inline FONT2DVERTEX InitFont2DVertex( float x, float y, DWORD color, float tu, float tv )
|
||||
{
|
||||
FONT2DVERTEX v; v.x=x; v.y=y; v.z=0; v.rhw=1.0f; v.color = color; v.tu = tu; v.tv = tv;
|
||||
return v;
|
||||
}
|
||||
|
||||
CD3DFont::CD3DFont()
|
||||
{
|
||||
m_pTexture = NULL;
|
||||
m_pVB = NULL;
|
||||
}
|
||||
|
||||
const int RS[6][2] =
|
||||
{
|
||||
{ D3DRS_ALPHABLENDENABLE, TRUE },
|
||||
{ D3DRS_SRCBLEND, D3DBLEND_SRCALPHA },
|
||||
{ D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA },
|
||||
{ D3DRS_CULLMODE, D3DCULL_NONE },
|
||||
{ D3DRS_ZENABLE, FALSE },
|
||||
{ D3DRS_FOGENABLE, FALSE },
|
||||
};
|
||||
const int TS[6][2] =
|
||||
{
|
||||
{D3DTSS_COLOROP, D3DTOP_MODULATE},
|
||||
{D3DTSS_COLORARG1, D3DTA_TEXTURE},
|
||||
{D3DTSS_COLORARG2, D3DTA_DIFFUSE },
|
||||
{D3DTSS_ALPHAOP, D3DTOP_MODULATE },
|
||||
{D3DTSS_ALPHAARG1, D3DTA_TEXTURE },
|
||||
{D3DTSS_ALPHAARG2, D3DTA_DIFFUSE },
|
||||
};
|
||||
|
||||
enum {m_dwTexWidth=512, m_dwTexHeight = 512};
|
||||
|
||||
int CD3DFont::Init()
|
||||
{
|
||||
int hr;
|
||||
m_fTextScale = 1.0f; // Draw fonts into texture without scaling
|
||||
// Create a new texture for the font
|
||||
hr = dev->CreateTexture( m_dwTexWidth, m_dwTexHeight, 1, 0, D3DFMT_A4R4G4B4, D3DPOOL_MANAGED, &m_pTexture, NULL );
|
||||
if( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
// Prepare to create a bitmap
|
||||
int *pBitmapBits;
|
||||
BITMAPINFO bmi;
|
||||
ZeroMemory( &bmi.bmiHeader, sizeof(BITMAPINFOHEADER) );
|
||||
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmi.bmiHeader.biWidth = (int)m_dwTexWidth;
|
||||
bmi.bmiHeader.biHeight = -(int)m_dwTexHeight;
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
bmi.bmiHeader.biBitCount = 32;
|
||||
|
||||
// Create a DC and a bitmap for the font
|
||||
HDC hDC = CreateCompatibleDC( NULL );
|
||||
HBITMAP hbmBitmap = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS,
|
||||
(VOID**)&pBitmapBits, NULL, 0 );
|
||||
SetMapMode( hDC, MM_TEXT );
|
||||
|
||||
// Create a font. By specifying ANTIALIASED_QUALITY, we might get an
|
||||
// antialiased font, but this is not guaranteed.
|
||||
// We definitely don't want to get it cleartype'd, anyway.
|
||||
int m_dwFontHeight = 36;
|
||||
|
||||
INT nHeight = -MulDiv( m_dwFontHeight, (INT)(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72 );
|
||||
int dwBold = FW_NORMAL; ///FW_BOLD
|
||||
HFONT hFont = CreateFont( nHeight, 0, 0, 0, dwBold, 0,
|
||||
FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
|
||||
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
|
||||
VARIABLE_PITCH, "Tahoma");
|
||||
|
||||
if (NULL == hFont)
|
||||
return E_FAIL;
|
||||
|
||||
HGDIOBJ hOldbmBitmap = SelectObject( hDC, hbmBitmap );
|
||||
HGDIOBJ hOldFont = SelectObject( hDC, hFont );
|
||||
|
||||
// Set text properties
|
||||
SetTextColor( hDC, 0xFFFFFF );
|
||||
SetBkColor ( hDC, 0 );
|
||||
SetTextAlign( hDC, TA_TOP );
|
||||
|
||||
// Loop through all printable character and output them to the bitmap..
|
||||
// Meanwhile, keep track of the corresponding tex coords for each character.
|
||||
int x = 0, y = 0;
|
||||
|
||||
char str[2] = "\0";
|
||||
SIZE size;
|
||||
|
||||
for( char c=0; c<127-32; c++ )
|
||||
{
|
||||
str[0] = c+32;
|
||||
GetTextExtentPoint32( hDC, str, 1, &size );
|
||||
|
||||
if( (int)(x+size.cx+1) > m_dwTexWidth )
|
||||
{
|
||||
x = 0;
|
||||
y += size.cy+1;
|
||||
}
|
||||
|
||||
ExtTextOut( hDC, x+1, y+0, ETO_OPAQUE | ETO_CLIPPED, NULL, str, 1, NULL );
|
||||
|
||||
m_fTexCoords[c][0] = ((float)(x+0))/m_dwTexWidth;
|
||||
m_fTexCoords[c][1] = ((float)(y+0))/m_dwTexHeight;
|
||||
m_fTexCoords[c][2] = ((float)(x+0+size.cx))/m_dwTexWidth;
|
||||
m_fTexCoords[c][3] = ((float)(y+0+size.cy))/m_dwTexHeight;
|
||||
|
||||
x += size.cx+3; //3 to avoid annoying ij conflict (part of the j ends up with the i)
|
||||
}
|
||||
|
||||
// Lock the surface and write the alpha values for the set pixels
|
||||
D3DLOCKED_RECT d3dlr;
|
||||
m_pTexture->LockRect( 0, &d3dlr, 0, 0 );
|
||||
unsigned short* pDst16 = (unsigned short*)d3dlr.pBits;
|
||||
int bAlpha; // 4-bit measure of pixel intensity
|
||||
|
||||
for( y=0; y < m_dwTexHeight; y++ )
|
||||
{
|
||||
for( x=0; x < m_dwTexWidth; x++ )
|
||||
{
|
||||
bAlpha = ((pBitmapBits[m_dwTexWidth*y + x] & 0xff) >> 4);
|
||||
*pDst16++ = (bAlpha << 12) | 0x0fff;
|
||||
}
|
||||
}
|
||||
|
||||
// Done updating texture, so clean up used objects
|
||||
m_pTexture->UnlockRect(0);
|
||||
|
||||
SelectObject( hDC, hOldbmBitmap );
|
||||
DeleteObject( hbmBitmap );
|
||||
|
||||
SelectObject( hDC, hOldFont );
|
||||
DeleteObject( hFont );
|
||||
|
||||
// Create vertex buffer for the letters
|
||||
if( FAILED( hr = dev->CreateVertexBuffer( MAX_NUM_VERTICES*sizeof(FONT2DVERTEX),
|
||||
D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0,
|
||||
D3DPOOL_DEFAULT, &m_pVB,NULL ) ) )
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
int CD3DFont::Shutdown()
|
||||
{
|
||||
SAFE_RELEASE( m_pVB );
|
||||
SAFE_RELEASE( m_pTexture );
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void CD3DFont::SetRenderStates()
|
||||
{
|
||||
for (int i=0; i<6; i++)
|
||||
dev->SetRenderState((_D3DRENDERSTATETYPE)RS[i][0],RS[i][1]);
|
||||
for (int i=0; i<6; i++)
|
||||
dev->SetTextureStageState(0,(_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]),TS[i][1]);
|
||||
}
|
||||
|
||||
int CD3DFont::DrawTextScaled( float x, float y, float fXScale, float fYScale, float spacing, int dwColor, const char* strText, bool center )
|
||||
{
|
||||
SetRenderStates();
|
||||
dev->SetTexture( 0, m_pTexture );
|
||||
dev->SetPixelShader(0);
|
||||
dev->SetVertexShader(0);
|
||||
dev->SetVertexDeclaration(0);
|
||||
dev->SetFVF( D3DFVF_FONT2DVERTEX );
|
||||
dev->SetStreamSource( 0, m_pVB, 0, sizeof(FONT2DVERTEX) );
|
||||
|
||||
float vpWidth = 1;
|
||||
float vpHeight = 1;
|
||||
|
||||
float sx = x*vpWidth-0.5f;
|
||||
float sy = y*vpHeight-0.5f;
|
||||
|
||||
float fStartX = sx;
|
||||
|
||||
float invLineHeight = 1.0f / (( m_fTexCoords[0][3] - m_fTexCoords[0][1] ) * m_dwTexHeight);
|
||||
// Fill vertex buffer
|
||||
FONT2DVERTEX* pVertices;
|
||||
int dwNumTriangles = 0L;
|
||||
m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
|
||||
|
||||
const char *oldstrText=strText;
|
||||
//First, let's measure the text
|
||||
float tw=0;
|
||||
float mx=0;
|
||||
float maxx=0;
|
||||
|
||||
while( *strText )
|
||||
{
|
||||
char c = *strText++;
|
||||
|
||||
if( c == ('\n') )
|
||||
mx=0;
|
||||
if( c < (' ') )
|
||||
continue;
|
||||
|
||||
float tx1 = m_fTexCoords[c-32][0];
|
||||
float tx2 = m_fTexCoords[c-32][2];
|
||||
|
||||
float w = (tx2-tx1)*m_dwTexWidth;
|
||||
w *= (fXScale*vpHeight)*invLineHeight;
|
||||
mx += w + spacing*fXScale*vpWidth;
|
||||
if (mx>maxx) maxx=mx;
|
||||
}
|
||||
|
||||
float offset=-maxx/2;
|
||||
strText=oldstrText;
|
||||
//Then let's draw it
|
||||
if (center)
|
||||
{
|
||||
sx+=offset;
|
||||
fStartX+=offset;
|
||||
}
|
||||
|
||||
float wScale=(fXScale*vpHeight)*invLineHeight;
|
||||
float hScale=(fYScale*vpHeight)*invLineHeight;
|
||||
|
||||
while( *strText )
|
||||
{
|
||||
char c = *strText++;
|
||||
|
||||
if( c == ('\n') )
|
||||
{
|
||||
sx = fStartX;
|
||||
sy += fYScale*vpHeight;
|
||||
}
|
||||
if( c < (' ') )
|
||||
continue;
|
||||
|
||||
c-=32;
|
||||
float tx1 = m_fTexCoords[c][0];
|
||||
float ty1 = m_fTexCoords[c][1];
|
||||
float tx2 = m_fTexCoords[c][2];
|
||||
float ty2 = m_fTexCoords[c][3];
|
||||
|
||||
float w = (tx2-tx1)*m_dwTexWidth;
|
||||
float h = (ty2-ty1)*m_dwTexHeight;
|
||||
|
||||
w *= wScale;
|
||||
h *= hScale;
|
||||
|
||||
|
||||
FONT2DVERTEX v[6];
|
||||
v[0]=InitFont2DVertex(sx, sy+h, dwColor, tx1, ty2);
|
||||
v[1]=InitFont2DVertex(sx, sy, dwColor, tx1, ty1);
|
||||
v[2]=InitFont2DVertex(sx+w, sy+h, dwColor, tx2, ty2);
|
||||
v[3]=InitFont2DVertex(sx+w, sy, dwColor, tx2, ty1);
|
||||
v[4]=v[2];
|
||||
v[5]=v[1];
|
||||
|
||||
memcpy(pVertices,v,6*sizeof(FONT2DVERTEX));
|
||||
|
||||
pVertices+=6;
|
||||
dwNumTriangles += 2;
|
||||
|
||||
if( dwNumTriangles*3 > (MAX_NUM_VERTICES-6) )
|
||||
{
|
||||
// Unlock, render, and relock the vertex buffer
|
||||
m_pVB->Unlock();
|
||||
dev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
|
||||
m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
|
||||
dwNumTriangles = 0;
|
||||
}
|
||||
|
||||
sx += w + spacing*fXScale*vpWidth;
|
||||
}
|
||||
|
||||
// Unlock and render the vertex buffer
|
||||
m_pVB->Unlock();
|
||||
if( dwNumTriangles > 0 )
|
||||
dev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
|
||||
|
||||
dev->SetRenderState(D3DRS_ZENABLE,TRUE);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void quad2d(float x1, float y1, float x2, float y2, DWORD color, float u1, float v1, float u2, float v2)
|
||||
{
|
||||
struct Q2DVertex { float x,y,z,rhw; int color; float u, v; } coords[4] = {
|
||||
{x1-0.5f, y1-0.5f, 0, 1, color, u1, v1},
|
||||
{x2-0.5f, y1-0.5f, 0, 1, color, u2, v1},
|
||||
{x2-0.5f, y2-0.5f, 0, 1, color, u2, v2},
|
||||
{x1-0.5f, y2-0.5f, 0, 1, color, u1, v2},
|
||||
};
|
||||
dev->SetPixelShader(0);
|
||||
dev->SetVertexShader(0);
|
||||
dev->SetVertexDeclaration(0);
|
||||
dev->SetFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1);
|
||||
dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,coords,sizeof(Q2DVertex));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include "D3DBase.h"
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
// Font creation flags
|
||||
#define D3DFONT_BOLD 0x0001
|
||||
#define D3DFONT_ITALIC 0x0002
|
||||
|
||||
// Font rendering flags
|
||||
#define D3DFONT_CENTERED 0x0001
|
||||
|
||||
//a cut-down variant of the DXSDK CD3DFont class
|
||||
class CD3DFont
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 m_pTexture; // The d3d texture for this font
|
||||
LPDIRECT3DVERTEXBUFFER9 m_pVB; // VertexBuffer for rendering text
|
||||
//int m_dwTexWidth; // Texture dimensions
|
||||
//int m_dwTexHeight;
|
||||
float m_fTextScale;
|
||||
float m_fTexCoords[128-32][4];
|
||||
|
||||
public:
|
||||
CD3DFont();
|
||||
// 2D (no longer 3D) text drawing function
|
||||
// Initializing and destroying device-dependent objects
|
||||
void SetRenderStates();
|
||||
int Init();
|
||||
int Shutdown();
|
||||
int DrawTextScaled( float x, float y,
|
||||
float fXScale, float fYScale,
|
||||
float spacing, int dwColor,
|
||||
const char* strText, bool center=true );
|
||||
|
||||
|
||||
// Constructor / destructor
|
||||
//~CD3DFont();
|
||||
};
|
||||
|
||||
extern CD3DFont font;
|
||||
|
||||
void quad2d(float x1, float y1, float x2, float y2, DWORD color, float u1=0, float v1=0, float u2=1, float v2=1);
|
||||
}
|
||||
@@ -0,0 +1,468 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#if 0
|
||||
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "VertexHandler.h"
|
||||
#include "DataReader.h"
|
||||
#include "BPStructs.h"
|
||||
#include "CPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
#include "DLCompiler.h"
|
||||
#include "x86.h"
|
||||
#include "main.h"
|
||||
#include "Utils.h"
|
||||
|
||||
CompiledDList::CompiledDList(u32 _addr, u32 _size)
|
||||
{
|
||||
dataSize = 0;
|
||||
data = 0;
|
||||
code = 0;
|
||||
addr = _addr;
|
||||
size = _size;
|
||||
pass = 0;
|
||||
numBatches = 0;
|
||||
batches = 0;
|
||||
}
|
||||
|
||||
CompiledDList::~CompiledDList()
|
||||
{
|
||||
if (data)
|
||||
delete [] data;
|
||||
if (code)
|
||||
delete [] code;
|
||||
if (batches)
|
||||
delete [] batches;
|
||||
}
|
||||
|
||||
|
||||
bool CompiledDList::Call()
|
||||
{
|
||||
switch(pass) {
|
||||
case 0: // First compiling pass : find data size
|
||||
if (Pass1())
|
||||
{
|
||||
pass = 1;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
case 1: // Second compiling pass : actually compile
|
||||
//if pass1 succeeded, pass2 will too
|
||||
Pass2();
|
||||
pass = 2;
|
||||
return true;
|
||||
case 2: // Run pass - we have a compiled dlist, just call it
|
||||
Run();
|
||||
return true;
|
||||
default:
|
||||
//ERROR
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CompiledDList::Pass1()
|
||||
{
|
||||
/* //find the size of code + data, if the dlist is worth recompiling etc
|
||||
// at the same time, do the ordinary stuff
|
||||
g_pDataReader = &dlistReader;
|
||||
OpcodeReaders::SetDListReader(addr, addr+size);
|
||||
dataSize = 0;
|
||||
codeSize = 0;
|
||||
numBatches = 0;
|
||||
bool lastIsPrim = false;
|
||||
while (OpcodeReaders::IsDListOKToRead())
|
||||
{
|
||||
int Cmd = g_pDataReader->Read8();
|
||||
switch(Cmd)
|
||||
{
|
||||
case GX_LOAD_CP_REG: //0x08
|
||||
{
|
||||
u32 SubCmd = g_pDataReader->Read8();
|
||||
u32 Value = g_pDataReader->Read32();
|
||||
LoadCPReg(SubCmd,Value);
|
||||
//COMPILER
|
||||
codeSize+=13;
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
u32 Cmd2 = g_pDataReader->Read32();
|
||||
int dwTransferSize = ((Cmd2>>16)&15) + 1;
|
||||
DWORD dwAddress = Cmd2 & 0xFFFF;
|
||||
static u32 pData[16];
|
||||
for (int i=0; i<dwTransferSize; i++)
|
||||
pData[i] = g_pDataReader->Read32();
|
||||
LoadXFReg(dwTransferSize,dwAddress,pData);
|
||||
//COMPILER
|
||||
dataSize+=dwTransferSize;
|
||||
codeSize+=17;
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
{
|
||||
u32 cmd=g_pDataReader->Read32();
|
||||
LoadBPReg(cmd);
|
||||
codeSize+=9;
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A: //used for position matrices
|
||||
LoadIndexedXF(g_pDataReader->Read32(),0xC);
|
||||
codeSize+=13;
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //used for normal matrices
|
||||
LoadIndexedXF(g_pDataReader->Read32(),0xD);
|
||||
codeSize+=13;
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //used for postmatrices
|
||||
LoadIndexedXF(g_pDataReader->Read32(),0xE);
|
||||
codeSize+=13;
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //used for lights
|
||||
LoadIndexedXF(g_pDataReader->Read32(),0xF);
|
||||
codeSize+=13;
|
||||
break;
|
||||
|
||||
case GX_CMD_CALL_DL:
|
||||
MessageBox(0,"Display lists can't recurse!!","error",0);
|
||||
break;
|
||||
|
||||
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
|
||||
break;
|
||||
case GX_NOP:
|
||||
break;
|
||||
default:
|
||||
if (Cmd&0x80)
|
||||
{
|
||||
int primitive = (Cmd&GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
|
||||
if (lastIsPrim)
|
||||
{
|
||||
//join to last
|
||||
}
|
||||
else
|
||||
{
|
||||
//finish up last and commit
|
||||
}
|
||||
u16 numVertices = g_pDataReader->Read16();
|
||||
tempvarray.Reset();
|
||||
VertexLoader::SetVArray(&tempvarray);
|
||||
VertexLoader *loader = &VertexLoader[Cmd&GX_VAT_MASK];
|
||||
loader->Setup();
|
||||
loader->PrepareRun();
|
||||
int vsize = loader->GetVertexSize();
|
||||
loader->RunVertices(numVertices);
|
||||
CVertexHandler::DrawVertices(primitive, numVertices, &tempvarray);
|
||||
CVertexHandler::Flush();
|
||||
//COMPILER
|
||||
codeSize+=21;
|
||||
numBatches++;
|
||||
lastIsPrim = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lastIsPrim)
|
||||
{
|
||||
//finish up last and commit
|
||||
}
|
||||
codeSize*=2;*/
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CompiledDList::Pass2()
|
||||
{
|
||||
/* OpcodeReaders::SetDListReader(addr, addr+size);
|
||||
|
||||
data = new u32[dataSize];
|
||||
code = new u8[codeSize]; //at least
|
||||
|
||||
batches = new Batch[numBatches];
|
||||
int batchCount = 0;
|
||||
u32 *dataptr = data;
|
||||
|
||||
x86Init();
|
||||
x86SetPtr((s8*)code);
|
||||
//WC8(0xCC);
|
||||
|
||||
//actually do the recompiling, emit code and data, protect the memory
|
||||
// but again, at the same time do the ordinary stuff
|
||||
// so the compiled display list won't be run until the third time actually
|
||||
bool dump = false,lastIsGeom=false;
|
||||
FILE *f;
|
||||
|
||||
#ifndef TEASER
|
||||
if (dump)
|
||||
{
|
||||
f=fopen("D:\\dlistlogs.txt","a");
|
||||
fprintf(f,"===========================================\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
while (OpcodeReaders::IsDListOKToRead())
|
||||
{
|
||||
int Cmd = g_pDataReader->Read8();
|
||||
switch(Cmd)
|
||||
{
|
||||
case GX_LOAD_CP_REG: //0x08
|
||||
{
|
||||
lastIsGeom = false;
|
||||
u32 SubCmd = g_pDataReader->Read8();
|
||||
u32 Value = g_pDataReader->Read32();
|
||||
if (dump)
|
||||
fprintf(f,"CP | %02x %08x\n",SubCmd,Value);
|
||||
|
||||
LoadCPReg(SubCmd,Value);
|
||||
//COMPILER
|
||||
PUSH_WordToStack(Value);
|
||||
PUSH_WordToStack(SubCmd);
|
||||
CALLFunc((u32)LoadCPReg);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
lastIsGeom = false;
|
||||
u32 Cmd2 = g_pDataReader->Read32();
|
||||
int dwTransferSize = ((Cmd2>>16)&15) + 1;
|
||||
u32 dwAddress = Cmd2 & 0xFFFF;
|
||||
static u32 pData[16];
|
||||
|
||||
u32 *oldDataPtr = dataptr;
|
||||
|
||||
if (dump)
|
||||
{
|
||||
fprintf(f,"XF | %01xx %04x\n",dwTransferSize,dwAddress);
|
||||
for (int i=0; i<dwTransferSize; i++)
|
||||
fprintf(f, "%08x | %f\n",oldDataPtr[i], *((float*)oldDataPtr+i));
|
||||
}
|
||||
|
||||
|
||||
for (int i=0; i<dwTransferSize; i++) // a little compiler here too
|
||||
*dataptr++ = g_pDataReader->Read32();
|
||||
|
||||
|
||||
LoadXFReg(dwTransferSize,dwAddress,oldDataPtr);
|
||||
|
||||
//COMPILER
|
||||
PUSH_WordToStack((u32)oldDataPtr);
|
||||
PUSH_WordToStack(dwAddress);
|
||||
PUSH_WordToStack(dwTransferSize);
|
||||
CALLFunc((u32)LoadXFReg);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
{
|
||||
lastIsGeom = false;
|
||||
u32 cmd=g_pDataReader->Read32();
|
||||
if (dump)
|
||||
fprintf(f,"BP | %08x\n",cmd);
|
||||
|
||||
LoadBPReg(cmd);
|
||||
//COMPILER
|
||||
PUSH_WordToStack(cmd);
|
||||
CALLFunc((u32)LoadBPReg);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A: //usually used for position matrices
|
||||
{
|
||||
lastIsGeom = false;
|
||||
u32 value = g_pDataReader->Read32();
|
||||
LoadIndexedXF(value,0xC);
|
||||
//COMPILER
|
||||
PUSH_WordToStack(0xC);
|
||||
PUSH_WordToStack(value);
|
||||
CALLFunc((u32)LoadIndexedXF);
|
||||
if (dump)
|
||||
fprintf(f,"LOADINDEXA | pos matrix\n");
|
||||
}
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //usually used for normal matrices
|
||||
{
|
||||
lastIsGeom = false;
|
||||
u32 value = g_pDataReader->Read32();
|
||||
LoadIndexedXF(value,0xD);
|
||||
//COMPILER
|
||||
PUSH_WordToStack(0xD);
|
||||
PUSH_WordToStack(value);
|
||||
CALLFunc((u32)LoadIndexedXF);
|
||||
if (dump)
|
||||
fprintf(f,"LOADINDEXB | nrm matrix\n");
|
||||
}
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //usually used for postmatrices
|
||||
{
|
||||
lastIsGeom = false;
|
||||
u32 value = g_pDataReader->Read32();
|
||||
LoadIndexedXF(value,0xE);
|
||||
//COMPILER
|
||||
PUSH_WordToStack(0xE);
|
||||
PUSH_WordToStack(value);
|
||||
CALLFunc((u32)LoadIndexedXF);
|
||||
if (dump)
|
||||
fprintf(f,"LOADINDEXC | post matrix\n");
|
||||
}
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //usually used for lights
|
||||
{
|
||||
lastIsGeom = false;
|
||||
u32 value = g_pDataReader->Read32();
|
||||
LoadIndexedXF(value,0xF);
|
||||
//COMPILER
|
||||
PUSH_WordToStack(0xF);
|
||||
PUSH_WordToStack(value);
|
||||
CALLFunc((u32)LoadIndexedXF);
|
||||
if (dump)
|
||||
fprintf(f,"LOADINDEXD | light\n");
|
||||
}
|
||||
break;
|
||||
case GX_CMD_CALL_DL:
|
||||
// ERORRR
|
||||
break;
|
||||
|
||||
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
|
||||
if (dump)
|
||||
fprintf(f,"invalidate vc\n");
|
||||
break;
|
||||
case GX_NOP:
|
||||
if (dump)
|
||||
fprintf(f,"nop\n");
|
||||
break;
|
||||
default:
|
||||
if (Cmd&0x80)
|
||||
{
|
||||
int primitive = (Cmd&GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
|
||||
//if (lastIsGeom) INCSTAT(stats.numJoins);
|
||||
u16 numVertices = g_pDataReader->Read16();
|
||||
if (dump)
|
||||
fprintf(f,"DP: prim=%02x numv=%i\n",primitive,numVertices);
|
||||
DecodedVArray &va = batches[batchCount].varray;
|
||||
|
||||
VertexLoader *loader = &VertexLoader[Cmd&GX_VAT_MASK];
|
||||
TVtxDesc &vd = loader->GetVtxDesc();
|
||||
|
||||
VertexLoader::SetVArray(&va);
|
||||
loader->Setup();
|
||||
loader->PrepareRun();
|
||||
// va.numColors = loader->GetNumColors();
|
||||
// va.numUVs = loader->GetNumTCs();
|
||||
// va.numNormals = loader->GetNumNormals();
|
||||
//va.num
|
||||
va.Create(numVertices,vd.PosMatIdx,
|
||||
vd.Tex0MatIdx+vd.Tex1MatIdx+vd.Tex2MatIdx+vd.Tex3MatIdx+
|
||||
vd.Tex4MatIdx+vd.Tex5MatIdx+vd.Tex6MatIdx+vd.Tex7MatIdx,
|
||||
va.numNormals, va.numColors, va.numTCs);
|
||||
|
||||
int vsize = loader->GetVertexSize();
|
||||
loader->RunVertices(numVertices);
|
||||
CVertexHandler::DrawVertices(primitive, numVertices, &va);
|
||||
CVertexHandler::Flush();
|
||||
// YES we have now filled our varray
|
||||
//LETS COMPILE
|
||||
PUSH_WordToStack(primitive);
|
||||
PUSH_WordToStack(batchCount);
|
||||
PUSH_WordToStack((u32)this);
|
||||
CALLFunc((u32)DrawHelperHelper);
|
||||
batchCount++;
|
||||
lastIsGeom = true;
|
||||
if (dump)
|
||||
fprintf(f,"DRAW PRIMITIVE: prim=%02x numv=%i\n",primitive,numVertices);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dump)
|
||||
{
|
||||
fprintf(f,"***************************************\n\n\n");
|
||||
}
|
||||
RET();
|
||||
if (dump)
|
||||
fclose(f);*/
|
||||
//we're done, next time just kick the compiled list off, much much faster than interpreting!
|
||||
}
|
||||
|
||||
void CompiledDList::DrawHelperHelper(CompiledDList *dl, int vno, int prim)
|
||||
{
|
||||
Batch &b = dl->batches[vno];
|
||||
CVertexHandler::DrawVertices(prim, b.varray.GetSize(), &b.varray);
|
||||
}
|
||||
|
||||
void CompiledDList::Run()
|
||||
{
|
||||
//run the code
|
||||
((void (*)())(code))();
|
||||
CVertexHandler::Flush();
|
||||
}
|
||||
|
||||
DListCache::DLCache DListCache::dlists;
|
||||
|
||||
|
||||
|
||||
void DListCache::Init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void DListCache::Shutdown()
|
||||
{
|
||||
DLCache::iterator iter = dlists.begin();
|
||||
for (;iter!=dlists.end();iter++)
|
||||
iter->second.Destroy();
|
||||
dlists.clear();
|
||||
}
|
||||
|
||||
|
||||
void DListCache::Call(u32 _addr, u32 _size)
|
||||
{
|
||||
DLCache::iterator iter;
|
||||
iter = dlists.find(_addr);
|
||||
|
||||
if (iter != dlists.end())
|
||||
{
|
||||
if (iter->second.size == _size)
|
||||
{
|
||||
iter->second.dlist->Call();
|
||||
return;
|
||||
}
|
||||
else // wrong size, need to recompile
|
||||
{
|
||||
iter->second.Destroy();
|
||||
iter=dlists.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
//Make an entry in the table
|
||||
DLCacheEntry entry;
|
||||
entry.dlist = new CompiledDList(_addr, _size);
|
||||
entry.dlist->Call();
|
||||
entry.frameCount = frameCount;
|
||||
entry.size = _size;
|
||||
dlists[_addr] = entry;
|
||||
|
||||
INCSTAT(stats.numDListsCreated);
|
||||
SETSTAT(stats.numDListsAlive,(int)dlists.size());
|
||||
}
|
||||
|
||||
void DListCache::Cleanup()
|
||||
{
|
||||
for (DLCache::iterator iter=dlists.begin(); iter!=dlists.end();iter++)
|
||||
{
|
||||
DLCacheEntry &entry = iter->second;
|
||||
if (entry.frameCount<frameCount-80)
|
||||
{
|
||||
entry.Destroy();
|
||||
iter = dlists.erase(iter);
|
||||
}
|
||||
}
|
||||
SETSTAT(stats.numDListsAlive,(int)dlists.size());
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#if 0
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "DecodedVArray.h"
|
||||
#include <map>
|
||||
|
||||
|
||||
class CompiledDList
|
||||
{
|
||||
u32 *data;
|
||||
int dataSize;
|
||||
int pass;
|
||||
int codeSize;
|
||||
u8 *code;
|
||||
|
||||
struct Batch
|
||||
{
|
||||
DecodedVArray varray;
|
||||
LPDIRECT3DINDEXBUFFER9 ibuffer;
|
||||
int numDraws;
|
||||
};
|
||||
Batch *batches;
|
||||
int numBatches;
|
||||
|
||||
u32 addr, size;
|
||||
bool Compile();
|
||||
bool Pass1();
|
||||
void Pass2();
|
||||
void Run();
|
||||
|
||||
public:
|
||||
CompiledDList(u32 _addr, u32 _size);
|
||||
~CompiledDList();
|
||||
bool Call();
|
||||
static void DrawHelperHelper(CompiledDList *dl, int vno, int prim);
|
||||
};
|
||||
|
||||
class DListCache
|
||||
{
|
||||
struct DLCacheEntry
|
||||
{
|
||||
CompiledDList *dlist;
|
||||
int frameCount;
|
||||
int pass;
|
||||
u32 size;
|
||||
DLCacheEntry()
|
||||
{
|
||||
pass=0;
|
||||
dlist=0;
|
||||
frameCount=0;
|
||||
}
|
||||
void Destroy()
|
||||
{
|
||||
if (dlist)
|
||||
delete dlist;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<DWORD,DLCacheEntry> DLCache;
|
||||
|
||||
static DLCache dlists;
|
||||
|
||||
public:
|
||||
static void Init();
|
||||
static void Cleanup();
|
||||
static void Shutdown();
|
||||
static void Call(u32 _addr, u32 _size);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,74 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "Utils.h"
|
||||
#include "Common.h"
|
||||
#include "main.h"
|
||||
#include "DataReader.h"
|
||||
|
||||
// =================================================================================================
|
||||
// CDataReader_Fifo
|
||||
// =================================================================================================
|
||||
|
||||
IDataReader* g_pDataReader = NULL;
|
||||
extern u8 FAKE_ReadFifo8();
|
||||
extern u16 FAKE_ReadFifo16();
|
||||
extern u32 FAKE_ReadFifo32();
|
||||
|
||||
CDataReader_Fifo::CDataReader_Fifo(void)
|
||||
{
|
||||
m_szName = "CDataReader_Fifo";
|
||||
}
|
||||
|
||||
u8 CDataReader_Fifo::Read8(void)
|
||||
{
|
||||
return FAKE_ReadFifo8();
|
||||
};
|
||||
|
||||
u16 CDataReader_Fifo::Read16(void)
|
||||
{
|
||||
return FAKE_ReadFifo16();
|
||||
};
|
||||
|
||||
u32 CDataReader_Fifo::Read32(void)
|
||||
{
|
||||
return FAKE_ReadFifo32();
|
||||
};
|
||||
|
||||
// =================================================================================================
|
||||
// CDataReader_Memory
|
||||
// =================================================================================================
|
||||
|
||||
CDataReader_Memory::CDataReader_Memory(u32 _uAddress) :
|
||||
m_uReadAddress(_uAddress)
|
||||
{
|
||||
// F|RES: this wont work anymore caused by Mem2
|
||||
|
||||
// m_pMemory = g_VideoInitialize.pGetMemoryPointer(0x00);
|
||||
m_szName = "CDataReader_Memory";
|
||||
}
|
||||
|
||||
u32 CDataReader_Memory::GetReadAddress(void)
|
||||
{
|
||||
return m_uReadAddress;
|
||||
}
|
||||
|
||||
u8 CDataReader_Memory::Read8(void)
|
||||
{
|
||||
u8 tmp = Memory_Read_U8(m_uReadAddress); //m_pMemory[m_uReadAddress];
|
||||
m_uReadAddress++;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
u16 CDataReader_Memory::Read16(void)
|
||||
{
|
||||
u16 tmp = Memory_Read_U16(m_uReadAddress); //_byteswap_ushort(*(u16*)&m_pMemory[m_uReadAddress]);
|
||||
m_uReadAddress += 2;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
u32 CDataReader_Memory::Read32(void)
|
||||
{
|
||||
u32 tmp =Memory_Read_U32(m_uReadAddress); // _byteswap_ulong(*(u32*)&m_pMemory[m_uReadAddress]);
|
||||
m_uReadAddress += 4;
|
||||
return tmp;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
#ifndef _DATAREADER_H
|
||||
#define _DATAREADER_H
|
||||
|
||||
// =================================================================================================
|
||||
// IDataReader
|
||||
// =================================================================================================
|
||||
|
||||
class IDataReader
|
||||
{
|
||||
protected:
|
||||
const char *m_szName;
|
||||
|
||||
public:
|
||||
virtual u8 Read8 (void) = NULL;
|
||||
virtual u16 Read16(void) = NULL;
|
||||
virtual u32 Read32(void) = NULL;
|
||||
};
|
||||
|
||||
// =================================================================================================
|
||||
// CDataReader_Fifo
|
||||
// =================================================================================================
|
||||
|
||||
class CDataReader_Fifo : public IDataReader
|
||||
{
|
||||
private:
|
||||
|
||||
public:
|
||||
CDataReader_Fifo(void);
|
||||
|
||||
virtual u8 Read8(void);
|
||||
virtual u16 Read16(void);
|
||||
virtual u32 Read32(void);
|
||||
};
|
||||
|
||||
// =================================================================================================
|
||||
// CDataReader_Memory
|
||||
// =================================================================================================
|
||||
|
||||
class CDataReader_Memory : public IDataReader
|
||||
{
|
||||
private:
|
||||
|
||||
// u8* m_pMemory;
|
||||
u32 m_uReadAddress;
|
||||
|
||||
public:
|
||||
|
||||
CDataReader_Memory(u32 _uAddress);
|
||||
|
||||
u32 GetReadAddress(void);
|
||||
|
||||
virtual u8 Read8(void);
|
||||
virtual u16 Read16(void);
|
||||
virtual u32 Read32(void);
|
||||
};
|
||||
|
||||
extern IDataReader* g_pDataReader;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,75 @@
|
||||
#include "stdafx.h"
|
||||
#include "DecodedVArray.h"
|
||||
|
||||
#include "main.h"
|
||||
|
||||
DecodedVArray::DecodedVArray()
|
||||
{
|
||||
Zero();
|
||||
}
|
||||
|
||||
DecodedVArray::~DecodedVArray()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void DecodedVArray::Zero()
|
||||
{
|
||||
size = 0;
|
||||
count = 0;
|
||||
components = 0;
|
||||
positions = 0;
|
||||
posMtxInds = 0;
|
||||
for (int i=0; i<3; i++)
|
||||
normals[i] = 0;
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
texMtxInds[i] = 0;
|
||||
uvs[i] = 0;
|
||||
}
|
||||
for (int i=0; i<2; i++)
|
||||
colors[i] = 0;
|
||||
}
|
||||
|
||||
void DecodedVArray::Destroy()
|
||||
{
|
||||
//,,
|
||||
delete [] positions;
|
||||
delete [] posMtxInds;
|
||||
for (int i=0; i<3; i++)
|
||||
delete [] normals[i];
|
||||
for (int i=0; i<2; i++)
|
||||
delete [] colors[i];
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
delete [] uvs[i];
|
||||
delete [] texMtxInds[i];
|
||||
}
|
||||
Zero();
|
||||
}
|
||||
|
||||
void DecodedVArray::Create(int _size, int pmcount, int tmcount, int nrmcount, int colcount, int tccount)
|
||||
{
|
||||
size = _size;
|
||||
// position matrix indices
|
||||
if (pmcount)
|
||||
posMtxInds = new DecMtxInd[size];
|
||||
// texture matrix indices
|
||||
if (tmcount)
|
||||
for (int i=0; i<tmcount; i++)
|
||||
texMtxInds[i] = new DecMtxInd[size];
|
||||
// positions (always)
|
||||
positions = new DecPos[size];
|
||||
// normals
|
||||
if (nrmcount)
|
||||
for (int i=0; i<nrmcount; i++)
|
||||
normals[i] = new DecNormal[size];
|
||||
// colors
|
||||
if (colcount)
|
||||
for (int i=0; i<colcount; i++)
|
||||
colors[i] = new DecColor[size];
|
||||
|
||||
if (tccount)
|
||||
for (int i=0; i<tccount; i++)
|
||||
uvs[i] = new DecUV[size];
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
#ifndef _DECODED_VARRAY_H
|
||||
#define _DECODED_VARRAY_H
|
||||
|
||||
#include "Vec3.h"
|
||||
#include "Common.h"
|
||||
|
||||
typedef Vec3 DecPos;
|
||||
typedef Vec3 DecNormal;
|
||||
|
||||
struct DecUV
|
||||
{
|
||||
float u,v;
|
||||
};
|
||||
|
||||
typedef u32 DecColor;
|
||||
typedef u8 DecMtxInd;
|
||||
|
||||
int ComputeVertexSize(u32 components);
|
||||
|
||||
//TODO(ector): Change the internal implementation to pack it tight according to components
|
||||
// The tight packing will be fed directly to the gfx card in the mystic future.
|
||||
class DecodedVArray
|
||||
{
|
||||
int size;
|
||||
u32 components;
|
||||
int vertexSize;
|
||||
|
||||
public:
|
||||
int count;
|
||||
DecodedVArray();
|
||||
~DecodedVArray();
|
||||
void SetComponents(u32 comps) {components = comps; vertexSize=ComputeVertexSize(components);}
|
||||
u32 GetComponents() const {return components;}
|
||||
void Create(int _size, int pmcount, int tmcount, int nrmcount, int colcount, int tccount);
|
||||
void Zero();
|
||||
void Destroy();
|
||||
void Reset() {count=0;}
|
||||
int GetSize() {return size;}
|
||||
int GetCount() {return count;}
|
||||
void Next() {count++;}
|
||||
void SetPosNrmIdx(int i) {posMtxInds[count] = i;}
|
||||
void SetTcIdx(int n, int i) {texMtxInds[n][count] = i;}
|
||||
void SetPosX(float x) {positions[count].x=x;}
|
||||
void SetPosY(float y) {positions[count].y=y;}
|
||||
void SetPosZ(float z) {positions[count].z=z;}
|
||||
|
||||
void SetNormalX(int n,float x) {normals[n][count].x=x;}
|
||||
void SetNormalY(int n,float y) {normals[n][count].y=y;}
|
||||
void SetNormalZ(int n,float z) {normals[n][count].z=z;}
|
||||
void SetU(int n, float u) {uvs[n][count].u = u;}
|
||||
void SetV(int n, float v) {uvs[n][count].v = v;}
|
||||
void SetPosition(float x, float y, float z) {
|
||||
positions[count].x=x;
|
||||
positions[count].y=y;
|
||||
positions[count].z=z;
|
||||
}
|
||||
void SetNormal(int n, float x, float y, float z) {
|
||||
normals[n][count].x=x;
|
||||
normals[n][count].y=y;
|
||||
normals[n][count].z=z;
|
||||
}
|
||||
void SetColor(int n, u32 c)
|
||||
{
|
||||
colors[n][count] = c;
|
||||
}
|
||||
void SetUV(int n, float u, float v) {
|
||||
uvs[n][count].u=u;
|
||||
uvs[n][count].v=v;
|
||||
}
|
||||
const DecPos &GetPos(int n) const { return positions[n]; }
|
||||
const DecNormal &GetNormal(int i, int n) const { return normals[i][n]; }
|
||||
const DecColor &GetColor(int i, int n) const { return colors[i][n]; }
|
||||
const DecUV &GetUV(int i, int n) const { return uvs[i][n]; }
|
||||
const DecMtxInd &GetPosMtxInd(int n) const { return posMtxInds[n]; }
|
||||
const DecMtxInd &GetTexMtxInd(int i, int n) const { return texMtxInds[i][n]; }
|
||||
//private:
|
||||
DecPos *positions;
|
||||
DecNormal *normals[3];
|
||||
DecColor *colors[2];
|
||||
DecUV *uvs[8];
|
||||
DecMtxInd *posMtxInds;
|
||||
DecMtxInd *texMtxInds[8];
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,203 @@
|
||||
#include <windowsx.h>
|
||||
|
||||
#include "resource.h"
|
||||
#include "W32Util/PropertySheet.h"
|
||||
#include "W32Util/ShellUtil.h"
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "D3DPostprocess.h"
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
#define NUMWNDRES 6
|
||||
int g_Res[NUMWNDRES][2] =
|
||||
{
|
||||
{640,480},
|
||||
{800,600},
|
||||
{1024,768},
|
||||
{1280,960},
|
||||
{1280,1024},
|
||||
{1600,1200},
|
||||
};
|
||||
|
||||
struct TabDirect3D : public W32Util::Tab
|
||||
{
|
||||
void Init(HWND hDlg)
|
||||
{
|
||||
for (int i=0; i<D3D::GetNumAdapters(); i++)
|
||||
{
|
||||
const D3D::Adapter &adapter = D3D::GetAdapter(i);
|
||||
ComboBox_AddString(GetDlgItem(hDlg,IDC_ADAPTER),adapter.ident.Description);
|
||||
}
|
||||
|
||||
const D3D::Adapter &adapter = D3D::GetAdapter(g_Config.iAdapter);
|
||||
|
||||
ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_ADAPTER),g_Config.iAdapter);
|
||||
|
||||
for (int i = 0; i < (int)adapter.aa_levels.size(); i++)
|
||||
{
|
||||
ComboBox_AddString(GetDlgItem(hDlg, IDC_ANTIALIASMODE), adapter.aa_levels[i].name);
|
||||
}
|
||||
|
||||
ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_ANTIALIASMODE), g_Config.iMultisampleMode);
|
||||
if (adapter.aa_levels.size() == 1)
|
||||
{
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_ANTIALIASMODE), FALSE);
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)adapter.resolutions.size(); i++)
|
||||
{
|
||||
const D3D::Resolution &r = adapter.resolutions[i];
|
||||
ComboBox_AddString(GetDlgItem(hDlg,IDC_RESOLUTION), r.name);
|
||||
}
|
||||
ComboBox_SetCurSel(GetDlgItem(hDlg,IDC_RESOLUTION), g_Config.iFSResolution);
|
||||
|
||||
for (int i = 0; i < NUMWNDRES; i++)
|
||||
{
|
||||
char temp[256];
|
||||
sprintf(temp,"%ix%i",g_Res[i][0],g_Res[i][1]);
|
||||
ComboBox_AddString(GetDlgItem(hDlg,IDC_RESOLUTIONWINDOWED),temp);
|
||||
}
|
||||
ComboBox_SetCurSel(GetDlgItem(hDlg,IDC_RESOLUTIONWINDOWED),g_Config.iWindowedRes);
|
||||
|
||||
CheckDlgButton(hDlg, IDC_FULLSCREENENABLE, g_Config.bFullscreen ? TRUE : FALSE);
|
||||
CheckDlgButton(hDlg, IDC_VSYNC, g_Config.bVsync ? TRUE : FALSE);
|
||||
}
|
||||
|
||||
void Command(HWND hDlg,WPARAM wParam)
|
||||
{
|
||||
/*
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Apply(HWND hDlg)
|
||||
{
|
||||
g_Config.iAdapter = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_ADAPTER));
|
||||
g_Config.iWindowedRes = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_RESOLUTIONWINDOWED));
|
||||
g_Config.iMultisampleMode = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_ANTIALIASMODE));
|
||||
g_Config.iFSResolution = ComboBox_GetCurSel(GetDlgItem(hDlg,IDC_RESOLUTION));
|
||||
g_Config.bFullscreen = Button_GetCheck(GetDlgItem(hDlg, IDC_FULLSCREENENABLE)) ? true : false;
|
||||
g_Config.bVsync = Button_GetCheck(GetDlgItem(hDlg, IDC_VSYNC)) ? true : false;
|
||||
}
|
||||
};
|
||||
|
||||
struct TabAdvanced : public W32Util::Tab
|
||||
{
|
||||
void Init(HWND hDlg)
|
||||
{
|
||||
HWND opt = GetDlgItem(hDlg,IDC_DLOPTLEVEL);
|
||||
ComboBox_AddString(opt,"0: Interpret (slowest, most compatible)");
|
||||
ComboBox_AddString(opt,"1: Compile lists and decode vertex lists");
|
||||
//ComboBox_AddString(opt,"2: Compile+decode to vbufs and use hw xform");
|
||||
//ComboBox_AddString(opt,"Recompile to vbuffers and shaders");
|
||||
ComboBox_SetCurSel(opt,g_Config.iCompileDLsLevel);
|
||||
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_OVERLAYSTATS), g_Config.bOverlayStats);
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_WIREFRAME), g_Config.bWireFrame);
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_TEXDUMP), g_Config.bDumpTextures);
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_SHOWSHADERERRORS), g_Config.bShowShaderErrors);
|
||||
|
||||
SetWindowText(GetDlgItem(hDlg,IDC_TEXDUMPPATH),g_Config.texDumpPath.c_str());
|
||||
Edit_LimitText(GetDlgItem(hDlg,IDC_TEXDUMPPATH),255);
|
||||
}
|
||||
void Command(HWND hDlg,WPARAM wParam)
|
||||
{
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
case IDC_BROWSETEXDUMPPATH:
|
||||
{
|
||||
std::string path = W32Util::BrowseForFolder(hDlg,"Choose texture dump path:");
|
||||
SetWindowText(GetDlgItem(hDlg,IDC_TEXDUMPPATH),path.c_str());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
void Apply(HWND hDlg)
|
||||
{
|
||||
g_Config.bOverlayStats = Button_GetCheck(GetDlgItem(hDlg,IDC_OVERLAYSTATS)) ? true : false;
|
||||
g_Config.bWireFrame = Button_GetCheck(GetDlgItem(hDlg,IDC_WIREFRAME)) ? true : false;
|
||||
g_Config.bDumpTextures = Button_GetCheck(GetDlgItem(hDlg,IDC_TEXDUMP)) ? true : false;
|
||||
g_Config.iCompileDLsLevel = (int)ComboBox_GetCurSel(GetDlgItem(hDlg,IDC_DLOPTLEVEL));
|
||||
g_Config.bShowShaderErrors = Button_GetCheck(GetDlgItem(hDlg,IDC_SHOWSHADERERRORS)) ? true : false;
|
||||
char temp[MAX_PATH];
|
||||
GetWindowText(GetDlgItem(hDlg,IDC_TEXDUMPPATH), temp, MAX_PATH);
|
||||
g_Config.texDumpPath = temp;
|
||||
}
|
||||
};
|
||||
|
||||
struct TabDebug : public W32Util::Tab
|
||||
{
|
||||
void Init(HWND hDlg)
|
||||
{
|
||||
}
|
||||
void Command(HWND hDlg,WPARAM wParam)
|
||||
{
|
||||
/*
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
void Apply(HWND hDlg)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct TabEnhancements : public W32Util::Tab
|
||||
{
|
||||
void Init(HWND hDlg)
|
||||
{
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_FORCEFILTERING),g_Config.bForceFiltering);
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_FORCEANISOTROPY),g_Config.bForceMaxAniso);
|
||||
HWND pp = GetDlgItem(hDlg,IDC_POSTPROCESSEFFECT);
|
||||
const char **names = Postprocess::GetPostprocessingNames();
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
if (!names[i])
|
||||
break;
|
||||
|
||||
ComboBox_AddString(pp, names[i]);
|
||||
i++;
|
||||
}
|
||||
ComboBox_SetCurSel(pp, g_Config.iPostprocessEffect);
|
||||
}
|
||||
void Command(HWND hDlg,WPARAM wParam)
|
||||
{
|
||||
/*
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
void Apply(HWND hDlg)
|
||||
{
|
||||
g_Config.bForceMaxAniso = Button_GetCheck(GetDlgItem(hDlg, IDC_FORCEANISOTROPY)) ? true : false;
|
||||
g_Config.bForceFiltering = Button_GetCheck(GetDlgItem(hDlg,IDC_FORCEFILTERING)) ? true : false;
|
||||
g_Config.iPostprocessEffect = ComboBox_GetCurSel(GetDlgItem(hDlg,IDC_POSTPROCESSEFFECT));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void DlgSettings_Show(HINSTANCE hInstance, HWND _hParent)
|
||||
{
|
||||
g_Config.Load();
|
||||
W32Util::PropSheet sheet;
|
||||
sheet.Add(new TabDirect3D,(LPCTSTR)IDD_SETTINGS,"Direct3D");
|
||||
sheet.Add(new TabEnhancements,(LPCTSTR)IDD_ENHANCEMENTS,"Enhancements");
|
||||
sheet.Add(new TabAdvanced,(LPCTSTR)IDD_ADVANCED,"Advanced");
|
||||
//sheet.Add(new TabDebug,(LPCTSTR)IDD_DEBUGGER,"Debugger");
|
||||
sheet.Show(hInstance,_hParent,"Graphics Plugin");
|
||||
g_Config.Save();
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void DlgSettings_Show(HINSTANCE hInstance, HWND parent);
|
||||
@@ -0,0 +1,137 @@
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "../../Core/Src/Core.h"
|
||||
#include "EmuWindow.h"
|
||||
|
||||
namespace EmuWindow
|
||||
{
|
||||
HWND m_hWnd;
|
||||
HINSTANCE m_hInstance;
|
||||
WNDCLASSEX wndClass;
|
||||
const TCHAR m_szClassName[] = "DolphinEmuWnd";
|
||||
|
||||
HWND GetWnd()
|
||||
{
|
||||
|
||||
return m_hWnd;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
HDC hdc;
|
||||
PAINTSTRUCT ps;
|
||||
switch( iMsg )
|
||||
{
|
||||
case WM_PAINT:
|
||||
hdc = BeginPaint( hWnd, &ps );
|
||||
EndPaint( hWnd, &ps );
|
||||
return 0;
|
||||
|
||||
case WM_KEYDOWN:
|
||||
switch( LOWORD( wParam ))
|
||||
{
|
||||
case VK_ESCAPE: /* Pressing esc quits */
|
||||
//DestroyWindow(hWnd);
|
||||
//PostQuitMessage(0);
|
||||
break;
|
||||
/*
|
||||
case MY_KEYS:
|
||||
hypotheticalScene->sendMessage(KEYDOWN...);
|
||||
*/
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
//Core::SetState(Core::CORE_UNINITIALIZED);
|
||||
exit(0);
|
||||
return 0;
|
||||
|
||||
case WM_DESTROY:
|
||||
//Shutdown();
|
||||
//PostQuitMessage( 0 );
|
||||
break;
|
||||
|
||||
case WM_SIZE:
|
||||
// Reset the D3D Device here
|
||||
// Also make damn sure that this is not called from inside rendering a frame :P
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProc(hWnd, iMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
|
||||
HWND OpenWindow(HWND parent, HINSTANCE hInstance, bool windowed, int width, int height, const TCHAR *title)
|
||||
{
|
||||
wndClass.cbSize = sizeof( wndClass );
|
||||
wndClass.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wndClass.lpfnWndProc = WndProc;
|
||||
wndClass.cbClsExtra = 0;
|
||||
wndClass.cbWndExtra = 0;
|
||||
wndClass.hInstance = hInstance;
|
||||
wndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
|
||||
wndClass.hCursor = LoadCursor( NULL, IDC_ARROW );
|
||||
wndClass.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
|
||||
wndClass.lpszMenuName = NULL;
|
||||
wndClass.lpszClassName = m_szClassName;
|
||||
wndClass.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
|
||||
|
||||
m_hInstance = hInstance;
|
||||
RegisterClassEx( &wndClass );
|
||||
|
||||
DWORD style = windowed ? WS_OVERLAPPEDWINDOW : WS_POPUP;
|
||||
|
||||
RECT rc = {0, 0, width, height};
|
||||
AdjustWindowRect(&rc, style, false);
|
||||
|
||||
int w = rc.right - rc.left;
|
||||
int h = rc.bottom - rc.top;
|
||||
|
||||
rc.left = (1280 - w)/2;
|
||||
rc.right = rc.left + w;
|
||||
rc.top = (1024 - h)/2;
|
||||
rc.bottom = rc.top + h;
|
||||
|
||||
m_hWnd = CreateWindow(m_szClassName, title,
|
||||
style,
|
||||
rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
|
||||
parent, NULL, hInstance, NULL );
|
||||
|
||||
return m_hWnd;
|
||||
}
|
||||
|
||||
void Show()
|
||||
{
|
||||
ShowWindow(m_hWnd, SW_SHOW);
|
||||
BringWindowToTop(m_hWnd);
|
||||
UpdateWindow(m_hWnd);
|
||||
}
|
||||
|
||||
HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR *title)
|
||||
{
|
||||
return OpenWindow(hParent, hInstance, true, 640, 480, title);
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
DestroyWindow(m_hWnd);
|
||||
UnregisterClass(m_szClassName, m_hInstance);
|
||||
}
|
||||
|
||||
|
||||
void SetSize(int width, int height)
|
||||
{
|
||||
RECT rc = {0, 0, width, height};
|
||||
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false);
|
||||
|
||||
int w = rc.right - rc.left;
|
||||
int h = rc.bottom - rc.top;
|
||||
|
||||
rc.left = (1280 - w)/2;
|
||||
rc.right = rc.left + w;
|
||||
rc.top = (1024 - h)/2;
|
||||
rc.bottom = rc.top + h;
|
||||
::MoveWindow(m_hWnd, rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top, TRUE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef _EMUWINDOW_H
|
||||
#define _EMUWINDOW_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
namespace EmuWindow
|
||||
{
|
||||
HWND GetWnd();
|
||||
HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR *title);
|
||||
void Show();
|
||||
void Close();
|
||||
void SetSize(int displayWidth, int displayHeight);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,149 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "Utils.h"
|
||||
#include "Fifo.h"
|
||||
#include "main.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
|
||||
#define FIFO_SIZE (1024*1024)
|
||||
|
||||
FifoReader fifo;
|
||||
static u8 *videoBuffer;
|
||||
|
||||
int size = 0;
|
||||
int readptr = 0;
|
||||
|
||||
void Fifo_Init()
|
||||
{
|
||||
//VirtualFree((LPVOID)buffer,CMDBUFFER_SIZE,MEM_RELEASE);
|
||||
videoBuffer = (u8*)VirtualAlloc(0, FIFO_SIZE, MEM_COMMIT, PAGE_READWRITE);
|
||||
fifo.Init(videoBuffer, videoBuffer); //zero length. there is no data yet.
|
||||
}
|
||||
|
||||
void Fifo_Shutdown()
|
||||
{
|
||||
VirtualFree(videoBuffer, FIFO_SIZE, MEM_RELEASE);
|
||||
}
|
||||
|
||||
int FAKE_GetFifoSize()
|
||||
{
|
||||
if (size < readptr)
|
||||
{
|
||||
DebugBreak();
|
||||
}
|
||||
return (size - readptr);
|
||||
}
|
||||
|
||||
u8 FAKE_PeekFifo8(u32 _uOffset)
|
||||
{
|
||||
return videoBuffer[readptr + _uOffset];
|
||||
}
|
||||
|
||||
u16 FAKE_PeekFifo16(u32 _uOffset)
|
||||
{
|
||||
return _byteswap_ushort(*(u16*)&videoBuffer[readptr + _uOffset]);
|
||||
}
|
||||
|
||||
u32 FAKE_PeekFifo32(u32 _uOffset)
|
||||
{
|
||||
return _byteswap_ulong(*(u32*)&videoBuffer[readptr + _uOffset]);
|
||||
}
|
||||
|
||||
u8 FAKE_ReadFifo8()
|
||||
{
|
||||
return videoBuffer[readptr++];
|
||||
}
|
||||
|
||||
u16 FAKE_ReadFifo16()
|
||||
{
|
||||
u16 val = _byteswap_ushort(*(u16*)(videoBuffer+readptr));
|
||||
readptr += 2;
|
||||
return val;
|
||||
}
|
||||
|
||||
u32 FAKE_ReadFifo32()
|
||||
{
|
||||
u32 val = _byteswap_ulong(*(u32*)(videoBuffer+readptr));
|
||||
readptr += 4;
|
||||
return val;
|
||||
}
|
||||
|
||||
void Video_SendFifoData(BYTE *_uData)
|
||||
{
|
||||
memcpy(videoBuffer + size, _uData, 32);
|
||||
size += 32;
|
||||
if (size + 32 >= FIFO_SIZE)
|
||||
{
|
||||
if (FAKE_GetFifoSize() > readptr)
|
||||
{
|
||||
MessageBox(NULL, "out of bounds", "video-plugin", MB_OK);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
DebugLog("FAKE BUFFER LOOPS");
|
||||
memmove(&videoBuffer[0], &videoBuffer[readptr], FAKE_GetFifoSize());
|
||||
// memset(&videoBuffer[FAKE_GetFifoSize()], 0, FIFO_SIZE - FAKE_GetFifoSize());
|
||||
size = FAKE_GetFifoSize();
|
||||
readptr = 0;
|
||||
}
|
||||
OpcodeDecoder_Run();
|
||||
}
|
||||
|
||||
|
||||
//TODO - turn inside out, have the "reader" ask for bytes instead
|
||||
// See Core.cpp for threading idea
|
||||
void Video_EnterLoop()
|
||||
{
|
||||
SCPFifoStruct &fifo = *g_VideoInitialize.pCPFifo;
|
||||
|
||||
// TODO(ector): Don't peek so often!
|
||||
while (g_VideoInitialize.pPeekMessages())
|
||||
{
|
||||
if (fifo.CPReadWriteDistance < 1) //fifo.CPLoWatermark)
|
||||
Sleep(1);
|
||||
//etc...
|
||||
|
||||
// check if we are able to run this buffer
|
||||
if ((fifo.bFF_GPReadEnable) && !(fifo.bFF_BPEnable && fifo.bFF_Breakpoint))
|
||||
{
|
||||
int count = 200;
|
||||
while(fifo.CPReadWriteDistance > 0 && count)
|
||||
{
|
||||
// check if we are on a breakpoint
|
||||
if (fifo.bFF_BPEnable)
|
||||
{
|
||||
//MessageBox(0,"Breakpoint enabled",0,0);
|
||||
if (fifo.CPReadPointer == fifo.CPBreakpoint)
|
||||
{
|
||||
fifo.bFF_Breakpoint = 1;
|
||||
g_VideoInitialize.pUpdateInterrupts();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// read the data and send it to the VideoPlugin
|
||||
|
||||
u8 *uData = Memory_GetPtr(fifo.CPReadPointer);
|
||||
|
||||
EnterCriticalSection(&fifo.sync);
|
||||
fifo.CPReadPointer += 32;
|
||||
Video_SendFifoData(uData);
|
||||
InterlockedExchangeAdd((LONG*)&fifo.CPReadWriteDistance, -32);
|
||||
LeaveCriticalSection(&fifo.sync);
|
||||
|
||||
// increase the ReadPtr
|
||||
if (fifo.CPReadPointer >= fifo.CPEnd)
|
||||
{
|
||||
fifo.CPReadPointer = fifo.CPBase;
|
||||
//LOG(COMMANDPROCESSOR, "BUFFER LOOP");
|
||||
// MessageBox(NULL, "loop", "now", MB_OK);
|
||||
}
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
#ifndef _FIFO_H
|
||||
#define _FIFO_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
// inline for speed!
|
||||
class FifoReader
|
||||
{
|
||||
u8 *ptr;
|
||||
u8 *end;
|
||||
u8 *tempPtr; //single element stack :P
|
||||
u8 *tempEnd;
|
||||
bool pushed;
|
||||
public:
|
||||
void Init(u8 *_ptr, u8 *_end)
|
||||
{
|
||||
ptr = _ptr; end = _end; pushed = false;
|
||||
}
|
||||
bool IsPushed() {return pushed;}
|
||||
void Push(u8 *_ptr, u8 *_end) {pushed = true; tempPtr = ptr; tempEnd = end; ptr = _ptr; end = _end;}
|
||||
void Pop() {pushed = false; ptr = tempPtr; end = tempEnd;}
|
||||
u8 Peek8 (int offset) { return ptr[offset]; }
|
||||
u16 Peek16(int offset) { return _byteswap_ushort(*(u16*)(ptr+offset)); }
|
||||
u32 Peek32(int offset) { return _byteswap_ulong(*(u32*)(ptr+offset)); }
|
||||
u8 Read8 () {return *ptr++;}
|
||||
u16 Read16() {const u16 value = _byteswap_ushort(*((u16*)ptr)); ptr+=2; return value;}
|
||||
u32 Read32() {const u32 value = _byteswap_ulong(*((u32*)ptr)); ptr+=4; return value;}
|
||||
float Read32F() {const u32 value = _byteswap_ulong(*((u32*)ptr)); ptr+=4; return *(float*)&value;}
|
||||
size_t GetRemainSize() const { return (int)(end - ptr); }
|
||||
u8 *GetPtr() const { return ptr; }
|
||||
void MoveEndForward() { end += 32; }
|
||||
u8 *GetEnd() const { return end; }
|
||||
};
|
||||
|
||||
extern FifoReader fifo;
|
||||
|
||||
void Fifo_Init();
|
||||
void Fifo_Shutdown();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,58 @@
|
||||
#include "Globals.h"
|
||||
#include "IniFile.h"
|
||||
|
||||
Config g_Config;
|
||||
|
||||
Config::Config()
|
||||
{
|
||||
}
|
||||
|
||||
void Config::Load()
|
||||
{
|
||||
IniFile iniFile;
|
||||
iniFile.Load("flipper.ini");
|
||||
iniFile.Get("Hardware", "Adapter", &iAdapter, 0);
|
||||
iniFile.Get("Hardware", "WindowedRes", &iWindowedRes, 0);
|
||||
iniFile.Get("Hardware", "FullscreenRes", &iFSResolution, 0);
|
||||
iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0);
|
||||
iniFile.Get("Hardware", "VSync", &bVsync, 0);
|
||||
if (iAdapter == -1)
|
||||
iAdapter = 0;
|
||||
|
||||
iniFile.Get("Settings", "OverlayStats", &bOverlayStats, false);
|
||||
iniFile.Get("Settings", "Postprocess", &iPostprocessEffect, 0);
|
||||
iniFile.Get("Settings", "DLOptimize", &iCompileDLsLevel, 0);
|
||||
iniFile.Get("Settings", "DumpTextures", &bDumpTextures, 0);
|
||||
iniFile.Get("Settings", "ShowShaderErrors", &bShowShaderErrors, 0);
|
||||
iniFile.Get("Settings", "Multisample", &iMultisampleMode, 0);
|
||||
iniFile.Get("Settings", "TexDumpPath", &texDumpPath, 0);
|
||||
|
||||
iniFile.Get("Enhancements", "ForceFiltering", &bForceFiltering, 0);
|
||||
iniFile.Get("Enhancements", "ForceMaxAniso", &bForceMaxAniso, 0);
|
||||
}
|
||||
|
||||
void Config::Save()
|
||||
{
|
||||
IniFile iniFile;
|
||||
iniFile.Load("flipper.ini");
|
||||
iniFile.Set("Hardware", "Adapter", iAdapter);
|
||||
iniFile.Set("Hardware", "WindowedRes", iWindowedRes);
|
||||
iniFile.Set("Hardware", "FullscreenRes", iFSResolution);
|
||||
iniFile.Set("Hardware", "Fullscreen", bFullscreen);
|
||||
iniFile.Set("Hardware", "VSync", bVsync);
|
||||
|
||||
iniFile.Set("Settings", "OverlayStats", bOverlayStats);
|
||||
iniFile.Set("Settings", "OverlayStats", bOverlayStats);
|
||||
iniFile.Set("Settings", "Postprocess", iPostprocessEffect);
|
||||
iniFile.Set("Settings", "DLOptimize", iCompileDLsLevel);
|
||||
iniFile.Set("Settings", "DumpTextures", bDumpTextures);
|
||||
iniFile.Set("Settings", "ShowShaderErrors", bShowShaderErrors);
|
||||
iniFile.Set("Settings", "Multisample", iMultisampleMode);
|
||||
iniFile.Set("Settings", "TexDumpPath", texDumpPath);
|
||||
|
||||
iniFile.Set("Enhancements", "ForceFiltering", bForceFiltering);
|
||||
iniFile.Set("Enhancements", "ForceMaxAniso", bForceMaxAniso);
|
||||
iniFile.Save("flipper.ini");
|
||||
}
|
||||
|
||||
Statistics stats;
|
||||
@@ -0,0 +1,103 @@
|
||||
#ifndef _GLOBALS_H
|
||||
#define _GLOBALS_H
|
||||
|
||||
#include <string>
|
||||
|
||||
struct Config
|
||||
{
|
||||
Config();
|
||||
void Load();
|
||||
void Save();
|
||||
|
||||
int iAdapter;
|
||||
int iFSResolution;
|
||||
int iMultisampleMode;
|
||||
|
||||
int iPostprocessEffect;
|
||||
int iCompileDLsLevel;
|
||||
|
||||
bool bFullscreen;
|
||||
bool bVsync;
|
||||
bool bWireFrame;
|
||||
bool bOverlayStats;
|
||||
bool bDumpTextures;
|
||||
bool bOldCard;
|
||||
bool bShowShaderErrors;
|
||||
//enhancements
|
||||
bool bForceFiltering;
|
||||
bool bForceMaxAniso;
|
||||
|
||||
bool bPreUpscale;
|
||||
int iPreUpscaleFilter;
|
||||
|
||||
bool bTruform;
|
||||
int iTruformLevel;
|
||||
|
||||
int iWindowedRes;
|
||||
|
||||
char psProfile[16];
|
||||
char vsProfile[16];
|
||||
|
||||
std::string texDumpPath;
|
||||
};
|
||||
|
||||
|
||||
extern Config g_Config;
|
||||
|
||||
|
||||
struct Statistics
|
||||
{
|
||||
int numPrimitives;
|
||||
|
||||
int numPixelShadersCreated;
|
||||
int numPixelShadersAlive;
|
||||
int numVertexShadersCreated;
|
||||
int numVertexShadersAlive;
|
||||
|
||||
int numTexturesCreated;
|
||||
int numTexturesAlive;
|
||||
|
||||
int numRenderTargetsCreated;
|
||||
int numRenderTargetsAlive;
|
||||
|
||||
int numDListsCalled;
|
||||
int numDListsCreated;
|
||||
int numDListsAlive;
|
||||
|
||||
int numJoins;
|
||||
|
||||
struct ThisFrame
|
||||
{
|
||||
int numBPLoads;
|
||||
int numCPLoads;
|
||||
int numXFLoads;
|
||||
|
||||
int numBPLoadsInDL;
|
||||
int numCPLoadsInDL;
|
||||
int numXFLoadsInDL;
|
||||
|
||||
int numDLs;
|
||||
int numDLPrims;
|
||||
int numPrims;
|
||||
int numShaderChanges;
|
||||
int numBadCommands; //hope this always is zero ;)
|
||||
};
|
||||
ThisFrame thisFrame;
|
||||
void ResetFrame() {memset(&thisFrame,0,sizeof(ThisFrame));}
|
||||
};
|
||||
|
||||
extern Statistics stats;
|
||||
|
||||
#define STATISTICS
|
||||
|
||||
#ifdef STATISTICS
|
||||
#define INCSTAT(a) (a)++;
|
||||
#define ADDSTAT(a,b) (a)+=(b);
|
||||
#define SETSTAT(a,x) (a)=(x);
|
||||
#else
|
||||
#define INCSTAT(a) ;
|
||||
#define ADDSTAT(a,b) ;
|
||||
#define SETSTAT(a,x) ;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,113 @@
|
||||
#include "stdafx.h"
|
||||
#include "IndexGenerator.h"
|
||||
|
||||
/*
|
||||
*
|
||||
QUAD simulator
|
||||
|
||||
0 2 4 6
|
||||
1 3 5 7
|
||||
021231 243453
|
||||
*/
|
||||
|
||||
|
||||
void IndexGenerator::Start(unsigned short *startptr)
|
||||
{
|
||||
ptr=startptr;
|
||||
index=0;
|
||||
numPrims=0;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddList(int numVerts)
|
||||
{
|
||||
int numTris = numVerts/3;
|
||||
if (numTris<=0) return;
|
||||
for (int i=0; i<numTris; i++)
|
||||
{
|
||||
*ptr++ = index+i*3;
|
||||
*ptr++ = index+i*3+1;
|
||||
*ptr++ = index+i*3+2;
|
||||
}
|
||||
index += numVerts;
|
||||
numPrims += numTris;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddStrip(int numVerts)
|
||||
{
|
||||
int numTris = numVerts-2;
|
||||
if (numTris<=0) return;
|
||||
bool wind = false;
|
||||
for (int i=0; i<numTris; i++)
|
||||
{
|
||||
*ptr++ = index+i;
|
||||
*ptr++ = index+i+(wind?2:1);
|
||||
*ptr++ = index+i+(wind?1:2);
|
||||
wind = !wind;
|
||||
}
|
||||
index += numVerts;
|
||||
numPrims += numTris;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddLineList(int numVerts)
|
||||
{
|
||||
int numLines= numVerts/2;
|
||||
if (numLines<=0) return;
|
||||
for (int i=0; i<numLines; i++)
|
||||
{
|
||||
*ptr++ = index+i*2;
|
||||
*ptr++ = index+i*2+1;
|
||||
}
|
||||
index += numVerts;
|
||||
numPrims += numLines;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddLineStrip(int numVerts)
|
||||
{
|
||||
int numLines = numVerts-1;
|
||||
if (numLines<=0) return;
|
||||
for (int i=0; i<numLines; i++)
|
||||
{
|
||||
*ptr++ = index+i;
|
||||
*ptr++ = index+i+1;
|
||||
}
|
||||
index += numVerts;
|
||||
numPrims += numLines;
|
||||
}
|
||||
|
||||
|
||||
void IndexGenerator::AddFan(int numVerts)
|
||||
{
|
||||
int numTris = numVerts-2;
|
||||
if (numTris<=0) return;
|
||||
for (int i=0; i<numTris; i++)
|
||||
{
|
||||
*ptr++ = index;
|
||||
*ptr++ = index+i+1;
|
||||
*ptr++ = index+i+2;
|
||||
}
|
||||
index += numVerts;
|
||||
numPrims += numTris;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddQuads(int numVerts)
|
||||
{
|
||||
int numTris = (numVerts/4)*2;
|
||||
if (numTris<=0) return;
|
||||
for (int i=0; i<numTris/2; i++)
|
||||
{
|
||||
*ptr++=index+i*4;
|
||||
*ptr++=index+i*4+1;
|
||||
*ptr++=index+i*4+3;
|
||||
*ptr++=index+i*4+1;
|
||||
*ptr++=index+i*4+2;
|
||||
*ptr++=index+i*4+3;
|
||||
}
|
||||
index += numVerts;
|
||||
numPrims += numTris;
|
||||
}
|
||||
|
||||
|
||||
void IndexGenerator::AddPointList(int numVerts)
|
||||
{
|
||||
index += numVerts;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
class IndexGenerator
|
||||
{
|
||||
unsigned short *ptr;
|
||||
int numPrims;
|
||||
int index;
|
||||
public:
|
||||
void Start(unsigned short *startptr);
|
||||
void AddList(int numVerts);
|
||||
void AddStrip(int numVerts);
|
||||
void AddLineList(int numVerts);
|
||||
void AddPointList(int numVerts); //dummy for counting vertices
|
||||
void AddLineStrip(int numVerts);
|
||||
void AddFan(int numVerts);
|
||||
void AddQuads(int numVerts);
|
||||
int GetNumPrims() {return numPrims;} //returns numprimitives
|
||||
int GetNumVerts() {return index;} //returns numprimitives
|
||||
};
|
||||
@@ -0,0 +1,310 @@
|
||||
//DL facts:
|
||||
// Ikaruga uses NO display lists!
|
||||
// Zelda WW uses TONS of display lists
|
||||
// Zelda TP uses almost 100% display lists except menus (we like this!)
|
||||
|
||||
// Note that it IS NOT POSSIBLE to precompile display lists! You can compile them as they are
|
||||
// and hope that the vertex format doesn't change, though, if you do it just when they are
|
||||
// called. The reason is that the vertex format affects the sizes of the vertices.
|
||||
|
||||
|
||||
#include "D3DBase.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "Globals.h"
|
||||
#include "VertexHandler.h"
|
||||
#include "TransformEngine.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "TextureCache.h"
|
||||
#include "ShaderManager.h"
|
||||
#include "DecodedVArray.h"
|
||||
|
||||
#include "BPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
#include "Utils.h"
|
||||
#include "main.h"
|
||||
#include "DataReader.h"
|
||||
|
||||
#include "DLCompiler.h"
|
||||
|
||||
#define CMDBUFFER_SIZE 1024*1024
|
||||
DecodedVArray tempvarray;
|
||||
void Decode();
|
||||
|
||||
extern u8 FAKE_PeekFifo8(u32 _uOffset);
|
||||
extern u16 FAKE_PeekFifo16(u32 _uOffset);
|
||||
extern u32 FAKE_PeekFifo32(u32 _uOffset);
|
||||
extern int FAKE_GetFifoSize();
|
||||
|
||||
CDataReader_Fifo g_fifoReader;
|
||||
|
||||
void ExecuteDisplayList(u32 address, u32 size)
|
||||
{
|
||||
IDataReader* pOldReader = g_pDataReader;
|
||||
|
||||
// address &= 0x01FFFFFF; // phys address
|
||||
CDataReader_Memory memoryReader(address);
|
||||
g_pDataReader = &memoryReader;
|
||||
|
||||
while((memoryReader.GetReadAddress() - address) < size)
|
||||
{
|
||||
Decode();
|
||||
}
|
||||
INCSTAT(stats.numDListsAlive);
|
||||
// reset to the old reader
|
||||
g_pDataReader = pOldReader;
|
||||
}
|
||||
|
||||
inline u8 PeekFifo8(u32 _uOffset)
|
||||
{
|
||||
return FAKE_PeekFifo8(_uOffset);
|
||||
}
|
||||
|
||||
inline u16 PeekFifo16(u32 _uOffset)
|
||||
{
|
||||
return FAKE_PeekFifo16(_uOffset);
|
||||
}
|
||||
|
||||
inline u32 PeekFifo32(u32 _uOffset)
|
||||
{
|
||||
return FAKE_PeekFifo32(_uOffset);
|
||||
}
|
||||
|
||||
|
||||
bool FifoCommandRunnable(void)
|
||||
{
|
||||
u32 iBufferSize = FAKE_GetFifoSize();
|
||||
if (iBufferSize == 0)
|
||||
return false;
|
||||
|
||||
u8 Cmd = PeekFifo8(0);
|
||||
u32 iCommandSize = 0;
|
||||
|
||||
switch(Cmd)
|
||||
{
|
||||
case GX_NOP:
|
||||
// Hm, this means that we scan over nop streams pretty slowly...
|
||||
iCommandSize = 1;
|
||||
break;
|
||||
|
||||
case GX_LOAD_CP_REG:
|
||||
iCommandSize = 6;
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A:
|
||||
case GX_LOAD_INDX_B:
|
||||
case GX_LOAD_INDX_C:
|
||||
case GX_LOAD_INDX_D:
|
||||
iCommandSize = 5;
|
||||
break;
|
||||
|
||||
case GX_CMD_CALL_DL:
|
||||
iCommandSize = 9;
|
||||
break;
|
||||
|
||||
case 0x44:
|
||||
iCommandSize = 1;
|
||||
// zelda 4 swords calls it and checks the metrics registers after that
|
||||
break;
|
||||
|
||||
case GX_CMD_INVL_VC: // invalid vertex cache - no parameter?
|
||||
iCommandSize = 1;
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG:
|
||||
iCommandSize = 5;
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
// check if we can read the header
|
||||
if (iBufferSize >= 5)
|
||||
{
|
||||
iCommandSize = 1 + 4;
|
||||
u32 Cmd2 = PeekFifo32(1);
|
||||
int dwTransferSize = ((Cmd2 >> 16) & 15) + 1;
|
||||
iCommandSize += dwTransferSize * 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (Cmd&0x80)
|
||||
{
|
||||
// check if we can read the header
|
||||
if (iBufferSize >= 3)
|
||||
{
|
||||
iCommandSize = 1 + 2;
|
||||
u16 numVertices = PeekFifo16(1);
|
||||
VertexLoader& vtxLoader = g_VertexLoaders[Cmd & GX_VAT_MASK];
|
||||
vtxLoader.Setup();
|
||||
int vsize = vtxLoader.GetVertexSize();
|
||||
iCommandSize += numVertices * vsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char szTemp[512];
|
||||
sprintf(szTemp, "Error: Unknown Opcode (0x%x)", Cmd);
|
||||
MessageBox(NULL, szTemp, "Video-Plugin", MB_OK);
|
||||
g_VideoInitialize.pLog(szTemp, TRUE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (iCommandSize > iBufferSize)
|
||||
return false;
|
||||
|
||||
#ifdef _DEBUG
|
||||
char temp[256];
|
||||
sprintf(temp, "OP detected: Cmd 0x%x size %i buffer %i",Cmd, iCommandSize, iBufferSize);
|
||||
g_VideoInitialize.pLog(temp, FALSE);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Decode(void)
|
||||
{
|
||||
static int DecoderCount = 0;
|
||||
DecoderCount++;
|
||||
|
||||
if (DecoderCount == 0x0019c601)
|
||||
{
|
||||
int i = 0;
|
||||
}
|
||||
|
||||
// 0x0019c603 <- error
|
||||
|
||||
int Cmd = g_pDataReader->Read8();
|
||||
switch(Cmd)
|
||||
{
|
||||
case GX_NOP:
|
||||
break;
|
||||
|
||||
case GX_LOAD_CP_REG: //0x08
|
||||
{
|
||||
u32 SubCmd = g_pDataReader->Read8();
|
||||
u32 Value = g_pDataReader->Read32();
|
||||
LoadCPReg(SubCmd,Value);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
u32 test = PeekFifo32(0);
|
||||
u32 Cmd2 = g_pDataReader->Read32();
|
||||
|
||||
int dwTransferSize = ((Cmd2>>16)&15) + 1;
|
||||
DWORD dwAddress = Cmd2 & 0xFFFF;
|
||||
static u32 pData[16];
|
||||
for (int i=0; i<dwTransferSize; i++)
|
||||
pData[i] = g_pDataReader->Read32();
|
||||
LoadXFReg(dwTransferSize,dwAddress,pData);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A: //used for position matrices
|
||||
LoadIndexedXF(g_pDataReader->Read32(),0xC);
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //used for normal matrices
|
||||
LoadIndexedXF(g_pDataReader->Read32(),0xD);
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //used for postmatrices
|
||||
LoadIndexedXF(g_pDataReader->Read32(),0xE);
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //used for lights
|
||||
LoadIndexedXF(g_pDataReader->Read32(),0xF);
|
||||
break;
|
||||
|
||||
case GX_CMD_CALL_DL:
|
||||
{
|
||||
u32 dwAddr = g_pDataReader->Read32();
|
||||
u32 dwCount = g_pDataReader->Read32();
|
||||
ExecuteDisplayList(dwAddr, dwCount);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x44:
|
||||
// zelda 4 swords calls it and checks the metrics registers after that
|
||||
break;
|
||||
|
||||
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
|
||||
DebugLog("Invalidate (vertex cache?)");
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
{
|
||||
u32 cmd = g_pDataReader->Read32();
|
||||
LoadBPReg(cmd);
|
||||
}
|
||||
break;
|
||||
|
||||
// draw primitives
|
||||
default:
|
||||
if (Cmd&0x80)
|
||||
{
|
||||
// load vertices
|
||||
u16 numVertices = g_pDataReader->Read16();
|
||||
tempvarray.Reset();
|
||||
VertexLoader::SetVArray(&tempvarray);
|
||||
VertexLoader& vtxLoader = g_VertexLoaders[Cmd & GX_VAT_MASK];
|
||||
vtxLoader.Setup();
|
||||
vtxLoader.PrepareRun();
|
||||
int vsize = vtxLoader.GetVertexSize();
|
||||
vtxLoader.RunVertices(numVertices);
|
||||
|
||||
// draw vertices
|
||||
int primitive = (Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
|
||||
CVertexHandler::DrawVertices(primitive, numVertices, &tempvarray);
|
||||
}
|
||||
else
|
||||
{
|
||||
char szTmp[256];
|
||||
// sprintf(szTmp, "Illegal command %02x (at %08x)",Cmd,g_pDataReader->GetPtr());
|
||||
sprintf(szTmp, "Illegal command %02x",Cmd);
|
||||
g_VideoInitialize.pLog(szTmp, TRUE);
|
||||
MessageBox(0,szTmp,"GFX ERROR",0);
|
||||
// _assert_msg_(0,szTmp,"");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OpcodeDecoder_Init()
|
||||
{
|
||||
g_pDataReader = &g_fifoReader;
|
||||
tempvarray.Create(65536*3, 1, 8, 3, 2, 8);
|
||||
}
|
||||
|
||||
|
||||
void OpcodeDecoder_Shutdown()
|
||||
{
|
||||
//VirtualFree((LPVOID)buffer,CMDBUFFER_SIZE,MEM_RELEASE);
|
||||
tempvarray.Destroy();
|
||||
}
|
||||
|
||||
void OpcodeDecoder_Run()
|
||||
{
|
||||
// just a small check
|
||||
if (g_pDataReader != &g_fifoReader)
|
||||
{
|
||||
MessageBox(NULL, "very strange", "video-plugin", MB_OK);
|
||||
}
|
||||
|
||||
DVSTARTPROFILE();
|
||||
|
||||
while (FifoCommandRunnable())
|
||||
{
|
||||
Decode();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef _OPCODE_DECODING_H
|
||||
#define _OPCODE_DECODING_H
|
||||
|
||||
#include "PluginSpecs_Video.h"
|
||||
#include "Common.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_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
|
||||
|
||||
void OpcodeDecoder_Init();
|
||||
void OpcodeDecoder_Shutdown();
|
||||
void OpcodeDecoder_Run();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,216 @@
|
||||
#include "stdafx.h"
|
||||
#include "OpcodeReaders.h"
|
||||
|
||||
_u8 *readerMemPtr;
|
||||
_u8 *bufPtr;
|
||||
FifoData *gFifoData;
|
||||
_u32 gDListEnd, gDListPtr;
|
||||
|
||||
namespace OpcodeReaders
|
||||
{
|
||||
void SetBufPtr(_u8 *_bufptr)
|
||||
{
|
||||
bufPtr = _bufptr;
|
||||
}
|
||||
void SetFifoData(FifoData *_fdata)
|
||||
{
|
||||
gFifoData = _fdata;
|
||||
}
|
||||
void SetMemPtr(_u8 *_mptr)
|
||||
{
|
||||
readerMemPtr = _mptr;
|
||||
}
|
||||
|
||||
void SetDListReader(_u32 _ptr, _u32 _end)
|
||||
{
|
||||
gDListPtr = _ptr & 0x1FFFFFF;
|
||||
gDListEnd = _end & 0x1FFFFFF;
|
||||
}
|
||||
void DListReaderSkip(int _skip)
|
||||
{
|
||||
gDListPtr+=_skip;
|
||||
}
|
||||
bool IsDListOKToRead()
|
||||
{
|
||||
return gDListPtr<gDListEnd;
|
||||
}
|
||||
}
|
||||
//FifoData *fifoData;
|
||||
|
||||
_u8 PeekFifo8()
|
||||
{
|
||||
int addr = (gFifoData->readptr+1)^3;
|
||||
if (addr==gFifoData->gpend)
|
||||
addr=gFifoData->gpbegin;
|
||||
return readerMemPtr[addr];
|
||||
}
|
||||
// ________________________________________________________________________________________________
|
||||
// ReadFifo8
|
||||
//
|
||||
_u8 ReadFifo8()
|
||||
{
|
||||
while (
|
||||
(gFifoData->readenable == false) ||
|
||||
(gFifoData->readptr == gFifoData->writeptr) ||
|
||||
(gFifoData->bpenable && (gFifoData->readptr == gFifoData->breakpt))
|
||||
)
|
||||
{
|
||||
//if (gFifoData->readptr == gFifoData->breakpt)
|
||||
// MessageBox(0,"hello breakpoint",0,0);
|
||||
SwitchToFiber(gFifoData->cpuFiber);
|
||||
}
|
||||
|
||||
_u8 val = readerMemPtr[(gFifoData->readptr++)^3];
|
||||
|
||||
if (gFifoData->readptr == gFifoData->gpend)
|
||||
gFifoData->readptr = gFifoData->gpbegin;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
// ________________________________________________________________________________________________
|
||||
// ReadFifo16
|
||||
//
|
||||
_u16 ReadFifo16()
|
||||
{
|
||||
//PowerPC byte ordering :(
|
||||
_u8 val1 = ReadFifo8();
|
||||
_u8 val2 = ReadFifo8();
|
||||
return (val1<<8)|(val2);
|
||||
}
|
||||
|
||||
// ________________________________________________________________________________________________
|
||||
// ReadFifo32
|
||||
//
|
||||
_u32 ReadFifo32()
|
||||
{
|
||||
//PowerPC byte ordering :(
|
||||
_u8 val1 = ReadFifo8();
|
||||
_u8 val2 = ReadFifo8();
|
||||
_u8 val3 = ReadFifo8();
|
||||
_u8 val4 = ReadFifo8();
|
||||
return (val1<<24)|(val2<<16)|(val3<<8)|(val4);
|
||||
}
|
||||
|
||||
_u32 GetPtrFifo()
|
||||
{
|
||||
return gFifoData->readptr;
|
||||
}
|
||||
|
||||
_u8 PeekDList8()
|
||||
{
|
||||
if (gDListPtr<gDListEnd-1)
|
||||
return readerMemPtr[(gDListPtr+1)^3];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
// ________________________________________________________________________________________________
|
||||
// ReadFifo8
|
||||
//
|
||||
_u8 ReadDList8()
|
||||
{
|
||||
return readerMemPtr[(gDListPtr++)^3];
|
||||
}
|
||||
|
||||
// ________________________________________________________________________________________________
|
||||
// ReadFifo16
|
||||
//
|
||||
_u16 ReadDList16()
|
||||
{
|
||||
//PowerPC byte ordering :(
|
||||
_u8 val1 = readerMemPtr[(gDListPtr++)^3];
|
||||
_u8 val2 = readerMemPtr[(gDListPtr++)^3];
|
||||
return (val1<<8)|(val2);
|
||||
}
|
||||
|
||||
// ________________________________________________________________________________________________
|
||||
// ReadFifo32
|
||||
//
|
||||
_u32 ReadDList32()
|
||||
{
|
||||
//PowerPC byte ordering :(
|
||||
_u8 val1 = readerMemPtr[(gDListPtr++)^3];
|
||||
_u8 val2 = readerMemPtr[(gDListPtr++)^3];
|
||||
_u8 val3 = readerMemPtr[(gDListPtr++)^3];
|
||||
_u8 val4 = readerMemPtr[(gDListPtr++)^3];
|
||||
return (val1<<24)|(val2<<16)|(val3<<8)|(val4);
|
||||
}
|
||||
|
||||
_u32 GetPtrDList()
|
||||
{
|
||||
return gDListPtr;
|
||||
}
|
||||
|
||||
|
||||
_u8 PeekBuf8()
|
||||
{
|
||||
return bufPtr[0];
|
||||
}
|
||||
|
||||
// ________________________________________________________________________________________________
|
||||
// ReadFifo8
|
||||
//
|
||||
_u8 ReadBuf8()
|
||||
{
|
||||
return *bufPtr++;
|
||||
}
|
||||
|
||||
// ________________________________________________________________________________________________
|
||||
// ReadFifo16
|
||||
//
|
||||
_u16 ReadBuf16()
|
||||
{
|
||||
_u16 val = *(_u16*)bufPtr;
|
||||
bufPtr+=2;
|
||||
return (val<<8)|(val>>8);
|
||||
}
|
||||
|
||||
// ________________________________________________________________________________________________
|
||||
// ReadFifo32
|
||||
//
|
||||
_u32 ReadBuf32()
|
||||
{
|
||||
// _u32 val = *(_u32*)bufPtr;
|
||||
//__asm
|
||||
// {
|
||||
// mov ebx,bufPtr
|
||||
// mov eax,[ebx]
|
||||
// add ebx,4
|
||||
// mov bufPtr,ebx
|
||||
// bswap eax
|
||||
// }
|
||||
_u32 high = ReadBuf16();
|
||||
return (high<<16) | ReadBuf16();
|
||||
// return swap32(val);
|
||||
}
|
||||
|
||||
|
||||
ReaderInterface fifoReader =
|
||||
{
|
||||
ReadFifo8,
|
||||
PeekFifo8,
|
||||
ReadFifo16,
|
||||
ReadFifo32,
|
||||
GetPtrFifo
|
||||
};
|
||||
|
||||
|
||||
ReaderInterface dlistReader =
|
||||
{
|
||||
ReadDList8,
|
||||
PeekDList8,
|
||||
ReadDList16,
|
||||
ReadDList32,
|
||||
GetPtrDList
|
||||
};
|
||||
|
||||
ReaderInterface bufReader =
|
||||
{
|
||||
ReadBuf8,
|
||||
PeekBuf8,
|
||||
ReadBuf16,
|
||||
ReadBuf32,
|
||||
0
|
||||
};
|
||||
|
||||
ReaderInterface *reader;
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include "../plugin_specs/video.h"
|
||||
#include "structs.h"
|
||||
|
||||
struct ReaderInterface
|
||||
{
|
||||
_u8 (*Read8) (void);
|
||||
_u8 (*Peek8) (void); //to combine primitive draws..
|
||||
_u16 (*Read16)(void);
|
||||
_u32 (*Read32)(void);
|
||||
_u32 (*GetPtr)(void);
|
||||
};
|
||||
|
||||
extern ReaderInterface *reader;
|
||||
extern ReaderInterface fifoReader,dlistReader,bufReader;
|
||||
|
||||
namespace OpcodeReaders
|
||||
{
|
||||
void SetDListReader(_u32 _ptr, _u32 _end);
|
||||
void DListReaderSkip(int _skip);
|
||||
void SetMemPtr(_u8 *_mptr);
|
||||
void SetFifoData(FifoData *_fdata);
|
||||
bool IsDListOKToRead();
|
||||
|
||||
void SetBufPtr(_u8 *_bufptr);
|
||||
}
|
||||
@@ -0,0 +1,523 @@
|
||||
#include "Globals.h"
|
||||
#include "D3DShader.h"
|
||||
#include "PixelShader.h"
|
||||
#include "BPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
#include "W32Util/Misc.h"
|
||||
#include "Utils.h"
|
||||
|
||||
/*
|
||||
old tev->pixelshader notes
|
||||
|
||||
color for this stage (alpha, color) is given by bpmem.tevorders[0].colorchan0
|
||||
konstant for this stage (alpha, color) is given by bpmem.tevksel
|
||||
inputs are given by bpmem.combiners[0].colorC.a/b/c/d << could be current chan color
|
||||
according to GXTevColorArg table above
|
||||
output is given by .outreg
|
||||
tevtemp is set according to swapmodetables and
|
||||
*/
|
||||
|
||||
const float epsilon = 1.0f/255.0f;
|
||||
|
||||
const char *tevKSelTableC[] =
|
||||
{
|
||||
"1,1,1", //KCSEL_1 = 0x00
|
||||
"0.875,0.875,0.875",//KCSEL_7_8 = 0x01
|
||||
"0.75,0.75,0.75", //KCSEL_3_4 = 0x02
|
||||
"0.625,0.625,0.625",//KCSEL_5_8 = 0x03
|
||||
"0.5,0.5,0.5", //KCSEL_1_2 = 0x04
|
||||
"0.375,0.375,0.375",//KCSEL_3_8 = 0x05
|
||||
"0.25,0.25,0.25", //KCSEL_1_4 = 0x06
|
||||
"0.125,0.125,0.125",//KCSEL_1_8 = 0x07
|
||||
"ERROR", //0x08
|
||||
"ERROR", //0x09
|
||||
"ERROR", //0x0a
|
||||
"ERROR", //0x0b
|
||||
"k0.rgb",//KCSEL_K0 = 0x0C
|
||||
"k1.rgb",//KCSEL_K1 = 0x0D
|
||||
"k2.rgb",//KCSEL_K2 = 0x0E
|
||||
"k3.rgb",//KCSEL_K3 = 0x0F
|
||||
"k0.rrr",//KCSEL_K0_R = 0x10
|
||||
"k1.rrr",//KCSEL_K1_R = 0x11
|
||||
"k2.rrr",//KCSEL_K2_R = 0x12
|
||||
"k3.rrr",//KCSEL_K3_R = 0x13
|
||||
"k0.ggg",//KCSEL_K0_G = 0x14
|
||||
"k1.ggg",//KCSEL_K1_G = 0x15
|
||||
"k2.ggg",//KCSEL_K2_G = 0x16
|
||||
"k3.ggg",//KCSEL_K3_G = 0x17
|
||||
"k0.bbb",//KCSEL_K0_B = 0x18
|
||||
"k1.bbb",//KCSEL_K1_B = 0x19
|
||||
"k2.bbb",//KCSEL_K2_B = 0x1A
|
||||
"k3.bbb",//KCSEL_K3_B = 0x1B
|
||||
"k0.aaa",//KCSEL_K0_A = 0x1C
|
||||
"k1.aaa",//KCSEL_K1_A = 0x1D
|
||||
"k2.aaa",//KCSEL_K2_A = 0x1E
|
||||
"k3.aaa",//KCSEL_K3_A = 0x1F
|
||||
};
|
||||
const char *tevKSelTableA[] =
|
||||
{
|
||||
"1", //KASEL_1 = 0x00
|
||||
"0.875",//KASEL_7_8 = 0x01
|
||||
"0.75", //KASEL_3_4 = 0x02
|
||||
"0.625",//KASEL_5_8 = 0x03
|
||||
"0.5", //KASEL_1_2 = 0x04
|
||||
"0.375",//KASEL_3_8 = 0x05
|
||||
"0.25", //KASEL_1_4 = 0x06
|
||||
"0.125",//KASEL_1_8 = 0x07
|
||||
"ERROR",//0x08
|
||||
"ERROR",//0x09
|
||||
"ERROR",//0x0a
|
||||
"ERROR",//0x0b
|
||||
"ERROR",//0x0c
|
||||
"ERROR",//0x0d
|
||||
"ERROR",//0x0e
|
||||
"ERROR",//0x0f
|
||||
"k0.r", //KASEL_K0_R = 0x10
|
||||
"k1.r", //KASEL_K1_R = 0x11
|
||||
"k2.r", //KASEL_K2_R = 0x12
|
||||
"k3.r", //KASEL_K3_R = 0x13
|
||||
"k0.g", //KASEL_K0_G = 0x14
|
||||
"k1.g", //KASEL_K1_G = 0x15
|
||||
"k2.g", //KASEL_K2_G = 0x16
|
||||
"k3.g", //KASEL_K3_G = 0x17
|
||||
"k0.b", //KASEL_K0_B = 0x18
|
||||
"k1.b", //KASEL_K1_B = 0x19
|
||||
"k2.b", //KASEL_K2_B = 0x1A
|
||||
"k3.b", //KASEL_K3_B = 0x1B
|
||||
"k0.a", //KASEL_K0_A = 0x1C
|
||||
"k1.a", //KASEL_K1_A = 0x1D
|
||||
"k2.a", //KASEL_K2_A = 0x1E
|
||||
"k3.a", //KASEL_K3_A = 0x1F
|
||||
};
|
||||
|
||||
const char *tevScaleTable[] =
|
||||
{
|
||||
"1", //SCALE_1
|
||||
"2", //SCALE_2
|
||||
"4", //SCALE_4
|
||||
"0.5", //DIVIDE_2
|
||||
};
|
||||
|
||||
const char *tevBiasTable[] =
|
||||
{
|
||||
"", //ZERO,
|
||||
"+0.5", //ADD_HALF,
|
||||
"-0.5", //SUB_HALF,
|
||||
"", //WTF? seen in shadow2
|
||||
};
|
||||
|
||||
const char *tevOpTable[] =
|
||||
{
|
||||
"+", //ADD = 0,
|
||||
"-", //SUB = 1,
|
||||
};
|
||||
|
||||
const char *tevCompOpTable[] =
|
||||
{
|
||||
">",
|
||||
"==",
|
||||
};
|
||||
|
||||
|
||||
#define TEV_COMP_R8 0
|
||||
#define TEV_COMP_GR16 1
|
||||
#define TEV_COMP_BGR24 2
|
||||
#define TEV_COMP_RGB8 3
|
||||
|
||||
const char *tevCInputTable[] =
|
||||
{
|
||||
"prev.rgb", //CPREV,
|
||||
"prev.aaa", //APREV,
|
||||
"c0.rgb", //C0,
|
||||
"c0.aaa", //A0,
|
||||
"c1.rgb", //C1,
|
||||
"c1.aaa", //A1,
|
||||
"c2.rgb", //C2,
|
||||
"c2.aaa", //A2,
|
||||
"textemp.rgb", //TEXC,
|
||||
"textemp.aaa", //TEXA,
|
||||
"rastemp.rgb", //RASC,
|
||||
"rastemp.aaa", //RASA,
|
||||
"float3(1,1,1)", //ONE,
|
||||
"float3(.5,.5,.5)", //HALF,
|
||||
"konsttemp.rgb", //KONST,
|
||||
"float3(0,0,0)", //ZERO
|
||||
"PADERROR", "PADERROR", "PADERROR", "PADERROR",
|
||||
"PADERROR", "PADERROR", "PADERROR", "PADERROR",
|
||||
"PADERROR", "PADERROR", "PADERROR", "PADERROR",
|
||||
"PADERROR", "PADERROR", "PADERROR", "PADERROR",
|
||||
"PADERROR", "PADERROR", "PADERROR", "PADERROR",
|
||||
};
|
||||
const char *tevCInputTable2[] =
|
||||
{
|
||||
"prev", //CPREV,
|
||||
"(prev.aaa)", //APREV,
|
||||
"c0", //C0,
|
||||
"(c0.aaa)", //A0,
|
||||
"c1", //C1,
|
||||
"(c1.aaa)", //A1,
|
||||
"c2", //C2,
|
||||
"(c2.aaa)", //A2,
|
||||
"textemp", //TEXC,
|
||||
"(textemp.aaa)", //TEXA,
|
||||
"rastemp", //RASC,
|
||||
"(rastemp.aaa)", //RASA,
|
||||
"float3(1,1,1)", //ONE,
|
||||
"float3(.5,.5,.5)", //HALF,
|
||||
"konsttemp", //KONST,
|
||||
"float3(0,0,0)", //ZERO
|
||||
"PADERROR", "PADERROR", "PADERROR", "PADERROR",
|
||||
"PADERROR", "PADERROR", "PADERROR", "PADERROR",
|
||||
"PADERROR", "PADERROR", "PADERROR", "PADERROR",
|
||||
"PADERROR", "PADERROR", "PADERROR", "PADERROR",
|
||||
"PADERROR", "PADERROR", "PADERROR", "PADERROR",
|
||||
};
|
||||
|
||||
const char *tevAInputTable[] =
|
||||
{
|
||||
"prev.a", //APREV,
|
||||
"c0.a", //A0,
|
||||
"c1.a", //A1,
|
||||
"c2.a", //A2,
|
||||
"textemp.a", //TEXA,
|
||||
"rastemp.a", //RASA,
|
||||
"konsttemp.a", //KONST, (hw1 had quarter)
|
||||
"0.0", //ZERO
|
||||
"PADERROR",
|
||||
"PADERROR",
|
||||
"PADERROR",
|
||||
"PADERROR",
|
||||
"PADERROR",
|
||||
"PADERROR",
|
||||
"PADERROR",
|
||||
"PADERROR",
|
||||
"PADERROR",
|
||||
"PADERROR",
|
||||
"PADERROR",
|
||||
"PADERROR",
|
||||
"PADERROR",
|
||||
"PADERROR",
|
||||
"PADERROR",
|
||||
|
||||
};
|
||||
|
||||
const char *tevRasTable[] =
|
||||
{
|
||||
"colors[0]",//RAS1_CC_0 0x00000000 /* color channel 0 */
|
||||
"colors[1]",//RAS1_CC_1 0x00000001 /* color channel 1 */
|
||||
"ERROR", //2
|
||||
"ERROR", //3
|
||||
"ERROR", //4
|
||||
"float4(0,1,0,1)", //RAS1_CC_B 0x00000005 /* indirect texture bump alpha */ //green cuz unsupported
|
||||
"float4(0,1,0,1)", //RAS1_CC_BN 0x00000006 /* ind tex bump alpha, normalized 0-255 *///green cuz unsupported
|
||||
"float4(0,0,0,0)", //RAS1_CC_Z 0x00000007 /* set color value to zero */
|
||||
};
|
||||
|
||||
const char *tevCOutputTable[] =
|
||||
{
|
||||
"prev.rgb",
|
||||
"c0.rgb",
|
||||
"c1.rgb",
|
||||
"c2.rgb",
|
||||
};
|
||||
const char *tevAOutputTable[] =
|
||||
{
|
||||
"prev.a",
|
||||
"c0.a",
|
||||
"c1.a",
|
||||
"c2.a",
|
||||
};
|
||||
|
||||
const char *texFuncs[] =
|
||||
{
|
||||
"tex2D",
|
||||
"tex2Dproj"
|
||||
};
|
||||
|
||||
//I hope we don't get too many hash collisions :p
|
||||
//all these magic numbers are primes, it should help a bit
|
||||
tevhash GetCurrentTEV()
|
||||
{
|
||||
u32 hash = bpmem.genMode.numindstages + bpmem.genMode.numtevstages*11 + bpmem.genMode.numtexgens*8*17;
|
||||
for (int i=0; i<(int)bpmem.genMode.numtevstages+1; i++)
|
||||
{
|
||||
hash = _rotl(hash,3) ^ (bpmem.combiners[i].colorC.hex*13);
|
||||
hash = _rotl(hash,7) ^ ((bpmem.combiners[i].alphaC.hex&0xFFFFFFFC)*3);
|
||||
hash = _rotl(hash,9) ^ texcoords[i].texmtxinfo.projection*451;
|
||||
}
|
||||
for (int i=0; i<(int)bpmem.genMode.numtevstages/2+1; i++)
|
||||
{
|
||||
hash = _rotl(hash,13) ^ (bpmem.tevorders[i].hex*7);
|
||||
}
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
hash = _rotl(hash,3) ^ bpmem.tevksel[i].swap1;
|
||||
hash = _rotl(hash,3) ^ bpmem.tevksel[i].swap2;
|
||||
}
|
||||
hash ^= bpmem.dstalpha.enable ^ 0xc0debabe;
|
||||
hash = _rotl(hash,4) ^ bpmem.alphaFunc.comp0*7;
|
||||
hash = _rotl(hash,4) ^ bpmem.alphaFunc.comp1*13;
|
||||
hash = _rotl(hash,4) ^ bpmem.alphaFunc.logic*11;
|
||||
return hash;
|
||||
}
|
||||
|
||||
char text[65536];
|
||||
#define WRITE p+=sprintf
|
||||
|
||||
|
||||
void WriteStage(char *&p, int n);
|
||||
void WriteAlphaTest(char *&p);
|
||||
|
||||
|
||||
char *swapColors = "rgba";
|
||||
char swapModeTable[4][5];
|
||||
|
||||
void BuildSwapModeTable()
|
||||
{
|
||||
//bpmem.tevregs[0].
|
||||
for (int i=0; i<4; i++)
|
||||
{
|
||||
swapModeTable[i][0]=swapColors[bpmem.tevksel[i*2].swap1];
|
||||
swapModeTable[i][1]=swapColors[bpmem.tevksel[i*2].swap2];
|
||||
swapModeTable[i][2]=swapColors[bpmem.tevksel[i*2+1].swap1];
|
||||
swapModeTable[i][3]=swapColors[bpmem.tevksel[i*2+1].swap2];
|
||||
swapModeTable[i][4]=0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 GeneratePixelShader()
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
|
||||
BuildSwapModeTable();
|
||||
int numStages = bpmem.genMode.numtevstages + 1;
|
||||
int numTexgen = bpmem.genMode.numtexgens;
|
||||
int numSamplers = 8;
|
||||
|
||||
char *p = text;
|
||||
WRITE(p,"//Pixel Shader for TEV stages\n");
|
||||
WRITE(p,"//%i TEV stages, %i texgens, %i IND stages, %i COL channels\n",
|
||||
bpmem.genMode.numtevstages,bpmem.genMode.numtexgens,bpmem.genMode.numindstages,bpmem.genMode.numcolchans);
|
||||
|
||||
//write kcolor declarations
|
||||
for (int i=0; i<4; i++)
|
||||
WRITE(p,"float4 k%i : register(c%i);\n",i,PS_CONST_KCOLORS+i);
|
||||
|
||||
for (int i=0; i<3; i++)
|
||||
WRITE(p,"float4 color%i : register(c%i);\n",i,PS_CONST_COLORS+i+1);
|
||||
|
||||
WRITE(p,"float constalpha : register(c%i);\n",PS_CONST_CONSTALPHA);
|
||||
WRITE(p,"float2 alphaRef : register(c%i);\n",PS_CONST_ALPHAREF);
|
||||
|
||||
WRITE(p,"\n");
|
||||
|
||||
WRITE(p,"sampler samp[%i] : register(s0);\n",numSamplers,numSamplers);
|
||||
|
||||
WRITE(p,"\n");
|
||||
|
||||
WRITE(p,"float4 main(in float4 colors[2] : COLOR0");
|
||||
if (numTexgen)
|
||||
WRITE(p,", float4 uv[%i] : TEXCOORD0",numTexgen);
|
||||
else
|
||||
WRITE(p,", float4 uv[1] : TEXCOORD0"); //HACK
|
||||
WRITE(p,") : COLOR\n");
|
||||
WRITE(p,"{\n");
|
||||
WRITE(p,"float4 c0=color0,c1=color1,c2=color2,prev=float4(0.0f,0.0f,0.0f,0.0f),textemp,rastemp,konsttemp;\n");
|
||||
WRITE(p,"\n");
|
||||
|
||||
//WRITE(p, "return 1;}\n");
|
||||
//return D3D::CompilePShader(text,(int)(p-text));
|
||||
|
||||
for (int i=0; i<numStages; i++)
|
||||
WriteStage(p,i); //build the equation for this stage
|
||||
|
||||
//WRITE(p, "prev = textemp;\n");
|
||||
//WRITE(p, "prev = float4(uv[0].x,uv[0].y,0,1);\n");
|
||||
WriteAlphaTest(p);
|
||||
|
||||
if (bpmem.dstalpha.enable)
|
||||
WRITE(p," return float4(prev.rgb,constalpha.x);\n");
|
||||
else
|
||||
WRITE(p," return prev;\n");
|
||||
|
||||
WRITE(p,"}\n");
|
||||
WRITE(p,"\0");
|
||||
|
||||
//#ifndef TEASER
|
||||
/*
|
||||
FILE *f=fopen("D:\\dlistlogs.txt","a");
|
||||
fprintf(f,"===========================================\n");
|
||||
fprintf(f,"%s",text);
|
||||
fclose(f);
|
||||
*/
|
||||
//W32Util::CopyTextToClipboard(0,text);
|
||||
//#endif
|
||||
|
||||
//MessageBox(0,text,0,0);
|
||||
return D3D::CompilePShader(text,(int)(p-text));
|
||||
}
|
||||
|
||||
void WriteStage(char *&p, int n)
|
||||
{
|
||||
char *rasswap = swapModeTable[bpmem.combiners[n].alphaC.rswap];
|
||||
char *texswap = swapModeTable[bpmem.combiners[n].alphaC.tswap];
|
||||
|
||||
int texfun = texcoords[n].texmtxinfo.projection;
|
||||
|
||||
WRITE(p,"rastemp=%s.%s;\n",tevRasTable[bpmem.tevorders[n/2].getColorChan(n&1)],rasswap);
|
||||
if (bpmem.tevorders[n/2].getEnable(n&1))
|
||||
WRITE(p,"textemp=%s(samp[%i],uv[%i]).%s;\n",
|
||||
texFuncs[texfun],
|
||||
bpmem.tevorders[n/2].getTexMap(n&1),
|
||||
bpmem.tevorders[n/2].getTexCoord(n&1),texswap);
|
||||
else
|
||||
WRITE(p,"textemp=float4(1,1,1,1);\n");
|
||||
|
||||
int kc = bpmem.tevksel[n/2].getKC(n&1);
|
||||
int ka = bpmem.tevksel[n/2].getKA(n&1);
|
||||
|
||||
WRITE(p,"konsttemp=float4(%s,%s);\n",tevKSelTableC[kc],tevKSelTableA[ka]);
|
||||
|
||||
TevStageCombiner::ColorCombiner &cc = bpmem.combiners[n].colorC;
|
||||
TevStageCombiner::AlphaCombiner &ac = bpmem.combiners[n].alphaC;
|
||||
|
||||
WRITE(p,"float4(%s,%s)=", tevCOutputTable[cc.outreg], tevAOutputTable[ac.outreg]);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//start of color
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
WRITE(p,"float4(\n");
|
||||
|
||||
if (cc.bias != TB_COMPARE)
|
||||
{
|
||||
//normal color combiner goes here
|
||||
WRITE(p," %s*(%s%s",tevScaleTable[cc.scale],tevCInputTable[cc.d],tevOpTable[cc.op]);
|
||||
WRITE(p,"(lerp(%s,%s,%s)%s)),\n",
|
||||
tevCInputTable[cc.a],tevCInputTable[cc.b],
|
||||
tevCInputTable[cc.c],tevBiasTable[cc.bias]);
|
||||
}
|
||||
else
|
||||
{
|
||||
//compare color combiner goes here
|
||||
switch(cc.scale) // yep comparemode stored here :P
|
||||
{
|
||||
case TEV_COMP_R8:
|
||||
if (cc.op == 0) //equality check needs tolerance, fp in gpu has drawbacks :(
|
||||
WRITE(p," %s + ((%s.r > %s.r) ? %s : float3(0,0,0)),\n",
|
||||
tevCInputTable[cc.d],tevCInputTable2[cc.a],
|
||||
tevCInputTable2[cc.b],tevCInputTable[cc.c]);
|
||||
else
|
||||
WRITE(p," %s + (abs(%s.r - %s.r)<%f ? %s : float3(0,0,0)),\n",
|
||||
tevCInputTable[cc.d],tevCInputTable2[cc.a],
|
||||
tevCInputTable2[cc.b],epsilon,tevCInputTable[cc.c]);
|
||||
break;
|
||||
default:
|
||||
WRITE(p,"float3(0,0,0),\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
//end of color
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//start of alpha
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (ac.bias != TB_COMPARE)
|
||||
{
|
||||
//normal alpha combiner goes here
|
||||
WRITE(p," %s*(%s%s",tevScaleTable[ac.scale],tevAInputTable[ac.d],tevOpTable[ac.op]);
|
||||
WRITE(p,"(lerp(%s,%s,%s)%s))\n",
|
||||
tevAInputTable[ac.a],tevAInputTable[ac.b],
|
||||
tevAInputTable[ac.c],tevBiasTable[ac.bias]);
|
||||
}
|
||||
else
|
||||
{
|
||||
//compare alpha combiner goes here
|
||||
if (ac.op==0)
|
||||
WRITE(p," %s + ((%s > %s) ? %s : 0)\n",
|
||||
tevAInputTable[ac.d],tevAInputTable[ac.a],
|
||||
tevAInputTable[ac.b],tevAInputTable[ac.c]);
|
||||
else
|
||||
WRITE(p," %s + (abs(%s - %s)<%f ? %s : 0)\n",
|
||||
tevAInputTable[ac.d],tevAInputTable[ac.a],
|
||||
tevAInputTable[ac.b],epsilon,tevAInputTable[ac.c]);
|
||||
|
||||
}
|
||||
WRITE(p,");");
|
||||
//end of alpha
|
||||
WRITE(p,"\n");
|
||||
}
|
||||
|
||||
char *alphaRef[2] =
|
||||
{
|
||||
"alphaRef.x",
|
||||
"alphaRef.y"
|
||||
};
|
||||
|
||||
void WriteAlphaCompare(char *&p, int num, int comp)
|
||||
{
|
||||
WRITE(p," res%i = ",num);
|
||||
switch(comp) {
|
||||
case COMPARE_ALWAYS: WRITE(p,"0;\n"); break;
|
||||
case COMPARE_NEVER: WRITE(p,"1;\n"); break;
|
||||
case COMPARE_LEQUAL: WRITE(p,"prev.a - %s.x;\n",alphaRef[num]); break;
|
||||
case COMPARE_LESS: WRITE(p,"prev.a - %s.x + %f;\n",alphaRef[num],epsilon*2);break;
|
||||
case COMPARE_GEQUAL: WRITE(p,"%s - prev.a;\n",alphaRef[num]); break;
|
||||
case COMPARE_GREATER: WRITE(p,"%s - prev.a + %f;\n",alphaRef[num],epsilon*2);break;
|
||||
case COMPARE_EQUAL: WRITE(p,"abs(%s-prev.a)-%f;\n",alphaRef[num],epsilon*2); break;
|
||||
case COMPARE_NEQUAL: WRITE(p,"%f-abs(%s-prev.a);\n",epsilon*2,alphaRef[num]); break;
|
||||
}
|
||||
}
|
||||
|
||||
void WriteAlphaTest(char *&p)
|
||||
{
|
||||
AlphaOp op = (AlphaOp)bpmem.alphaFunc.logic;
|
||||
Compare comp[2] = {(Compare)bpmem.alphaFunc.comp0,(Compare)bpmem.alphaFunc.comp1};
|
||||
|
||||
//first kill all the simple cases
|
||||
if (op == ALPHAOP_AND && (comp[0] == COMPARE_ALWAYS && comp[1] == COMPARE_ALWAYS)) return;
|
||||
if (op == ALPHAOP_OR && (comp[0] == COMPARE_ALWAYS || comp[1] == COMPARE_ALWAYS)) return;
|
||||
for (int i=0; i<2; i++)
|
||||
{
|
||||
int one = i;
|
||||
int other = 1-i;
|
||||
switch(op) {
|
||||
case ALPHAOP_XOR:
|
||||
if (comp[one] == COMPARE_ALWAYS && comp[other] == COMPARE_NEVER) return;
|
||||
break;
|
||||
case ALPHAOP_XNOR:
|
||||
if (comp[one] == COMPARE_ALWAYS && comp[other] == COMPARE_ALWAYS) return;
|
||||
if (comp[one] == COMPARE_ALWAYS && comp[other] == COMPARE_NEVER) return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Ok, didn't get to do the easy way out :P
|
||||
// do the general way
|
||||
WRITE(p,"float res0,res1;\n");
|
||||
WriteAlphaCompare(p,0,bpmem.alphaFunc.comp0);
|
||||
WriteAlphaCompare(p,1,bpmem.alphaFunc.comp1);
|
||||
WRITE(p,"res0=max(res0,0);\n");
|
||||
WRITE(p,"res1=max(res1,0);\n");
|
||||
//probably should use lookup textures for some of these :P
|
||||
switch(bpmem.alphaFunc.logic) {
|
||||
case ALPHAOP_AND: // if both are 0
|
||||
WRITE(p,"clip(-(res0+res1)+%f);\n",epsilon);
|
||||
break;
|
||||
case ALPHAOP_OR: //if either is 0
|
||||
WRITE(p,"clip(-res0*res1+%f);\n",epsilon*epsilon);
|
||||
break;
|
||||
case ALPHAOP_XOR:
|
||||
//hmm, this might work:
|
||||
WRITE(p,"res0=(res0>0?1:0)-.5;\n");
|
||||
WRITE(p,"res1=(res1>0?1:0)-.5;\n");
|
||||
WRITE(p,"clip(-res0*res1);\n",epsilon);
|
||||
break;
|
||||
case ALPHAOP_XNOR:
|
||||
WRITE(p,"res0=(res0>0?1:0)-.5;\n");
|
||||
WRITE(p,"res1=(res1>0?1:0)-.5;\n");
|
||||
WRITE(p,"clip(res0*res1);\n",epsilon);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
typedef u32 tevhash;
|
||||
|
||||
tevhash GetCurrentTEV();
|
||||
LPDIRECT3DPIXELSHADER9 GeneratePixelShader();
|
||||
|
||||
#define PS_CONST_COLORS 0
|
||||
#define PS_CONST_KCOLORS 4
|
||||
#define PS_CONST_CONSTALPHA 8
|
||||
#define PS_CONST_ALPHAREF 9 // x,y
|
||||
#define PS_CONST_INDMTXSTART 10
|
||||
#define PS_CONST_INDSIZE 2
|
||||
@@ -0,0 +1,84 @@
|
||||
#ifndef _RGBAFLOAT_H
|
||||
#define _RGBAFLOAT_H
|
||||
|
||||
struct RGBAFloat
|
||||
{
|
||||
float r,g,b,a;
|
||||
RGBAFloat(){a=r=g=b=1.0f;}
|
||||
RGBAFloat(float _r, float _g, float _b, float _a)
|
||||
{
|
||||
r=_r;g=_g;b=_b;a=_a;
|
||||
}
|
||||
void clamp()
|
||||
{
|
||||
if (r>1) r=1;
|
||||
if (g>1) g=1;
|
||||
if (b>1) b=1;
|
||||
if (a>1) a=1;
|
||||
if (r<0) r=0;
|
||||
if (g<0) g=0;
|
||||
if (b<0) b=0;
|
||||
if (a<0) a=0;
|
||||
}
|
||||
void convertToD3DColor(u32 &color)
|
||||
{
|
||||
clamp();
|
||||
color = (int(a*255)<<24) | (int(r*255)<<16) | (int(g*255)<<8) | (int(b*255));
|
||||
}
|
||||
void convertRGB_GC(u32 color)
|
||||
{
|
||||
r=((color>>24)&0xFF)/255.0f;
|
||||
g=((color>>16)&0xFF)/255.0f;
|
||||
b=((color>>8)&0xFF)/255.0f;
|
||||
}
|
||||
void convertRGB(u32 color)
|
||||
{
|
||||
r=((color>>16)&0xFF)/255.0f;
|
||||
g=((color>>8)&0xFF)/255.0f;
|
||||
b=((color)&0xFF)/255.0f;
|
||||
}
|
||||
void convertA(u32 color)
|
||||
{
|
||||
a=((color>>24)&0xFF)/255.0f;
|
||||
}
|
||||
void convertA_GC(u32 color)
|
||||
{
|
||||
a=((color)&0xFF)/255.0f;
|
||||
}
|
||||
void convert(u32 color)
|
||||
{
|
||||
convertRGB(color);
|
||||
convertA(color);
|
||||
}
|
||||
void convert_GC(u32 color)
|
||||
{
|
||||
convertRGB_GC(color);
|
||||
convertA_GC(color);
|
||||
}
|
||||
void operator *=(float f)
|
||||
{
|
||||
r*=f;g*=f;b*=f; a*=f;
|
||||
}
|
||||
RGBAFloat operator *(float f)
|
||||
{
|
||||
return RGBAFloat(r*f,g*f,b*f,a*f);
|
||||
}
|
||||
RGBAFloat operator *(RGBAFloat &o)
|
||||
{
|
||||
return RGBAFloat(r*o.r,g*o.g,b*o.b,a*o.a);
|
||||
}
|
||||
void operator *=(RGBAFloat &o)
|
||||
{
|
||||
r*=o.r;g*=o.g;b*=o.b;a*=o.a;
|
||||
}
|
||||
RGBAFloat operator +(RGBAFloat &o)
|
||||
{
|
||||
return RGBAFloat(r+o.r,g+o.g,b+o.b,a+o.a);
|
||||
}
|
||||
void operator +=(RGBAFloat &o)
|
||||
{
|
||||
r+=o.r;g+=o.g;b+=o.b;a+=o.a;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,295 @@
|
||||
#include <d3dx9.h>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "D3DBase.h"
|
||||
|
||||
#include "Globals.h"
|
||||
#include "main.h"
|
||||
#include "VertexHandler.h"
|
||||
#include "Render.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "BPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
#include "D3DPostprocess.h"
|
||||
#include "D3DUtil.h"
|
||||
#include "ShaderManager.h"
|
||||
#include "TextureCache.h"
|
||||
#include "Utils.h"
|
||||
#include "EmuWindow.h"
|
||||
|
||||
float Renderer::m_x,Renderer::m_y,Renderer::m_width, Renderer::m_height, Renderer::xScale,Renderer::yScale;
|
||||
|
||||
#define NUMWNDRES 6
|
||||
extern int g_Res[NUMWNDRES][2];
|
||||
|
||||
void Renderer::Init(SVideoInitialize &_VideoInitialize)
|
||||
{
|
||||
EmuWindow::SetSize(g_Res[g_Config.iWindowedRes][0], g_Res[g_Config.iWindowedRes][1]);
|
||||
|
||||
D3D::Create(g_Config.iAdapter, EmuWindow::GetWnd(), g_Config.bFullscreen, g_Config.iFSResolution, g_Config.iMultisampleMode);
|
||||
|
||||
D3DVIEWPORT9 vp;
|
||||
D3D::dev->GetViewport(&vp);
|
||||
|
||||
m_x = 0;
|
||||
m_y = 0;
|
||||
m_width = (float)vp.Width;
|
||||
m_height = (float)vp.Height;
|
||||
xScale = 640.0f / (float)vp.Width;
|
||||
yScale = 480.0f / (float)vp.Height;
|
||||
|
||||
D3D::font.Init();
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void Renderer::Shutdown(void)
|
||||
{
|
||||
D3D::font.Shutdown();
|
||||
D3D::EndFrame();
|
||||
D3D::Close();
|
||||
}
|
||||
|
||||
void Renderer::Initialize(void)
|
||||
{
|
||||
D3D::dev->SetRenderState(D3DRS_LIGHTING,FALSE);
|
||||
D3D::dev->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
|
||||
D3D::dev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
D3D::dev->SetRenderState(D3DRS_FOGENABLE, FALSE);
|
||||
D3D::dev->SetRenderState(D3DRS_FILLMODE, g_Config.bWireFrame?D3DFILL_WIREFRAME:D3DFILL_SOLID);
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
D3D::dev->SetSamplerState(i, D3DSAMP_MAXANISOTROPY, 16);
|
||||
}
|
||||
ReinitView();
|
||||
|
||||
Postprocess::Initialize();
|
||||
Postprocess::BeginFrame();
|
||||
D3D::BeginFrame(true, 0);
|
||||
CVertexHandler::BeginFrame();
|
||||
}
|
||||
|
||||
|
||||
void dumpMatrix(D3DXMATRIX &mtx)
|
||||
{
|
||||
for (int y=0; y<4; y++)
|
||||
{
|
||||
char temp[256];
|
||||
sprintf(temp,"%4.4f %4.4f %4.4f %4.4f",mtx.m[y][0],mtx.m[y][1],mtx.m[y][2],mtx.m[y][3]);
|
||||
g_VideoInitialize.pLog(temp, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::ReinitView()
|
||||
{
|
||||
D3DXMATRIX mtx;
|
||||
D3DXMatrixIdentity(&mtx);
|
||||
D3D::dev->SetTransform(D3DTS_VIEW,&mtx);
|
||||
D3D::dev->SetTransform(D3DTS_WORLD,&mtx);
|
||||
|
||||
float width = (float)D3D::GetDisplayWidth();
|
||||
float height = (float)D3D::GetDisplayHeight();
|
||||
|
||||
xScale = width/640.0f;
|
||||
yScale = height/480.0f;
|
||||
|
||||
RECT rc = {
|
||||
(LONG)(m_x*xScale), (LONG)(m_y*yScale), (LONG)(m_width*xScale), (LONG)(m_height*yScale)
|
||||
};
|
||||
}
|
||||
|
||||
void Renderer::SwapBuffers(void)
|
||||
{
|
||||
//Finish up the current frame, print some stats
|
||||
Postprocess::FinalizeFrame();
|
||||
if (g_Config.bOverlayStats)
|
||||
{
|
||||
char st[2048];
|
||||
char *p = st;
|
||||
p+=sprintf(p,"Num textures created: %i\n",stats.numTexturesCreated);
|
||||
p+=sprintf(p,"Num textures alive: %i\n",stats.numTexturesAlive);
|
||||
p+=sprintf(p,"Num pshaders created: %i\n",stats.numPixelShadersCreated);
|
||||
p+=sprintf(p,"Num pshaders alive: %i\n",stats.numPixelShadersAlive);
|
||||
p+=sprintf(p,"Num vshaders created: %i\n",stats.numVertexShadersCreated);
|
||||
p+=sprintf(p,"Num vshaders alive: %i\n",stats.numVertexShadersAlive);
|
||||
p+=sprintf(p,"Num dlists called: %i\n",stats.numDListsCalled);
|
||||
p+=sprintf(p,"Num dlists created: %i\n",stats.numDListsCreated);
|
||||
p+=sprintf(p,"Num dlists alive: %i\n",stats.numDListsAlive);
|
||||
p+=sprintf(p,"Num strip joins: %i\n",stats.numJoins);
|
||||
p+=sprintf(p,"Num primitives: %i\n",stats.thisFrame.numPrims);
|
||||
p+=sprintf(p,"Num primitives (DL): %i\n",stats.thisFrame.numDLPrims);
|
||||
p+=sprintf(p,"Num bad commands: %i%s\n",stats.thisFrame.numBadCommands,stats.thisFrame.numBadCommands?"!!!":"");
|
||||
p+=sprintf(p,"Num XF loads: %i\n",stats.thisFrame.numXFLoads);
|
||||
p+=sprintf(p,"Num XF loads (DL): %i\n",stats.thisFrame.numXFLoadsInDL);
|
||||
p+=sprintf(p,"Num CP loads: %i\n",stats.thisFrame.numCPLoads);
|
||||
p+=sprintf(p,"Num CP loads (DL): %i\n",stats.thisFrame.numCPLoadsInDL);
|
||||
p+=sprintf(p,"Num BP loads: %i\n",stats.thisFrame.numBPLoads);
|
||||
p+=sprintf(p,"Num BP loads (DL): %i\n",stats.thisFrame.numBPLoadsInDL);
|
||||
|
||||
D3D::font.DrawTextScaled(0,30,20,20,0.0f,0xFF00FFFF,st,false);
|
||||
|
||||
//end frame
|
||||
}
|
||||
|
||||
#if defined(DVPROFILE)
|
||||
if( g_bWriteProfile ) {
|
||||
//g_bWriteProfile = 0;
|
||||
static int framenum = 0;
|
||||
const int UPDATE_FRAMES = 8;
|
||||
if( ++framenum >= UPDATE_FRAMES ) {
|
||||
DVProfWrite("prof.txt", UPDATE_FRAMES);
|
||||
DVProfClear();
|
||||
framenum = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
D3D::EndFrame();
|
||||
//D3D frame is now over
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//clean out old stuff from caches
|
||||
frameCount++;
|
||||
PShaderCache::Cleanup();
|
||||
TextureCache::Cleanup();
|
||||
//DListCache::Cleanup();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//Begin new frame
|
||||
//Set default viewport and scissor, for the clear to work correctly
|
||||
stats.ResetFrame();
|
||||
D3DVIEWPORT9 vp;
|
||||
vp.X = 0;
|
||||
vp.Y = 0;
|
||||
vp.Width = (DWORD)m_width;
|
||||
vp.Height = (DWORD)m_height;
|
||||
vp.MinZ = 0;
|
||||
vp.MaxZ = 0;
|
||||
D3D::dev->SetViewport(&vp);
|
||||
RECT rc;
|
||||
rc.left = 0;
|
||||
rc.top = 0;
|
||||
rc.right = (LONG)m_width;
|
||||
rc.bottom = (LONG)m_height;
|
||||
D3D::dev->SetScissorRect(&rc);
|
||||
|
||||
u32 clearColor = (bpmem.clearcolorAR<<16)|bpmem.clearcolorGB;
|
||||
// clearColor |= 0x003F003F;
|
||||
// D3D::BeginFrame(true,clearColor,1.0f);
|
||||
D3D::BeginFrame(false,clearColor,1.0f);
|
||||
// D3D::EnableAlphaToCoverage();
|
||||
|
||||
Postprocess::BeginFrame();
|
||||
CVertexHandler::BeginFrame();
|
||||
|
||||
if (g_Config.bOldCard)
|
||||
D3D::font.SetRenderStates(); //compatibility with lowend cards
|
||||
}
|
||||
|
||||
void Renderer::Flush(void)
|
||||
{
|
||||
// render the rest of the vertex buffer
|
||||
//only to be used for debugging purposes
|
||||
//D3D::EndFrame();
|
||||
|
||||
//D3D::BeginFrame(false,0);
|
||||
}
|
||||
|
||||
void Renderer::SetViewport(float* _Viewport)
|
||||
{
|
||||
Viewport* pViewport = (Viewport*)_Viewport;
|
||||
D3DVIEWPORT9 vp;
|
||||
float x=(pViewport->xOrig-662)*2;
|
||||
float y=(pViewport->yOrig-582)*2; //something is wrong, but what??
|
||||
y-=16;
|
||||
|
||||
float w=pViewport->wd*2; //multiply up to real size
|
||||
float h=pViewport->ht*-2; //why is this negative? oh well..
|
||||
|
||||
if (x < 0.0f) x = 0.0f;
|
||||
if (y < 0.0f) y = 0.0f;
|
||||
if (x > 640.0f) x = 639.0f;
|
||||
if (y > 480.0f) y = 479.0f;
|
||||
if (w < 0) w=1;
|
||||
if (h < 0) h=1;
|
||||
if (x+w > 640.0f) w=640-x;
|
||||
if (y+h > 480.0f) h=480-y;
|
||||
//x=y=0;
|
||||
//if(w>0.0f) w=0.0f;
|
||||
//if(h<0.0f) h=0.0f;
|
||||
|
||||
vp.X = (DWORD)(x*xScale);
|
||||
vp.Y = (DWORD)(y*yScale);
|
||||
vp.Width = (DWORD)(w*xScale);
|
||||
vp.Height = (DWORD)(h*yScale);
|
||||
vp.MinZ = 0.0f;
|
||||
vp.MaxZ = 1.0f;
|
||||
|
||||
// char temp[256];
|
||||
// sprintf(temp,"Viewport: %i %i %i %i %f %f",vp.X,vp.Y,vp.Width,vp.Height,vp.MinZ,vp.MaxZ);
|
||||
// g_VideoInitialize.pLog(temp, FALSE);
|
||||
|
||||
D3D::dev->SetViewport(&vp);
|
||||
}
|
||||
|
||||
void Renderer::SetScissorBox(RECT &rc)
|
||||
{
|
||||
rc.left = (int)(rc.left * xScale);
|
||||
rc.top = (int)(rc.top * yScale);
|
||||
rc.right = (int)(rc.right * xScale);
|
||||
rc.bottom = (int)(rc.bottom * yScale);
|
||||
if (rc.right >= rc.left && rc.bottom >= rc.top)
|
||||
D3D::dev->SetScissorRect(&rc);
|
||||
else
|
||||
g_VideoInitialize.pLog("SCISSOR ERROR", FALSE);
|
||||
}
|
||||
|
||||
void Renderer::SetProjection(float* pMatrix, int constantIndex)
|
||||
{
|
||||
D3DXMATRIX mtx;
|
||||
if (pMatrix[6] == 0)
|
||||
{
|
||||
mtx.m[0][0] = pMatrix[0];
|
||||
mtx.m[1][0] = 0.0f;
|
||||
mtx.m[2][0] = pMatrix[1];
|
||||
mtx.m[3][0] = -0.5f/m_width;
|
||||
|
||||
mtx.m[0][1] = 0.0f;
|
||||
mtx.m[1][1] = pMatrix[2];
|
||||
mtx.m[2][1] = pMatrix[3];
|
||||
mtx.m[3][1] = +0.5f/m_height;
|
||||
|
||||
mtx.m[0][2] = 0.0f;
|
||||
mtx.m[1][2] = 0.0f;
|
||||
mtx.m[2][2] = -(1-pMatrix[4]);
|
||||
mtx.m[3][2] = pMatrix[5];
|
||||
|
||||
mtx.m[0][3] = 0.0f;
|
||||
mtx.m[1][3] = 0.0f;
|
||||
mtx.m[2][3] = -1.0f;
|
||||
mtx.m[3][3] = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtx.m[0][0] = pMatrix[0];
|
||||
mtx.m[1][0] = 0.0f;
|
||||
mtx.m[2][0] = 0.0f;
|
||||
mtx.m[3][0] = pMatrix[1]-0.5f/m_width; // fix d3d pixel center
|
||||
|
||||
mtx.m[0][1] = 0.0f;
|
||||
mtx.m[1][1] = pMatrix[2];
|
||||
mtx.m[2][1] = 0.0f;
|
||||
mtx.m[3][1] = pMatrix[3]+0.5f/m_height; // fix d3d pixel center
|
||||
|
||||
mtx.m[0][2] = 0.0f;
|
||||
mtx.m[1][2] = 0.0f;
|
||||
mtx.m[2][2] = pMatrix[4];
|
||||
mtx.m[3][2] = -(-1 - pMatrix[5]);
|
||||
|
||||
mtx.m[0][3] = 0;
|
||||
mtx.m[1][3] = 0;
|
||||
mtx.m[2][3] = 0.0f;
|
||||
mtx.m[3][3] = 1.0f;
|
||||
}
|
||||
D3D::dev->SetVertexShaderConstantF(constantIndex, mtx, 4);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "PluginSpecs_Video.h"
|
||||
|
||||
class Renderer
|
||||
{
|
||||
// screen offset
|
||||
static float m_x,m_y,m_width, m_height,xScale,yScale;
|
||||
|
||||
public:
|
||||
|
||||
static void Init(SVideoInitialize &_VideoInitialize);
|
||||
static void Shutdown();
|
||||
|
||||
// initialize opengl standard values (like viewport)
|
||||
static void Initialize(void);
|
||||
// must be called if the windowsize has changed
|
||||
static void ReinitView(void);
|
||||
//
|
||||
// --- Render Functions ---
|
||||
//
|
||||
static void SwapBuffers(void);
|
||||
static void Flush(void);
|
||||
static float GetXScale(){return xScale;}
|
||||
static float GetYScale(){return yScale;}
|
||||
|
||||
static void SetScissorBox(RECT &rc);
|
||||
static void SetViewport(float* _Viewport);
|
||||
static void SetProjection(float* _pProjection, int constantIndex = -1);
|
||||
};
|
||||
@@ -0,0 +1,153 @@
|
||||
#include "D3DBase.h"
|
||||
#include "Utils.h"
|
||||
#include "Globals.h"
|
||||
#include "ShaderManager.h"
|
||||
|
||||
PShaderCache::PSCache PShaderCache::pshaders;
|
||||
VShaderCache::VSCache VShaderCache::vshaders;
|
||||
|
||||
void PShaderCache::Init()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void PShaderCache::Shutdown()
|
||||
{
|
||||
PSCache::iterator iter = pshaders.begin();
|
||||
for (;iter!=pshaders.end();iter++)
|
||||
iter->second.Destroy();
|
||||
pshaders.clear();
|
||||
}
|
||||
|
||||
|
||||
void PShaderCache::SetShader()
|
||||
{
|
||||
if (D3D::GetShaderVersion() < 2)
|
||||
return; // we are screwed
|
||||
|
||||
static LPDIRECT3DPIXELSHADER9 lastShader = 0;
|
||||
DVSTARTPROFILE();
|
||||
|
||||
tevhash currentHash = GetCurrentTEV();
|
||||
|
||||
PSCache::iterator iter;
|
||||
iter = pshaders.find(currentHash);
|
||||
|
||||
if (iter != pshaders.end())
|
||||
{
|
||||
iter->second.frameCount=frameCount;
|
||||
PSCacheEntry &entry = iter->second;
|
||||
if (!lastShader || entry.shader != lastShader)
|
||||
{
|
||||
D3D::dev->SetPixelShader(entry.shader);
|
||||
lastShader = entry.shader;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 shader = GeneratePixelShader();
|
||||
|
||||
if (shader)
|
||||
{
|
||||
//Make an entry in the table
|
||||
PSCacheEntry newentry;
|
||||
newentry.shader = shader;
|
||||
newentry.frameCount=frameCount;
|
||||
pshaders[currentHash] = newentry;
|
||||
}
|
||||
|
||||
D3D::dev->SetPixelShader(shader);
|
||||
|
||||
INCSTAT(stats.numPixelShadersCreated);
|
||||
SETSTAT(stats.numPixelShadersAlive, (int)pshaders.size());
|
||||
}
|
||||
|
||||
void PShaderCache::Cleanup()
|
||||
{
|
||||
PSCache::iterator iter;
|
||||
iter = pshaders.begin();
|
||||
|
||||
while(iter!=pshaders.end())
|
||||
{
|
||||
PSCacheEntry &entry = iter->second;
|
||||
if (entry.frameCount<frameCount-30)
|
||||
{
|
||||
entry.Destroy();
|
||||
iter = pshaders.erase(iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
SETSTAT(stats.numPixelShadersAlive, (int)pshaders.size());
|
||||
}
|
||||
|
||||
|
||||
void VShaderCache::Init()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void VShaderCache::Shutdown()
|
||||
{
|
||||
VSCache::iterator iter = vshaders.begin();
|
||||
for (;iter!=vshaders.end();iter++)
|
||||
iter->second.Destroy();
|
||||
vshaders.clear();
|
||||
}
|
||||
|
||||
|
||||
void VShaderCache::SetShader()
|
||||
{
|
||||
static LPDIRECT3DVERTEXSHADER9 lastShader = 0;
|
||||
xformhash currentHash = GetCurrentXForm();
|
||||
|
||||
VSCache::iterator iter;
|
||||
iter = vshaders.find(currentHash);
|
||||
|
||||
if (iter != vshaders.end())
|
||||
{
|
||||
iter->second.frameCount=frameCount;
|
||||
VSCacheEntry &entry = iter->second;
|
||||
if (!lastShader || entry.shader != lastShader)
|
||||
{
|
||||
D3D::dev->SetVertexShader(entry.shader);
|
||||
lastShader = entry.shader;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
LPDIRECT3DVERTEXSHADER9 shader = GenerateVertexShader();
|
||||
|
||||
if (shader)
|
||||
{
|
||||
//Make an entry in the table
|
||||
VSCacheEntry entry;
|
||||
entry.shader = shader;
|
||||
entry.frameCount=frameCount;
|
||||
vshaders[currentHash] = entry;
|
||||
}
|
||||
D3D::dev->SetVertexShader(shader);
|
||||
|
||||
INCSTAT(stats.numVertexShadersCreated);
|
||||
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
|
||||
}
|
||||
|
||||
void VShaderCache::Cleanup()
|
||||
{
|
||||
for (VSCache::iterator iter=vshaders.begin(); iter!=vshaders.end();iter++)
|
||||
{
|
||||
VSCacheEntry &entry = iter->second;
|
||||
if (entry.frameCount<frameCount-30)
|
||||
{
|
||||
entry.Destroy();
|
||||
iter = vshaders.erase(iter);
|
||||
}
|
||||
}
|
||||
SETSTAT(stats.numPixelShadersAlive, (int)vshaders.size());
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
#include "D3DBase.h"
|
||||
|
||||
#include <map>
|
||||
#include "PixelShader.h"
|
||||
#include "VertexShader.h"
|
||||
|
||||
|
||||
|
||||
class PShaderCache
|
||||
{
|
||||
struct PSCacheEntry
|
||||
{
|
||||
LPDIRECT3DPIXELSHADER9 shader;
|
||||
//CGPShader shader;
|
||||
|
||||
int frameCount;
|
||||
PSCacheEntry()
|
||||
{
|
||||
shader=0;
|
||||
frameCount=0;
|
||||
}
|
||||
void Destroy()
|
||||
{
|
||||
if (shader)
|
||||
shader->Release();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef std::map<tevhash,PSCacheEntry> PSCache;
|
||||
|
||||
static PSCache pshaders;
|
||||
|
||||
public:
|
||||
static void Init();
|
||||
static void Cleanup();
|
||||
static void Shutdown();
|
||||
static void SetShader();
|
||||
};
|
||||
|
||||
|
||||
|
||||
class VShaderCache
|
||||
{
|
||||
struct VSCacheEntry
|
||||
{
|
||||
LPDIRECT3DVERTEXSHADER9 shader;
|
||||
//CGVShader shader;
|
||||
int frameCount;
|
||||
VSCacheEntry()
|
||||
{
|
||||
shader=0;
|
||||
frameCount=0;
|
||||
}
|
||||
void Destroy()
|
||||
{
|
||||
if (shader)
|
||||
shader->Release();
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<xformhash,VSCacheEntry> VSCache;
|
||||
|
||||
static VSCache vshaders;
|
||||
|
||||
|
||||
public:
|
||||
static void Init();
|
||||
static void Cleanup();
|
||||
static void Shutdown();
|
||||
static void SetShader();
|
||||
};
|
||||
|
||||
void InitCG();
|
||||
void ShutdownCG();
|
||||
@@ -0,0 +1,214 @@
|
||||
#include <d3dx9.h>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "D3Dtexture.h"
|
||||
|
||||
#include "Render.h"
|
||||
|
||||
#include "TextureDecoder.h"
|
||||
#include "TextureCache.h"
|
||||
|
||||
#include "Globals.h"
|
||||
#include "main.h"
|
||||
|
||||
u8 *TextureCache::temp = NULL;
|
||||
TextureCache::TexCache TextureCache::textures;
|
||||
|
||||
extern int frameCount;
|
||||
|
||||
#define TEMP_SIZE (1024*1024*4)
|
||||
|
||||
void TextureCache::TCacheEntry::Destroy()
|
||||
{
|
||||
if (texture)
|
||||
texture->Release();
|
||||
}
|
||||
|
||||
void TextureCache::Init()
|
||||
{
|
||||
temp = (u8*)VirtualAlloc(0,TEMP_SIZE,MEM_COMMIT,PAGE_READWRITE);
|
||||
}
|
||||
|
||||
void TextureCache::Invalidate()
|
||||
{
|
||||
TexCache::iterator iter = textures.begin();
|
||||
for (;iter!=textures.end();iter++)
|
||||
iter->second.Destroy();
|
||||
textures.clear();
|
||||
}
|
||||
|
||||
void TextureCache::Shutdown()
|
||||
{
|
||||
Invalidate();
|
||||
|
||||
VirtualFree(temp, 0, MEM_RELEASE);
|
||||
temp = NULL;
|
||||
}
|
||||
|
||||
void TextureCache::Cleanup()
|
||||
{
|
||||
TexCache::iterator iter=textures.begin();
|
||||
|
||||
while(iter!=textures.end())
|
||||
{
|
||||
if (frameCount>20+iter->second.frameCount)
|
||||
{
|
||||
if (!iter->second.isRenderTarget)
|
||||
{
|
||||
u32 *ptr = (u32*)g_VideoInitialize.pGetMemoryPointer(iter->second.addr + iter->second.hashoffset*4);
|
||||
if (*ptr == iter->second.hash)
|
||||
*ptr = iter->second.oldpixel;
|
||||
iter->second.Destroy();
|
||||
iter = textures.erase(iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCache::Load(int stage, DWORD address, int width, int height, int format, int tlutaddr, int tlutfmt)
|
||||
{
|
||||
if (address == 0)
|
||||
return;
|
||||
TexCache::iterator iter = textures.find(address);
|
||||
|
||||
u8 *ptr = g_VideoInitialize.pGetMemoryPointer(address);
|
||||
|
||||
int palSize = TexDecoder_GetPaletteSize(format);
|
||||
u32 palhash = 0xc0debabe;
|
||||
if (palSize)
|
||||
{
|
||||
if (palSize>16)
|
||||
palSize = 16; //let's not do excessive amount of checking
|
||||
u8 *pal = g_VideoInitialize.pGetMemoryPointer(tlutaddr);
|
||||
if (pal != 0)
|
||||
{
|
||||
for (int i=0; i<palSize; i++)
|
||||
{
|
||||
palhash = _rotl(palhash,13);
|
||||
palhash ^= pal[i];
|
||||
palhash += 31;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static LPDIRECT3DTEXTURE9 lastTexture[8] = {0,0,0,0,0,0,0,0};
|
||||
|
||||
if (iter != textures.end())
|
||||
{
|
||||
TCacheEntry &entry = iter->second;
|
||||
|
||||
if (entry.isRenderTarget || (((u32 *)ptr)[entry.hashoffset] == entry.hash && palhash == entry.paletteHash)) //stupid, improve
|
||||
{
|
||||
iter->second.frameCount = frameCount;
|
||||
if (lastTexture[stage] == iter->second.texture)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lastTexture[stage] = iter->second.texture;
|
||||
D3D::dev->SetTexture(stage,iter->second.texture);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
TCacheEntry &entry = iter->second;
|
||||
/* if (width == iter->second.w && height==entry.h && format==entry.fmt)
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 tex = entry.texture;
|
||||
int bs = TexDecoder_GetBlockWidthInTexels(format)-1; //TexelSizeInNibbles(format)*width*height/16;
|
||||
int expandedWidth = (width+bs) & (~bs);
|
||||
D3DFORMAT dfmt = TexDecoder_Decode(temp,ptr,expandedWidth,height,format, tlutaddr, tlutfmt);
|
||||
D3D::ReplaceTexture2D(tex,temp,width,height,expandedWidth,dfmt);
|
||||
D3D::dev->SetTexture(stage,tex);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{*/
|
||||
iter->second.Destroy();
|
||||
textures.erase(iter);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
int bs = TexDecoder_GetBlockWidthInTexels(format)-1; //TexelSizeInNibbles(format)*width*height/16;
|
||||
int expandedWidth = (width+bs) & (~bs);
|
||||
D3DFORMAT dfmt = TexDecoder_Decode(temp,ptr,expandedWidth,height,format, tlutaddr, tlutfmt);
|
||||
|
||||
//Make an entry in the table
|
||||
TCacheEntry entry;
|
||||
entry.hashoffset = 0;
|
||||
entry.hash = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF);
|
||||
entry.paletteHash = palhash;
|
||||
entry.oldpixel = ((u32 *)ptr)[entry.hashoffset];
|
||||
((u32 *)ptr)[entry.hashoffset] = entry.hash;
|
||||
|
||||
entry.addr = address;
|
||||
entry.isRenderTarget=false;
|
||||
entry.isNonPow2 = ((width&(width-1)) || (height&(height-1)));
|
||||
entry.texture = D3D::CreateTexture2D((BYTE*)temp,width,height,expandedWidth,dfmt);
|
||||
entry.frameCount = frameCount;
|
||||
entry.w=width;
|
||||
entry.h=height;
|
||||
entry.fmt=format;
|
||||
textures[address] = entry;
|
||||
|
||||
if (g_Config.bDumpTextures)
|
||||
{ // dump texture to file
|
||||
static int counter = 0;
|
||||
char szTemp[MAX_PATH];
|
||||
sprintf(szTemp, "%s\\txt_%04i_%i.png", g_Config.texDumpPath, counter++, format);
|
||||
|
||||
D3DXSaveTextureToFile(szTemp,D3DXIFF_BMP,entry.texture,0);
|
||||
}
|
||||
|
||||
INCSTAT(stats.numTexturesCreated);
|
||||
SETSTAT(stats.numTexturesAlive, (int)textures.size());
|
||||
|
||||
//Set the texture!
|
||||
D3D::dev->SetTexture(stage,entry.texture);
|
||||
lastTexture[stage] = entry.texture;
|
||||
}
|
||||
|
||||
|
||||
void TextureCache::CopyEFBToRenderTarget(DWORD address, RECT *source)
|
||||
{
|
||||
TexCache::iterator iter;
|
||||
LPDIRECT3DTEXTURE9 tex;
|
||||
iter = textures.find(address);
|
||||
if (iter != textures.end())
|
||||
{
|
||||
if (!iter->second.isRenderTarget)
|
||||
{
|
||||
g_VideoInitialize.pLog("Using non-rendertarget texture as render target!!! WTF?", FALSE);
|
||||
//TODO: remove it and recreate it as a render target
|
||||
}
|
||||
tex = iter->second.texture;
|
||||
iter->second.frameCount=frameCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
TCacheEntry entry;
|
||||
entry.isRenderTarget=true;
|
||||
entry.hash = 0;
|
||||
entry.hashoffset = 0;
|
||||
entry.frameCount = frameCount;
|
||||
// TODO(ector): infer this size in some sensible way
|
||||
D3D::dev->CreateTexture(512,512,1,D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &entry.texture, 0);
|
||||
textures[address] = entry;
|
||||
tex = entry.texture;
|
||||
}
|
||||
LPDIRECT3DSURFACE9 srcSurface,destSurface;
|
||||
tex->GetSurfaceLevel(0,&destSurface);
|
||||
srcSurface = D3D::GetBackBufferSurface();
|
||||
D3D::dev->StretchRect(srcSurface,source,destSurface,0,D3DTEXF_NONE);
|
||||
destSurface->Release();
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#ifndef _TEXTURECACHE_H
|
||||
#define _TEXTURECACHE_H
|
||||
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "D3DBase.h"
|
||||
|
||||
class TextureCache
|
||||
{
|
||||
struct TCacheEntry
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 texture;
|
||||
u32 addr;
|
||||
u32 hash;
|
||||
u32 paletteHash;
|
||||
u32 hashoffset;
|
||||
u32 oldpixel;
|
||||
bool isRenderTarget;
|
||||
bool isNonPow2;
|
||||
int frameCount;
|
||||
int w,h,fmt;
|
||||
TCacheEntry()
|
||||
{
|
||||
texture=0;
|
||||
isRenderTarget=0;
|
||||
hash=0;
|
||||
}
|
||||
void Destroy();
|
||||
};
|
||||
|
||||
|
||||
typedef std::map<DWORD,TCacheEntry> TexCache;
|
||||
|
||||
static u8 *temp;
|
||||
static TexCache textures;
|
||||
|
||||
public:
|
||||
static void Init();
|
||||
static void Cleanup();
|
||||
static void Shutdown();
|
||||
static void Invalidate();
|
||||
static void Load(int stage, DWORD address, int width, int height, int format, int tlutaddr, int tlutfmt);
|
||||
static void CopyEFBToRenderTarget(DWORD address, RECT *source);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,447 @@
|
||||
#include "stdafx.h"
|
||||
#include "D3DBase.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#include "BPStructs.h"
|
||||
#include "TextureDecoder.h"
|
||||
|
||||
#include "OpcodeDecoding.h"
|
||||
|
||||
|
||||
// TRAM
|
||||
u8 texMem[TMEM_SIZE];
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Gamecube texture decoder
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Decodes all known Gamecube texture formats.
|
||||
// TODO - speedup
|
||||
// by ector
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int TexDecoder_GetTexelSizeInNibbles(int format)
|
||||
{
|
||||
switch(format) {
|
||||
case GX_TF_I4: return 1;
|
||||
case GX_TF_I8: return 2;
|
||||
case GX_TF_IA4: return 2;
|
||||
case GX_TF_IA8: return 4;
|
||||
case GX_TF_RGB565: return 4;
|
||||
case GX_TF_RGB5A3: return 4;
|
||||
case GX_TF_RGBA8: return 8;
|
||||
case GX_TF_C4: return 1;
|
||||
case GX_TF_C8: return 2;
|
||||
case GX_TF_C14X2: return 4;
|
||||
case GX_TF_CMPR: return 1;
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
int TexDecoder_GetBlockWidthInTexels(int format)
|
||||
{
|
||||
switch(format) {
|
||||
case GX_TF_I4: return 8;
|
||||
case GX_TF_I8: return 8;
|
||||
case GX_TF_IA4: return 8;
|
||||
case GX_TF_IA8: return 4;
|
||||
case GX_TF_RGB565: return 4;
|
||||
case GX_TF_RGB5A3: return 4;
|
||||
case GX_TF_RGBA8: return 4;
|
||||
case GX_TF_C4: return 8;
|
||||
case GX_TF_C8: return 8;
|
||||
case GX_TF_C14X2: return 4;
|
||||
case GX_TF_CMPR: return 8;
|
||||
default:return 8;
|
||||
}
|
||||
}
|
||||
|
||||
//returns bytes
|
||||
int TexDecoder_GetPaletteSize(int format)
|
||||
{
|
||||
switch (format) {
|
||||
case GX_TF_C4: return 16*2;
|
||||
case GX_TF_C8: return 256*2;
|
||||
case GX_TF_C14X2: return 16384*2;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline u32 decode565(u16 val)
|
||||
{
|
||||
int r,g,b,a;
|
||||
r=lut5to8[(val>>11)&0x1f];
|
||||
g=lut6to8[(val>>5 )&0x3f];
|
||||
b=lut5to8[(val )&0x1f];
|
||||
a=0xFF;
|
||||
return (a<<24) | (r<<16) | (g<<8) | b;
|
||||
}
|
||||
|
||||
inline u32 decodeIA8(u16 val)
|
||||
{
|
||||
int a=val>>8;
|
||||
int r,g,b;
|
||||
r=g=b=val&0xFF;
|
||||
return (a<<24) | (r<<16) | (g<<8) | b;
|
||||
}
|
||||
|
||||
inline u32 decode5A3(u16 val)
|
||||
{
|
||||
int r,g,b,a;
|
||||
if ((val&0x8000))
|
||||
{
|
||||
r=lut5to8[(val>>10)&0x1f];
|
||||
g=lut5to8[(val>>5 )&0x1f];
|
||||
b=lut5to8[(val )&0x1f];
|
||||
a=0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
a=lut3to8[(val>>12)&0x7];
|
||||
r=lut4to8[(val>>8 )&0xf];
|
||||
g=lut4to8[(val>>4 )&0xf];
|
||||
b=lut4to8[(val )&0xf];
|
||||
}
|
||||
return (a<<24) | (r<<16) | (g<<8) | b;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct DXTBlock
|
||||
{
|
||||
u16 color1;
|
||||
u16 color2;
|
||||
u8 lines[4];
|
||||
};
|
||||
|
||||
inline int expand8888(const int j)
|
||||
{
|
||||
int i = j | (j<<8);
|
||||
return i|(i<<16);
|
||||
}
|
||||
|
||||
void decodebytesI4(u32 *dst, u8 *src, int numbytes)
|
||||
{
|
||||
for (int x=0; x<numbytes; x++)
|
||||
{
|
||||
int val = src[x];
|
||||
*dst++ = expand8888(lut4to8[val>>4]);
|
||||
*dst++ = expand8888(lut4to8[val&15]);
|
||||
}
|
||||
}
|
||||
|
||||
void decodebytesI8(u32 *dst, u8 *src, int numbytes)
|
||||
{
|
||||
for (int x=0; x<numbytes; x++)
|
||||
*dst++ = expand8888(src[x]); //asm bswap loop?
|
||||
}
|
||||
|
||||
void decodebytesC4(u32 *dst, u8 *src, int numbytes, int tlutaddr, int tlutfmt)
|
||||
{
|
||||
u16 *tlut = (u16*)(texMem+tlutaddr);
|
||||
for (int x=0; x<numbytes; x++)
|
||||
{
|
||||
int val = src[x];
|
||||
switch(tlutfmt) {
|
||||
case 0:
|
||||
*dst++ = decodeIA8(_byteswap_ushort(tlut[(val>>4)]));
|
||||
*dst++ = decodeIA8(_byteswap_ushort(tlut[(val&15)]));
|
||||
break;
|
||||
case 1:
|
||||
*dst++ = decode565(_byteswap_ushort(tlut[(val>>4)]));
|
||||
*dst++ = decode565(_byteswap_ushort(tlut[(val&15)]));
|
||||
break;
|
||||
case 2:
|
||||
*dst++ = decode5A3(_byteswap_ushort(tlut[(val>>4)]));
|
||||
*dst++ = decode5A3(_byteswap_ushort(tlut[(val&15)]));
|
||||
break;
|
||||
case 3: //ERROR
|
||||
*dst++ = 0xFFFF00FF;
|
||||
*dst++ = 0xFFFF00FF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void decodebytesC8(u32 *dst, u8 *src, int numbytes, int tlutaddr, int tlutfmt)
|
||||
{
|
||||
u16 *tlut = (u16*)(texMem+tlutaddr);
|
||||
for (int x=0; x<numbytes; x++)
|
||||
{
|
||||
int val = src[x];
|
||||
switch(tlutfmt) {
|
||||
case 0:
|
||||
*dst++ = decodeIA8(_byteswap_ushort(tlut[val]));
|
||||
break;
|
||||
case 1:
|
||||
*dst++ = decode565(_byteswap_ushort(tlut[val]));
|
||||
break;
|
||||
case 2:
|
||||
*dst++ = decode5A3(_byteswap_ushort(tlut[val]));
|
||||
break;
|
||||
case 3: //ERROR
|
||||
*dst++ = 0xFFFF00FF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void decodebytesC14X2(u32 *dst, u16 *src, int numpixels, int tlutaddr, int tlutfmt)
|
||||
{
|
||||
u16 *tlut = (u16*)(texMem+tlutaddr);
|
||||
for (int x=0; x<numpixels; x++)
|
||||
{
|
||||
int val = _byteswap_ushort(src[x]);
|
||||
switch(tlutfmt) {
|
||||
case 0:
|
||||
*dst++ = decodeIA8(_byteswap_ushort(tlut[(val&0x3FFF)]));
|
||||
break;
|
||||
case 1:
|
||||
*dst++ = decode565(_byteswap_ushort(tlut[(val&0x3FFF)]));
|
||||
break;
|
||||
case 2:
|
||||
*dst++ = decode5A3(_byteswap_ushort(tlut[(val&0x3FFF)]));
|
||||
break;
|
||||
case 3: //ERROR
|
||||
*dst++ = 0xFFFF00FF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void decodebytesRGB565(u32 *dst, u16 *src, int numpixels)
|
||||
{
|
||||
for (int x=0; x<numpixels; x++)
|
||||
*dst++ = decode565(_byteswap_ushort(src[x]));
|
||||
}
|
||||
|
||||
void decodebytesIA4(u32 *dst, u8 *src, int numbytes)
|
||||
{
|
||||
for (int x=0; x<numbytes; x++)
|
||||
{
|
||||
int val = src[x];
|
||||
|
||||
int a = lut4to8[val>>4];
|
||||
int r = lut4to8[val&15];
|
||||
*dst++ = (a<<24) | (r<<16) | (r<<8) | r;
|
||||
}
|
||||
}
|
||||
|
||||
inline void decodebytesIA8(u32 *dst, u16 *src, int numpixels)
|
||||
{
|
||||
for (int x=0; x<numpixels; x++)
|
||||
*dst++ = decodeIA8(_byteswap_ushort(src[x]));
|
||||
}
|
||||
|
||||
inline void decodebytesRGB5A3(u32 *dst, u16 *src, int numpixels)
|
||||
{
|
||||
for (int x=0; x<numpixels; x++)
|
||||
*dst++ = decode5A3(_byteswap_ushort(src[x]));
|
||||
}
|
||||
|
||||
void decodebytesARGB8pass1(u32 *dst, u16 *src, int numpixels)
|
||||
{
|
||||
for (int x=0; x<numpixels; x++)
|
||||
{
|
||||
int val = _byteswap_ushort(src[x]);
|
||||
int a=val&0xFF;
|
||||
val>>=8;
|
||||
|
||||
*dst++ = (a<<16) | (val<<24);
|
||||
}
|
||||
}
|
||||
void decodebytesARGB8pass2(u32 *dst, u16 *src, int numpixels)
|
||||
{
|
||||
for (int x=0; x<numpixels; x++)
|
||||
{
|
||||
int val = _byteswap_ushort(src[x]);
|
||||
int a=val&0xFF;
|
||||
val>>=8;
|
||||
|
||||
*dst++ |= (val<<8) | (a<<0);
|
||||
}
|
||||
}
|
||||
|
||||
inline u32 makecol(int r,int g,int b,int a)
|
||||
{
|
||||
return ((a&255)<<24)|((r&255)<<16)|((g&255)<<8)|((b&255));
|
||||
}
|
||||
|
||||
|
||||
//this needs to be FAST, used by some games realtime video
|
||||
//TODO: port to ASM or intrinsics
|
||||
void decodeDXTBlock(u32 *dst, DXTBlock *src, int pitch)
|
||||
{
|
||||
u16 c1 = _byteswap_ushort(src->color1);
|
||||
u16 c2 = _byteswap_ushort(src->color2);
|
||||
int blue1 = lut5to8[c1&0x1F];
|
||||
int blue2 = lut5to8[c2&0x1F];
|
||||
int green1 = lut6to8[(c1>>5)&0x3F];
|
||||
int green2 = lut6to8[(c2>>5)&0x3F];
|
||||
int red1 = lut5to8[(c1>>11)&0x1F];
|
||||
int red2 = lut5to8[(c2>>11)&0x1F];
|
||||
|
||||
int colors[4];
|
||||
|
||||
if (c1>c2)
|
||||
{
|
||||
colors[0]=makecol(red1,green1,blue1,255);
|
||||
colors[1]=makecol(red2,green2,blue2,255);
|
||||
colors[2]=makecol(red1+(red2-red1)/3,green1+(green2-green1)/3,blue1+(blue2-blue1)/3,255);
|
||||
colors[3]=makecol(red2+(red1-red2)/3,green2+(green1-green2)/3,blue2+(blue1-blue2)/3,255);
|
||||
}
|
||||
else
|
||||
{
|
||||
colors[0]=makecol(red1,green1,blue1,255);
|
||||
colors[1]=makecol(red2,green2,blue2,255);
|
||||
colors[2]=makecol((red1+red2)/2,(green1+green2)/2,(blue1+blue2)/2,255);
|
||||
colors[3]=makecol(0,0,0,0); //transparent
|
||||
}
|
||||
|
||||
for (int y=0; y<4; y++)
|
||||
{
|
||||
int val = src->lines[y];
|
||||
for (int x=0; x<4; x++)
|
||||
{
|
||||
dst[x] = colors[(val>>6)&3];
|
||||
val<<=2;
|
||||
}
|
||||
dst+=pitch;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//switch endianness, unswizzle
|
||||
//TODO: to save memory, don't blindly convert everything to argb8888
|
||||
//also ARGB order needs to be swapped later, to accommodate modern hardware better
|
||||
//need to add DXT support too
|
||||
D3DFORMAT TexDecoder_Decode(u8 *dst, u8 *src, int width, int height, int texformat, int tlutaddr, int tlutfmt)
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
|
||||
switch (texformat)
|
||||
{
|
||||
case GX_TF_C4:
|
||||
{
|
||||
for (int y=0; y<height; y+=8)
|
||||
for (int x=0; x<width; x+=8)
|
||||
for (int iy=0; iy<8; iy++, src+=4)
|
||||
decodebytesC4((u32*)dst+(y+iy)*width+x,src,4,tlutaddr,tlutfmt);
|
||||
}
|
||||
return D3DFMT_A8R8G8B8;
|
||||
case GX_TF_I4:
|
||||
{
|
||||
for (int y=0; y<height; y+=8)
|
||||
for (int x=0; x<width; x+=8)
|
||||
for (int iy=0; iy<8; iy++, src+=4)
|
||||
decodebytesI4((u32*)dst+(y+iy)*width+x,src,4);
|
||||
}
|
||||
return D3DFMT_A8R8G8B8;
|
||||
case GX_TF_C8:
|
||||
{
|
||||
for (int y=0; y<height; y+=4)
|
||||
for (int x=0; x<width; x+=8)
|
||||
for (int iy=0; iy<4; iy++, src+=8)
|
||||
decodebytesC8((u32*)dst+(y+iy)*width+x,src,8,tlutaddr,tlutfmt);
|
||||
}
|
||||
return D3DFMT_A8R8G8B8;
|
||||
case GX_TF_I8:
|
||||
{
|
||||
for (int y=0; y<height; y+=4)
|
||||
for (int x=0; x<width; x+=8)
|
||||
for (int iy=0; iy<4; iy++, src+=8)
|
||||
decodebytesI8((u32*)dst+(y+iy)*width+x,src,8);
|
||||
}
|
||||
return D3DFMT_A8R8G8B8;
|
||||
case GX_TF_IA4:
|
||||
{
|
||||
for (int y=0; y<height; y+=4)
|
||||
for (int x=0; x<width; x+=8)
|
||||
for (int iy=0; iy<4; iy++, src+=8)
|
||||
decodebytesIA4((u32*)dst+(y+iy)*width+x,src,8);
|
||||
}
|
||||
return D3DFMT_A8R8G8B8;
|
||||
case GX_TF_IA8:
|
||||
{
|
||||
for (int y=0; y<height; y+=4)
|
||||
for (int x=0; x<width; x+=4)
|
||||
for (int iy=0; iy<4; iy++,src+=8)
|
||||
decodebytesIA8((u32*)dst+(y+iy)*width+x,(u16*)src,4);
|
||||
}
|
||||
return D3DFMT_A8R8G8B8;
|
||||
case GX_TF_C14X2:
|
||||
{
|
||||
for (int y=0; y<height; y+=4)
|
||||
for (int x=0; x<width; x+=4)
|
||||
for (int iy=0; iy<4; iy++,src+=8)
|
||||
decodebytesC14X2((u32*)dst+(y+iy)*width+x,(u16*)src,4,tlutaddr,tlutfmt);
|
||||
}
|
||||
return D3DFMT_A8R8G8B8;
|
||||
case GX_TF_RGB565:
|
||||
{
|
||||
for (int y=0; y<height; y+=4)
|
||||
for (int x=0; x<width; x+=4)
|
||||
for (int iy=0; iy<4; iy++,src+=8)
|
||||
decodebytesRGB565((u32*)dst+(y+iy)*width+x,(u16*)src,4);
|
||||
}
|
||||
return D3DFMT_A8R8G8B8;
|
||||
case GX_TF_RGB5A3:
|
||||
{
|
||||
for (int y=0; y<height; y+=4)
|
||||
for (int x=0; x<width; x+=4)
|
||||
for (int iy=0; iy<4; iy++,src+=8)
|
||||
decodebytesRGB5A3((u32*)dst+(y+iy)*width+x,(u16*)src,4);
|
||||
}
|
||||
return D3DFMT_A8R8G8B8;
|
||||
case GX_TF_RGBA8:
|
||||
{
|
||||
for (int y=0; y<height; y+=4)
|
||||
for (int x=0; x<width; x+=4)
|
||||
{
|
||||
for (int iy=0; iy<4; iy++,src+=8)
|
||||
decodebytesARGB8pass1((u32*)dst+(y+iy)*width+x,(u16*)src,4);
|
||||
for (int iy=0; iy<4; iy++,src+=8)
|
||||
decodebytesARGB8pass2((u32*)dst+(y+iy)*width+x,(u16*)src,4);
|
||||
}
|
||||
}
|
||||
return D3DFMT_A8R8G8B8;
|
||||
case GX_TF_CMPR:
|
||||
{
|
||||
// 11111111 22222222 55555555 66666666
|
||||
// 33333333 44444444 77777777 88888888
|
||||
|
||||
|
||||
for (int y=0; y<height; y+=8)
|
||||
for (int x=0; x<width; x+=8)
|
||||
{
|
||||
decodeDXTBlock((u32*)dst+y*width+x,(DXTBlock*)src,width);src+=sizeof(DXTBlock);
|
||||
decodeDXTBlock((u32*)dst+y*width+x+4,(DXTBlock*)src,width);src+=sizeof(DXTBlock);
|
||||
decodeDXTBlock((u32*)dst+(y+4)*width+x,(DXTBlock*)src,width);src+=sizeof(DXTBlock);
|
||||
decodeDXTBlock((u32*)dst+(y+4)*width+x+4,(DXTBlock*)src,width);src+=sizeof(DXTBlock);
|
||||
}
|
||||
|
||||
/*
|
||||
int rowlen = width/2;
|
||||
int numBigBlockRows = height/8;
|
||||
int numBigBlocksPerRow = width/8;
|
||||
int numSmallBlocksPerRow = width/4;
|
||||
int numSmallBlockRows = height/4;
|
||||
int smallBlockSize = 8;
|
||||
for (int y=0; y<height/8; y+=8)
|
||||
{
|
||||
for (int x=0; x<width/8; x+=8)
|
||||
{
|
||||
memcpy(dst+y*2*numSmallBlocksPerRow*smallBlockSize+x*2*smallBlockSize,src,smallBlockSize); src+=smallBlockSize;
|
||||
memcpy(dst+y*2*numSmallBlocksPerRow*smallBlockSize+(x*2+1)*smallBlockSize,src,smallBlockSize); src+=smallBlockSize;
|
||||
memcpy(dst+(y*2+1)*numSmallBlocksPerRow*smallBlockSize+x*2*smallBlockSize,src,smallBlockSize); src+=smallBlockSize;
|
||||
memcpy(dst+(y*2+1)*numSmallBlocksPerRow*smallBlockSize+(x*2+1)*smallBlockSize,src,smallBlockSize); src+=smallBlockSize;
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
return D3DFMT_A8R8G8B8;
|
||||
// return D3DFMT_DXT1;
|
||||
}
|
||||
return D3DFMT_UNKNOWN;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef _TEXTUREDECODER_H
|
||||
#define _TEXTUREDECODER_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "D3DBase.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
TMEM_SIZE = 1024*1024,
|
||||
HALFTMEM_SIZE = 512*1024
|
||||
};
|
||||
extern u8 texMem[TMEM_SIZE];
|
||||
|
||||
|
||||
enum TextureFormat
|
||||
{
|
||||
GX_TF_I4 = 0x0,
|
||||
GX_TF_I8 = 0x1,
|
||||
GX_TF_IA4 = 0x2,
|
||||
GX_TF_IA8 = 0x3,
|
||||
GX_TF_RGB565 = 0x4,
|
||||
GX_TF_RGB5A3 = 0x5,
|
||||
GX_TF_RGBA8 = 0x6,
|
||||
GX_TF_C4 = 0x8,
|
||||
GX_TF_C8 = 0x9,
|
||||
GX_TF_C14X2 = 0xA,
|
||||
GX_TF_CMPR = 0xE,
|
||||
|
||||
_GX_TF_CTF = 0x20, /* copy-texture-format only */
|
||||
_GX_TF_ZTF = 0x10, /* Z-texture-format */
|
||||
|
||||
GX_TF_Z8 = 0x1 | _GX_TF_ZTF,
|
||||
GX_TF_Z16 = 0x3 | _GX_TF_ZTF,
|
||||
GX_TF_Z24X8 = 0x6 | _GX_TF_ZTF,
|
||||
|
||||
//and the strange copy texture formats..
|
||||
|
||||
|
||||
};
|
||||
|
||||
int TexDecoder_GetTexelSizeInNibbles(int format);
|
||||
int TexDecoder_GetBlockWidthInTexels(int format);
|
||||
int TexDecoder_GetPaletteSize(int fmt);
|
||||
|
||||
D3DFORMAT TexDecoder_Decode(u8 *dst, u8 *src, int width, int height, int texformat, int tlutaddr, int tlutfmt);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,347 @@
|
||||
#include "Common.h"
|
||||
#include "Globals.h"
|
||||
#include "TransformEngine.h"
|
||||
#include "VertexHandler.h"
|
||||
#include "VertexLoader.h"
|
||||
|
||||
#include "BPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#include "RGBAFloat.h"
|
||||
|
||||
float *CTransformEngine::m_pPosMatrix;
|
||||
float *CTransformEngine::m_pNormalMatrix;
|
||||
float *CTransformEngine::m_pTexMatrix[8];
|
||||
float *CTransformEngine::m_pTexPostMatrix[8];
|
||||
|
||||
size_t CTransformEngine::SaveLoadState(char *ptr, bool save)
|
||||
{
|
||||
// BEGINSAVELOAD;
|
||||
// SAVELOAD(m_VtxAttribTable,sizeof(m_VtxAttribTable));
|
||||
// SAVELOAD(&m_VtxDesc,sizeof(TVtxDesc));
|
||||
// ENDSAVELOAD;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Light *GetLight(int i)
|
||||
{
|
||||
return (const Light *)(xfmem + XFMEM_LIGHTS) + i;
|
||||
}
|
||||
|
||||
float DoLighting(const Light *light, const LitChannel &chan, const Vec3 &pos, const Vec3 &normal)
|
||||
{
|
||||
float val;
|
||||
if (chan.attnfunc == 0 || chan.attnfunc == 2) //no attn
|
||||
{
|
||||
Vec3 ldir = (light->dpos-pos);
|
||||
val = ldir.normalized() * normal;
|
||||
}
|
||||
else
|
||||
{
|
||||
float aattn = 0;
|
||||
float d;
|
||||
float mul = 1.0f;
|
||||
if (chan.attnfunc == 3)
|
||||
{
|
||||
Vec3 ldir = (light->dpos - pos);
|
||||
d = ldir.length();
|
||||
Vec3 ldirNorm = ldir / d; //normalize
|
||||
float l = ldirNorm * normal;
|
||||
aattn = light->ddir * ldirNorm;
|
||||
mul = l;
|
||||
}
|
||||
else if (chan.attnfunc == 1)
|
||||
{
|
||||
d = aattn = light->shalfangle * normal;
|
||||
mul = (light->sdir * normal > 0) ? (normal * light->shalfangle) : 0;
|
||||
if (mul < 0)
|
||||
mul = 0;
|
||||
}
|
||||
|
||||
float spot = (light->a2*aattn*aattn + light->a1*aattn + light->a0);
|
||||
float dist = 1.0f/(light->k2*d*d + light->k1*d + light->k0);
|
||||
if (spot<0)
|
||||
spot=0;
|
||||
|
||||
val = mul * spot * dist;
|
||||
}
|
||||
|
||||
if (val < 0 && chan.diffusefunc == 2) // clamp
|
||||
val = 0;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void VtxMulMtx43(Vec3 &out, const Vec3 &in, const float pMatrix[12])
|
||||
{
|
||||
out.x = in.x * pMatrix[0] + in.y * pMatrix[1] + in.z * pMatrix[2] + 1 * pMatrix[3];
|
||||
out.y = in.x * pMatrix[4] + in.y * pMatrix[5] + in.z * pMatrix[6] + 1 * pMatrix[7];
|
||||
out.z = in.x * pMatrix[8] + in.y * pMatrix[9] + in.z * pMatrix[10] + 1 * pMatrix[11];
|
||||
}
|
||||
|
||||
void VtxMulMtx43T(Vec3 &out, const Vec3 &in, const float pMatrix[12])
|
||||
{
|
||||
out.x = in.x * pMatrix[0] + in.y * pMatrix[1] + in.z * pMatrix[2] + 1 * pMatrix[3];
|
||||
out.y = in.x * pMatrix[4] + in.y * pMatrix[5] + in.z * pMatrix[6] + 1 * pMatrix[7];
|
||||
out.z = in.x * pMatrix[8] + in.y * pMatrix[9] + in.z * pMatrix[10] + 1 * pMatrix[11];
|
||||
}
|
||||
|
||||
void VtxMulMtx42(Vec3 &out, const Vec3 &in, const float pMatrix[8])
|
||||
{
|
||||
out.x = in.x * pMatrix[0] + in.y * pMatrix[1] + in.z * pMatrix[2] + 1 * pMatrix[3];
|
||||
out.y = in.x * pMatrix[4] + in.y * pMatrix[5] + in.z * pMatrix[6] + 1 * pMatrix[7];
|
||||
}
|
||||
|
||||
void VtxMulMtx33(Vec3 &out, const Vec3 &in, const float pMatrix[9])
|
||||
{
|
||||
out.x = in.x * pMatrix[0] + in.y * pMatrix[1] + in.z * pMatrix[2];
|
||||
out.y = in.x * pMatrix[3] + in.y * pMatrix[4] + in.z * pMatrix[5];
|
||||
out.z = in.x * pMatrix[6] + in.y * pMatrix[7] + in.z * pMatrix[8];
|
||||
}
|
||||
|
||||
void CTransformEngine::TransformVertices(int _numVertices, const DecodedVArray *varray, D3DVertex *vbuffer)
|
||||
{
|
||||
if (vbuffer == 0)
|
||||
{
|
||||
MessageBox(0,"TransformVertices : vbuffer == 0","WTF",0);
|
||||
}
|
||||
|
||||
DVSTARTPROFILE();
|
||||
|
||||
RGBAFloat lightColors[8];
|
||||
RGBAFloat lightVals[8];
|
||||
RGBAFloat chans[2];
|
||||
|
||||
// TODO: only for active lights
|
||||
for (int i=0; i<8; i++)
|
||||
lightColors[i].convert_GC(GetLight(i)->color);
|
||||
|
||||
for (int i=0; i<_numVertices; i++)
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//Step 1: xform position and normal
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Vec3 OrigPos = varray->GetPos(i);
|
||||
|
||||
if (varray->GetComponents() & VB_HAS_POSMTXIDX)
|
||||
{
|
||||
int index = varray->GetPosMtxInd(i);
|
||||
SetPosNormalMatrix(
|
||||
(float*)xfmem + (index & 63) * 4, //CHECK
|
||||
(float*)xfmem + 0x400 + 3 * (index & 31)); //CHECK
|
||||
}
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
if (varray->GetComponents() & (VB_HAS_TEXMTXIDX0<<j))
|
||||
{
|
||||
float *flipmem = (float *)xfmem;
|
||||
int index = varray->GetTexMtxInd(j, i);
|
||||
SetTexMatrix(j, flipmem + index * 4);
|
||||
}
|
||||
}
|
||||
|
||||
Vec3 TempPos;
|
||||
|
||||
// m_pPosMatrix can be switched out, through matrixindex vertex components
|
||||
VtxMulMtx43(TempPos, OrigPos, m_pPosMatrix);
|
||||
|
||||
Vec3 TempNormal;
|
||||
Vec3 OrigNormal;
|
||||
if (varray->GetComponents() & VB_HAS_NRM0)
|
||||
{
|
||||
OrigNormal = varray->GetNormal(0, i);
|
||||
VtxMulMtx33(TempNormal, OrigNormal, m_pNormalMatrix);
|
||||
TempNormal.normalize();
|
||||
}
|
||||
else
|
||||
{
|
||||
OrigNormal.setZero();
|
||||
TempNormal.setZero();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//Step 2: Light!
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//find all used lights
|
||||
u32 lightMask =
|
||||
colChans[0].color.GetFullLightMask() | colChans[0].alpha.GetFullLightMask() |
|
||||
colChans[1].color.GetFullLightMask() | colChans[1].alpha.GetFullLightMask();
|
||||
|
||||
float r0=0,g0=0,b0=0,a0=0;
|
||||
|
||||
//go through them and compute the lit colors
|
||||
//Sum lighting for both two color channels if they're active
|
||||
for (int j=0; j<(int)bpmem.genMode.numcolchans; j++)
|
||||
{
|
||||
RGBAFloat material;
|
||||
RGBAFloat lightSum(0,0,0,0);
|
||||
|
||||
bool hasColorJ = (varray->GetComponents() & (VB_HAS_COL0 << j)) != 0;
|
||||
|
||||
//get basic material color from appropriate sources (this would compile nicely!:)
|
||||
if (colChans[j].color.matsource==GX_SRC_REG)
|
||||
material.convertRGB_GC(colChans[j].matColor);
|
||||
else
|
||||
{
|
||||
if (hasColorJ)
|
||||
material.convertRGB(varray->GetColor(j, i));
|
||||
else
|
||||
material.r=material.g=material.b=1.0f;
|
||||
}
|
||||
|
||||
if (colChans[j].alpha.matsource==GX_SRC_REG)
|
||||
material.convertA_GC(colChans[j].matColor);
|
||||
else
|
||||
{
|
||||
if (hasColorJ)
|
||||
material.convertA(varray->GetColor(j, i));
|
||||
else
|
||||
material.a=1.0f;
|
||||
}
|
||||
|
||||
//combine together the light values from the lights that affect the color
|
||||
if (colChans[j].color.enablelighting)
|
||||
{
|
||||
//choose ambient source and start our lightsum accumulator with its value..
|
||||
if (colChans[j].color.ambsource == GX_SRC_REG)
|
||||
lightSum.convertRGB_GC(colChans[j].ambColor); //ambient
|
||||
else
|
||||
{
|
||||
if (hasColorJ)
|
||||
lightSum.convertRGB(varray->GetColor(j, i));
|
||||
else
|
||||
{
|
||||
lightSum.r=0.0f;lightSum.g=0.0f;lightSum.b=0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
//accumulate light colors
|
||||
int cmask = colChans[j].color.GetFullLightMask();
|
||||
for (int l=0; l<8; l++)
|
||||
{
|
||||
if (cmask&1)
|
||||
{
|
||||
float val = DoLighting(GetLight(l), colChans[j].color, TempPos, TempNormal);
|
||||
float r = lightColors[l].r * val;
|
||||
float g = lightColors[l].g * val;
|
||||
float b = lightColors[l].b * val;
|
||||
lightSum.r += r;
|
||||
lightSum.g += g;
|
||||
lightSum.b += b;
|
||||
}
|
||||
cmask >>= 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lightSum.r=lightSum.g=lightSum.b=1.0f;
|
||||
}
|
||||
|
||||
//combine together the light values from the lights that affect alpha (should be rare)
|
||||
if (colChans[j].alpha.enablelighting)
|
||||
{
|
||||
//choose ambient source..
|
||||
if (colChans[j].alpha.ambsource==GX_SRC_REG)
|
||||
lightSum.convertA_GC(colChans[j].ambColor);
|
||||
else
|
||||
{
|
||||
if (hasColorJ)
|
||||
lightSum.convertA(varray->GetColor(j, i));
|
||||
else
|
||||
lightSum.a=0.0f;
|
||||
}
|
||||
//accumulate light alphas
|
||||
int amask = colChans[j].alpha.GetFullLightMask();
|
||||
for (int l=0; l<8; l++)
|
||||
{
|
||||
if (amask&1)
|
||||
{
|
||||
float val = DoLighting(GetLight(l),colChans[j].alpha,TempPos,TempNormal);
|
||||
float a = lightColors[l].a * val;
|
||||
lightSum.a += a;
|
||||
}
|
||||
amask >>= 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lightSum.a=1.0f;
|
||||
}
|
||||
|
||||
chans[j] = lightSum * material;
|
||||
chans[j].clamp();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//Step 3: Generate texture coordinates!
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Vec3 TempUVs[8];
|
||||
for (int j=0; j<miscxf.numTexGens; j++)
|
||||
{
|
||||
int n = bpmem.tevorders[j/2].getTexCoord(j&1); // <- yazor: dirty zelda patch ^^
|
||||
n = j;
|
||||
Vec3 t;
|
||||
|
||||
switch(texcoords[n].texmtxinfo.sourcerow) {
|
||||
case XF_GEOM_INROW: t = OrigPos; break; //HACK WTFF???
|
||||
case XF_NORMAL_INROW: t = OrigNormal; break;
|
||||
case XF_COLORS_INROW: break; //set uvs to something?
|
||||
case XF_BINORMAL_T_INROW: t=Vec3(0,0,0);break;
|
||||
case XF_BINORMAL_B_INROW: t=Vec3(0,0,0);break;
|
||||
default:
|
||||
{
|
||||
int c = texcoords[n].texmtxinfo.sourcerow - XF_TEX0_INROW;
|
||||
bool hasTCC = (varray->GetComponents() & (VB_HAS_UV0 << c)) != 0;
|
||||
if (c >= 0 && c <= 7 && hasTCC)
|
||||
{
|
||||
const DecUV &uv = varray->GetUV(c, i);
|
||||
t = Vec3(uv.u, uv.v, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vec3 out,out2;
|
||||
switch (texcoords[n].texmtxinfo.texgentype)
|
||||
{
|
||||
case XF_TEXGEN_COLOR_STRGBC0:
|
||||
out=Vec3(chans[0].r*255, chans[0].g*255, 1)/255.0f;
|
||||
break;
|
||||
case XF_TEXGEN_COLOR_STRGBC1:
|
||||
out=Vec3(chans[1].r*255, chans[1].g*255, 1)/255.0f; //FIX: take color1 instead
|
||||
break;
|
||||
case XF_TEXGEN_REGULAR:
|
||||
if (texcoords[n].texmtxinfo.projection)
|
||||
VtxMulMtx43(out, t, m_pTexMatrix[n]);
|
||||
else
|
||||
VtxMulMtx42(out, t, m_pTexMatrix[n]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (texcoords[n].postmtxinfo.normalize)
|
||||
out.normalize();
|
||||
|
||||
int postMatrix = texcoords[n].postmtxinfo.index;
|
||||
float *pmtx = ((float*)xfmem) + 0x500 + postMatrix * 4; //CHECK
|
||||
//multiply with postmatrix
|
||||
VtxMulMtx43(TempUVs[j], out, pmtx);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//Step 4: Output the vertex!
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
for (int j=0; j<2; j++)
|
||||
chans[j].convertToD3DColor(vbuffer[i].colors[j]);
|
||||
|
||||
vbuffer[i].pos = TempPos;
|
||||
vbuffer[i].normal = TempNormal;
|
||||
for (int j=0; j<(int)bpmem.genMode.numtexgens; j++)
|
||||
{
|
||||
vbuffer[i].uv[j].u = TempUVs[j].x;
|
||||
vbuffer[i].uv[j].v = TempUVs[j].y;
|
||||
vbuffer[i].uv[j].w = TempUVs[j].z;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef _TRANSFORMENGINE_H
|
||||
#define _TRANSFORMENGINE_H
|
||||
|
||||
//T&L Engine
|
||||
//as much work as possible will be delegated to vertex shaders later
|
||||
//to take full advantage of current PC HW
|
||||
|
||||
#include "VertexHandler.h"
|
||||
#include "DecodedVArray.h"
|
||||
|
||||
class CTransformEngine
|
||||
{
|
||||
static float* m_pPosMatrix;
|
||||
static float* m_pNormalMatrix;
|
||||
static float* m_pTexMatrix[8];
|
||||
static float* m_pTexPostMatrix[8];
|
||||
|
||||
public:
|
||||
static size_t SaveLoadState(char *ptr, bool save);
|
||||
static void TransformVertices(int _numVertices,
|
||||
const DecodedVArray *varray,
|
||||
D3DVertex *vbuffer);
|
||||
|
||||
static void SetPosNormalMatrix(float *p, float *n)
|
||||
{
|
||||
m_pPosMatrix = p;
|
||||
m_pNormalMatrix = n;
|
||||
}
|
||||
static void SetTexMatrix(int i, float *f)
|
||||
{
|
||||
m_pTexMatrix[i] = f;
|
||||
}
|
||||
static void SetTexPostMatrix(int i, float *f)
|
||||
{
|
||||
m_pTexPostMatrix[i] = f;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,316 @@
|
||||
#ifdef _WIN32
|
||||
#include "W32Util/Misc.h"
|
||||
#endif
|
||||
|
||||
#include "Common.h"
|
||||
#include <assert.h>
|
||||
|
||||
int frameCount;
|
||||
int lut3to8[8];
|
||||
int lut4to8[16];
|
||||
int lut5to8[32];
|
||||
int lut6to8[64];
|
||||
float lutu8tosfloat[256];
|
||||
float lutu8toufloat[256];
|
||||
float luts8tosfloat[256];
|
||||
|
||||
void InitLUTs()
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
lut3to8[i] = (i * 255) / 7;
|
||||
for (int i = 0; i < 16; i++)
|
||||
lut4to8[i] = (i * 255) / 15;
|
||||
for (int i = 0; i < 32; i++)
|
||||
lut5to8[i] = (i * 255) / 31;
|
||||
for (int i = 0; i < 64; i++)
|
||||
lut6to8[i] = (i * 255) / 63;
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
lutu8tosfloat[i] = (float)(i-128) / 127.0f;
|
||||
lutu8toufloat[i] = (float)(i) / 255.0f;
|
||||
luts8tosfloat[i] = ((float)(signed char)(char)i) / 127.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Message handler for about box.
|
||||
LRESULT CALLBACK AboutProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
W32Util::CenterWindow(hDlg);
|
||||
return TRUE;
|
||||
|
||||
case WM_COMMAND:
|
||||
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
|
||||
{
|
||||
EndDialog(hDlg, LOWORD(wParam));
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
////////////////////
|
||||
// Small profiler //
|
||||
////////////////////
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <map>
|
||||
using namespace std;
|
||||
|
||||
int g_bWriteProfile=0;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#if defined (_MSC_VER) && _MSC_VER >= 1400
|
||||
#include <intrin.h>
|
||||
#pragma intrinsic(__rdtsc)
|
||||
#endif
|
||||
|
||||
static u64 luPerfFreq=0;
|
||||
inline u64 GET_PROFILE_TIME()
|
||||
{
|
||||
#if defined (_MSC_VER) && _MSC_VER >= 1400
|
||||
return __rdtsc();
|
||||
#else
|
||||
LARGE_INTEGER lu;
|
||||
QueryPerformanceCounter(&lu);
|
||||
return lu.QuadPart;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
static u64 luPerfFreq = 1000000;
|
||||
#define GET_PROFILE_TIME() //GetCpuTick()
|
||||
#endif
|
||||
|
||||
|
||||
struct DVPROFSTRUCT;
|
||||
|
||||
struct DVPROFSTRUCT
|
||||
{
|
||||
struct DATA
|
||||
{
|
||||
DATA(u64 time, u32 user = 0) : dwTime(time), dwUserData(user) {}
|
||||
DATA() : dwTime(0), dwUserData(0) {}
|
||||
|
||||
u64 dwTime;
|
||||
u32 dwUserData;
|
||||
};
|
||||
|
||||
~DVPROFSTRUCT() {
|
||||
list<DVPROFSTRUCT*>::iterator it = listpChild.begin();
|
||||
while(it != listpChild.end() ) {
|
||||
delete *it; *it = NULL;
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
list<DATA> listTimes; // before DVProfEnd is called, contains the global time it started
|
||||
// after DVProfEnd is called, contains the time it lasted
|
||||
// the list contains all the tracked times
|
||||
char pname[256];
|
||||
|
||||
list<DVPROFSTRUCT*> listpChild; // other profilers called during this profiler period
|
||||
};
|
||||
|
||||
struct DVPROFTRACK
|
||||
{
|
||||
u32 dwUserData;
|
||||
DVPROFSTRUCT::DATA* pdwTime;
|
||||
DVPROFSTRUCT* pprof;
|
||||
};
|
||||
|
||||
list<DVPROFTRACK> g_listCurTracking; // the current profiling functions, the back element is the
|
||||
// one that will first get popped off the list when DVProfEnd is called
|
||||
// the pointer is an element in DVPROFSTRUCT::listTimes
|
||||
list<DVPROFSTRUCT> g_listProfilers; // the current profilers, note that these are the parents
|
||||
// any profiler started during the time of another is held in
|
||||
// DVPROFSTRUCT::listpChild
|
||||
list<DVPROFSTRUCT*> g_listAllProfilers; // ignores the hierarchy, pointer to elements in g_listProfilers
|
||||
|
||||
void DVProfRegister(char* pname)
|
||||
{
|
||||
if( !g_bWriteProfile )
|
||||
return;
|
||||
|
||||
#ifdef _WIN32
|
||||
if( luPerfFreq <= 1 ) {
|
||||
#if defined (_MSC_VER) && _MSC_VER >= 1400
|
||||
luPerfFreq = 1000000;
|
||||
#else
|
||||
LARGE_INTEGER temp;
|
||||
QueryPerformanceFrequency(&temp);
|
||||
luPerfFreq = temp.QuadPart;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
list<DVPROFSTRUCT*>::iterator it = g_listAllProfilers.begin();
|
||||
|
||||
// while(it != g_listAllProfilers.end() ) {
|
||||
//
|
||||
// if( _tcscmp(pname, (*it)->pname) == 0 ) {
|
||||
// (*it)->listTimes.push_back(timeGetTime());
|
||||
// DVPROFTRACK dvtrack;
|
||||
// dvtrack.pdwTime = &(*it)->listTimes.back();
|
||||
// dvtrack.pprof = *it;
|
||||
// g_listCurTracking.push_back(dvtrack);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// ++it;
|
||||
// }
|
||||
|
||||
// else add in a new profiler to the appropriate parent profiler
|
||||
DVPROFSTRUCT* pprof = NULL;
|
||||
|
||||
if( g_listCurTracking.size() > 0 ) {
|
||||
assert( g_listCurTracking.back().pprof != NULL );
|
||||
g_listCurTracking.back().pprof->listpChild.push_back(new DVPROFSTRUCT());
|
||||
pprof = g_listCurTracking.back().pprof->listpChild.back();
|
||||
}
|
||||
else {
|
||||
g_listProfilers.push_back(DVPROFSTRUCT());
|
||||
pprof = &g_listProfilers.back();
|
||||
}
|
||||
|
||||
strncpy(pprof->pname, pname, 256);
|
||||
|
||||
// setup the profiler for tracking
|
||||
pprof->listTimes.push_back(DVPROFSTRUCT::DATA(GET_PROFILE_TIME()));
|
||||
|
||||
DVPROFTRACK dvtrack;
|
||||
dvtrack.pdwTime = &pprof->listTimes.back();
|
||||
dvtrack.pprof = pprof;
|
||||
dvtrack.dwUserData = 0;
|
||||
|
||||
g_listCurTracking.push_back(dvtrack);
|
||||
|
||||
// add to all profiler list
|
||||
g_listAllProfilers.push_back(pprof);
|
||||
}
|
||||
|
||||
void DVProfEnd(u32 dwUserData)
|
||||
{
|
||||
if( !g_bWriteProfile )
|
||||
return;
|
||||
if( g_listCurTracking.size() == 0 )
|
||||
return;
|
||||
|
||||
DVPROFTRACK dvtrack = g_listCurTracking.back();
|
||||
|
||||
assert( dvtrack.pdwTime != NULL && dvtrack.pprof != NULL );
|
||||
|
||||
dvtrack.pdwTime->dwTime = GET_PROFILE_TIME()- dvtrack.pdwTime->dwTime;
|
||||
dvtrack.pdwTime->dwUserData= dwUserData;
|
||||
|
||||
g_listCurTracking.pop_back();
|
||||
}
|
||||
|
||||
struct DVTIMEINFO
|
||||
{
|
||||
DVTIMEINFO() : uInclusive(0), uExclusive(0) {}
|
||||
u64 uInclusive, uExclusive;
|
||||
};
|
||||
|
||||
map<string, DVTIMEINFO> mapAggregateTimes;
|
||||
|
||||
u64 DVProfWriteStruct(FILE* f, DVPROFSTRUCT* p, int ident)
|
||||
{
|
||||
fprintf(f, "%*s%s - ", ident, "", p->pname);
|
||||
|
||||
list<DVPROFSTRUCT::DATA>::iterator ittime = p->listTimes.begin();
|
||||
|
||||
u64 utime = 0;
|
||||
|
||||
while(ittime != p->listTimes.end() ) {
|
||||
utime += ittime->dwTime;
|
||||
|
||||
if( ittime->dwUserData )
|
||||
fprintf(f, "time: %d, user: 0x%8.8x", (u32)ittime->dwTime, ittime->dwUserData);
|
||||
else
|
||||
fprintf(f, "time: %d", (u32)ittime->dwTime);
|
||||
++ittime;
|
||||
}
|
||||
|
||||
// yes this is necessary, maps have problems with constructors on their type
|
||||
map<string, DVTIMEINFO>::iterator ittimes = mapAggregateTimes.find(p->pname);
|
||||
if( ittimes == mapAggregateTimes.end() ) {
|
||||
ittimes = mapAggregateTimes.insert(map<string, DVTIMEINFO>::value_type(p->pname, DVTIMEINFO())).first;
|
||||
ittimes->second.uExclusive = 0;
|
||||
ittimes->second.uInclusive = 0;
|
||||
}
|
||||
|
||||
ittimes->second.uInclusive += utime;
|
||||
|
||||
fprintf(f, "\n");
|
||||
|
||||
list<DVPROFSTRUCT*>::iterator itprof = p->listpChild.begin();
|
||||
|
||||
u64 uex = utime;
|
||||
while(itprof != p->listpChild.end() ) {
|
||||
|
||||
uex -= DVProfWriteStruct(f, *itprof, ident+4);
|
||||
++itprof;
|
||||
}
|
||||
|
||||
if( uex > utime ) {
|
||||
uex = 0;
|
||||
}
|
||||
|
||||
ittimes->second.uExclusive += uex;
|
||||
return utime;
|
||||
}
|
||||
|
||||
void DVProfWrite(char* pfilename, u32 frames)
|
||||
{
|
||||
assert( pfilename != NULL );
|
||||
FILE* f = fopen(pfilename, "w");
|
||||
|
||||
// pop back any unused
|
||||
mapAggregateTimes.clear();
|
||||
list<DVPROFSTRUCT>::iterator it = g_listProfilers.begin();
|
||||
|
||||
while(it != g_listProfilers.end() ) {
|
||||
DVProfWriteStruct(f, &(*it), 0);
|
||||
++it;
|
||||
}
|
||||
|
||||
{
|
||||
map<string, DVTIMEINFO>::iterator it;
|
||||
fprintf(f, "\n\n-------------------------------------------------------------------\n\n");
|
||||
|
||||
u64 uTotal[2] = {0};
|
||||
double fiTotalTime[2];
|
||||
|
||||
for(it = mapAggregateTimes.begin(); it != mapAggregateTimes.end(); ++it) {
|
||||
uTotal[0] += it->second.uExclusive;
|
||||
uTotal[1] += it->second.uInclusive;
|
||||
}
|
||||
|
||||
fprintf(f, "total times (%d): ex: %Lu ", frames, 1000000*uTotal[0]/(luPerfFreq*(u64)frames));
|
||||
fprintf(f, "inc: %Lu\n", 1000000 * uTotal[1]/(luPerfFreq*(u64)frames));
|
||||
|
||||
fiTotalTime[0] = 1.0 / (double)uTotal[0];
|
||||
fiTotalTime[1] = 1.0 / (double)uTotal[1];
|
||||
|
||||
// output the combined times
|
||||
for(it = mapAggregateTimes.begin(); it != mapAggregateTimes.end(); ++it) {
|
||||
fprintf(f, "%s - ex: %f inc: %f\n", it->first.c_str(), (float)((double)it->second.uExclusive * fiTotalTime[0]),
|
||||
(float)((double)it->second.uInclusive * fiTotalTime[1]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void DVProfClear()
|
||||
{
|
||||
g_listCurTracking.clear();
|
||||
g_listProfilers.clear();
|
||||
g_listAllProfilers.clear();
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
#ifndef _UTILS_H
|
||||
#define _UTILS_H
|
||||
|
||||
|
||||
#include "Common.h"
|
||||
#include "main.h"
|
||||
|
||||
extern int frameCount;
|
||||
extern int lut3to8[8];
|
||||
extern int lut4to8[16];
|
||||
extern int lut5to8[32];
|
||||
extern int lut6to8[64];
|
||||
extern float lutu8tosfloat[256];
|
||||
extern float lutu8toufloat[256];
|
||||
extern float luts8tosfloat[256];
|
||||
|
||||
LRESULT CALLBACK AboutProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
void InitLUTs();
|
||||
|
||||
|
||||
//#define RAM_MASK 0x1FFFFFF
|
||||
|
||||
inline u8 *Memory_GetPtr(u32 _uAddress)
|
||||
{
|
||||
return g_VideoInitialize.pGetMemoryPointer(_uAddress);
|
||||
}
|
||||
|
||||
inline u8 Memory_Read_U8(u32 _uAddress)
|
||||
{
|
||||
return *g_VideoInitialize.pGetMemoryPointer(_uAddress);
|
||||
}
|
||||
|
||||
inline u16 Memory_Read_U16(u32 _uAddress)
|
||||
{
|
||||
return _byteswap_ushort(*(u16*)g_VideoInitialize.pGetMemoryPointer(_uAddress));
|
||||
// return _byteswap_ushort(*(u16*)&g_pMemory[_uAddress & RAM_MASK]);
|
||||
}
|
||||
|
||||
inline u32 Memory_Read_U32(u32 _uAddress)
|
||||
{
|
||||
if (_uAddress == 0x020143a8)
|
||||
{
|
||||
int i =0;
|
||||
}
|
||||
return _byteswap_ulong(*(u32*)g_VideoInitialize.pGetMemoryPointer(_uAddress));
|
||||
// return _byteswap_ulong(*(u32*)&g_pMemory[_uAddress & RAM_MASK]);
|
||||
}
|
||||
|
||||
inline float Memory_Read_Float(u32 _uAddress)
|
||||
{
|
||||
u32 uTemp = Memory_Read_U32(_uAddress);
|
||||
return *(float*)&uTemp;
|
||||
}
|
||||
|
||||
////
|
||||
// profiling
|
||||
///
|
||||
|
||||
extern int g_bWriteProfile; // global variable to enable/disable profiling (if DVPROFILE is defined)
|
||||
|
||||
// IMPORTANT: For every Reigster there must be an End
|
||||
void DVProfRegister(char* pname); // first checks if this profiler exists in g_listProfilers
|
||||
void DVProfEnd(u32 dwUserData);
|
||||
void DVProfWrite(char* pfilename, u32 frames = 0);
|
||||
void DVProfClear(); // clears all the profilers
|
||||
|
||||
// #define DVPROFILE // comment out to disable profiling
|
||||
|
||||
#if defined(DVPROFILE) && (defined(_WIN32)||defined(WIN32))
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#ifndef __PRETTY_FUNCTION__
|
||||
#define __PRETTY_FUNCTION__ __FUNCTION__
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#define DVSTARTPROFILE() DVProfileFunc _pf(__PRETTY_FUNCTION__);
|
||||
|
||||
class DVProfileFunc
|
||||
{
|
||||
public:
|
||||
u32 dwUserData;
|
||||
DVProfileFunc(char* pname) { DVProfRegister(pname); dwUserData = 0; }
|
||||
DVProfileFunc(char* pname, u32 dwUserData) : dwUserData(dwUserData) { DVProfRegister(pname); }
|
||||
~DVProfileFunc() { DVProfEnd(dwUserData); }
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#define DVSTARTPROFILE()
|
||||
|
||||
class DVProfileFunc
|
||||
{
|
||||
public:
|
||||
u32 dwUserData;
|
||||
__forceinline DVProfileFunc(char* pname) {}
|
||||
__forceinline DVProfileFunc(char* pname, u32 dwUserData) { }
|
||||
~DVProfileFunc() {}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,98 @@
|
||||
#ifndef _VEC3_H
|
||||
#define _VEC3_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
class Vec3
|
||||
{
|
||||
public:
|
||||
float x,y,z;
|
||||
Vec3() { }
|
||||
explicit Vec3(float f) {x=y=z=f;}
|
||||
Vec3(const float _x, const float _y, const float _z) {
|
||||
x=_x; y=_y; z=_z;
|
||||
}
|
||||
void set(const float _x, const float _y, const float _z) {
|
||||
x=_x; y=_y; z=_z;
|
||||
}
|
||||
Vec3 operator + (const Vec3 &other) const {
|
||||
return Vec3(x+other.x, y+other.y, z+other.z);
|
||||
}
|
||||
void operator += (const Vec3 &other) {
|
||||
x+=other.x; y+=other.y; z+=other.z;
|
||||
}
|
||||
Vec3 operator -(const Vec3 &v) const {
|
||||
return Vec3(x-v.x,y-v.y,z-v.z);
|
||||
}
|
||||
void operator -= (const Vec3 &other)
|
||||
{
|
||||
x-=other.x; y-=other.y; z-=other.z;
|
||||
}
|
||||
Vec3 operator -() const {
|
||||
return Vec3(-x,-y,-z);
|
||||
}
|
||||
|
||||
Vec3 operator * (const float f) const {
|
||||
return Vec3(x*f,y*f,z*f);
|
||||
}
|
||||
Vec3 operator / (const float f) const {
|
||||
float invf = (1.0f/f);
|
||||
return Vec3(x*invf,y*invf,z*invf);
|
||||
}
|
||||
void operator /= (const float f)
|
||||
{
|
||||
*this = *this / f;
|
||||
}
|
||||
float operator * (const Vec3 &other) const {
|
||||
return x*other.x + y*other.y + z*other.z;
|
||||
}
|
||||
void operator *= (const float f) {
|
||||
*this = *this * f;
|
||||
}
|
||||
Vec3 scaled_by(const Vec3 &other) const {
|
||||
return Vec3(x*other.x, y*other.y, z*other.z);
|
||||
}
|
||||
|
||||
Vec3 operator %(const Vec3 &v) const {
|
||||
return Vec3(y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x);
|
||||
}
|
||||
float length2() const {
|
||||
return x*x+y*y+z*z;
|
||||
}
|
||||
float length() const {
|
||||
return sqrtf(length2());
|
||||
}
|
||||
float distance2_to(Vec3 &other)
|
||||
{
|
||||
return (other-(*this)).length2();
|
||||
}
|
||||
Vec3 normalized() const {
|
||||
return (*this) / length();
|
||||
|
||||
}
|
||||
void normalize() {
|
||||
(*this) /= length();
|
||||
}
|
||||
float &operator [] (int i)
|
||||
{
|
||||
return *((&x) + i);
|
||||
}
|
||||
const float operator [] (const int i) const
|
||||
{
|
||||
return *((&x) + i);
|
||||
}
|
||||
bool operator == (const Vec3 &other) const
|
||||
{
|
||||
if (x==other.x && y==other.y && z==other.z)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
void setZero()
|
||||
{
|
||||
memset((void *)this,0,sizeof(float)*3);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,257 @@
|
||||
#include "D3DBase.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "Globals.h"
|
||||
#include "VertexHandler.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "TransformEngine.h"
|
||||
#include "IndexGenerator.h"
|
||||
#include "BPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
#include "ShaderManager.h"
|
||||
#include "Utils.h"
|
||||
|
||||
using namespace D3D;
|
||||
|
||||
//TODO(ector): remove and calculate inline?
|
||||
float shiftLookup[32];
|
||||
|
||||
IndexGenerator indexGen;
|
||||
Collection CVertexHandler::collection;
|
||||
|
||||
LPDIRECT3DVERTEXDECLARATION9 vDecl;
|
||||
|
||||
D3DVertex *fakeVBuffer;
|
||||
u16 *fakeIBuffer;
|
||||
|
||||
#define MAXVBUFFERSIZE 65536*3
|
||||
#define MAXIBUFFERSIZE 65536*3
|
||||
|
||||
const D3DVERTEXELEMENT9 decl[] =
|
||||
{
|
||||
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
|
||||
{ 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 },
|
||||
{ 0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },
|
||||
{ 0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1 },
|
||||
{ 0, 32+12*0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
|
||||
{ 0, 32+12*1, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 },
|
||||
{ 0, 32+12*2, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2 },
|
||||
{ 0, 32+12*3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3 },
|
||||
{ 0, 32+12*4, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4 },
|
||||
{ 0, 32+12*5, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 5 },
|
||||
{ 0, 32+12*6, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 6 },
|
||||
{ 0, 32+12*7, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 7 },
|
||||
D3DDECL_END()
|
||||
};
|
||||
|
||||
void CVertexHandler::Init()
|
||||
{
|
||||
collection = C_NOTHING;
|
||||
|
||||
for (int i = 0; i < 31; i++)
|
||||
shiftLookup[i] = 1.0f / float(1 << i);
|
||||
|
||||
fakeVBuffer = new D3DVertex[65536];
|
||||
fakeIBuffer = new u16[65536];
|
||||
CreateDeviceObjects();
|
||||
}
|
||||
|
||||
|
||||
void CVertexHandler::Shutdown()
|
||||
{
|
||||
DestroyDeviceObjects();
|
||||
delete [] fakeVBuffer;
|
||||
delete [] fakeIBuffer;
|
||||
}
|
||||
|
||||
void CVertexHandler::CreateDeviceObjects()
|
||||
{
|
||||
HRESULT hr;
|
||||
if( FAILED( hr = D3D::dev->CreateVertexDeclaration( decl, &vDecl) ) )
|
||||
{
|
||||
MessageBox(0,"Failed to create vertex declaration","sdfsd",0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void CVertexHandler::BeginFrame()
|
||||
{
|
||||
D3D::dev->SetVertexDeclaration(vDecl);
|
||||
//D3D::dev->SetStreamSource(0,vBuffer,0,sizeof(D3DVertex));
|
||||
}
|
||||
|
||||
void CVertexHandler::DestroyDeviceObjects()
|
||||
{
|
||||
if (vDecl)
|
||||
vDecl->Release();
|
||||
vDecl=0;
|
||||
}
|
||||
|
||||
|
||||
void CVertexHandler::AddIndices(int _primitive, int _numVertices)
|
||||
{
|
||||
switch(_primitive) {
|
||||
case GX_DRAW_QUADS: indexGen.AddQuads(_numVertices); return;
|
||||
case GX_DRAW_TRIANGLES: indexGen.AddList(_numVertices); return;
|
||||
case GX_DRAW_TRIANGLE_STRIP: indexGen.AddStrip(_numVertices); return;
|
||||
case GX_DRAW_TRIANGLE_FAN: indexGen.AddFan(_numVertices); return;
|
||||
case GX_DRAW_LINE_STRIP: indexGen.AddLineStrip(_numVertices); return;
|
||||
case GX_DRAW_LINES: indexGen.AddLineList(_numVertices); return;
|
||||
case GX_DRAW_POINTS: indexGen.AddPointList(_numVertices); return;
|
||||
}
|
||||
}
|
||||
|
||||
const Collection collectionTypeLUT[8] =
|
||||
{
|
||||
C_TRIANGLES,//quads
|
||||
C_NOTHING, //nothing
|
||||
C_TRIANGLES,//triangles
|
||||
C_TRIANGLES,//strip
|
||||
C_TRIANGLES,//fan
|
||||
C_LINES, //lines
|
||||
C_LINES, //linestrip
|
||||
C_POINTS //guess :P
|
||||
};
|
||||
|
||||
D3DVertex *vbufferwrite;
|
||||
|
||||
void CVertexHandler::DrawVertices(int _primitive, int _numVertices, const DecodedVArray *varray)
|
||||
{
|
||||
if (_numVertices <= 0) //This check is pretty stupid...
|
||||
return;
|
||||
|
||||
Collection type = collectionTypeLUT[_primitive];
|
||||
if (type == C_NOTHING)
|
||||
return;
|
||||
|
||||
DVSTARTPROFILE();
|
||||
_assert_msg_(type != C_NOTHING, "type == C_NOTHING!!", "WTF");
|
||||
|
||||
if (indexGen.GetNumVerts() > 1000) // TODO(ector): Raise?
|
||||
Flush();
|
||||
|
||||
ADDSTAT(stats.thisFrame.numPrims, _numVertices);
|
||||
|
||||
if (collection != type)
|
||||
{
|
||||
//We are NOT collecting the right type.
|
||||
Flush();
|
||||
collection = type;
|
||||
u16 *ptr = 0;
|
||||
|
||||
if (type != C_POINTS)
|
||||
{
|
||||
ptr = fakeIBuffer;
|
||||
indexGen.Start((unsigned short*)ptr);
|
||||
AddIndices(_primitive,_numVertices);
|
||||
}
|
||||
|
||||
vbufferwrite = fakeVBuffer;
|
||||
|
||||
if (_numVertices >= MAXVBUFFERSIZE)
|
||||
MessageBox(NULL, "To much vertices for the buffer", "Video.DLL", MB_OK);
|
||||
|
||||
CTransformEngine::TransformVertices(_numVertices,varray,vbufferwrite);
|
||||
}
|
||||
else //We are collecting the right type, keep going
|
||||
{
|
||||
_assert_msg_(vbufferwrite!=0, "collecting: vbufferwrite == 0!","WTF");
|
||||
INCSTAT(stats.numJoins);
|
||||
//Success, keep adding to unlocked buffer
|
||||
int last=indexGen.GetNumVerts();
|
||||
AddIndices(_primitive,_numVertices);
|
||||
|
||||
if (_numVertices >= MAXVBUFFERSIZE)
|
||||
MessageBox(NULL, "Too many vertices for the buffer", "Video.DLL", MB_OK);
|
||||
CTransformEngine::TransformVertices(_numVertices,varray,vbufferwrite + last);
|
||||
}
|
||||
}
|
||||
|
||||
const D3DPRIMITIVETYPE pts[3] =
|
||||
{
|
||||
D3DPT_POINTLIST, //DUMMY
|
||||
D3DPT_TRIANGLELIST,
|
||||
D3DPT_LINELIST,
|
||||
};
|
||||
|
||||
void CVertexHandler::Flush()
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
|
||||
if (collection != C_NOTHING)
|
||||
{
|
||||
ActivateTextures();
|
||||
|
||||
int numVertices = indexGen.GetNumVerts();
|
||||
if (numVertices != 0)
|
||||
{
|
||||
PShaderCache::SetShader(); // TODO(ector): only do this if shader has changed
|
||||
VShaderCache::SetShader(); // TODO(ector): only do this if shader has changed
|
||||
if (collection != C_POINTS)
|
||||
{
|
||||
int numPrimitives = indexGen.GetNumPrims();
|
||||
D3D::dev->DrawIndexedPrimitiveUP(pts[(int)collection],
|
||||
0,
|
||||
numVertices,
|
||||
numPrimitives,
|
||||
fakeIBuffer,
|
||||
D3DFMT_INDEX16,
|
||||
fakeVBuffer,
|
||||
sizeof(D3DVertex));
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D::dev->SetIndices(0);
|
||||
D3D::dev->DrawPrimitiveUP(D3DPT_POINTLIST,
|
||||
numVertices,
|
||||
fakeVBuffer,
|
||||
sizeof(D3DVertex));
|
||||
}
|
||||
}
|
||||
collection = C_NOTHING;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
char szTmp[256];
|
||||
sprintf(szTmp, "Batch size : %i",_numVertices);
|
||||
g_VideoInitialize.pLog(szTmp);
|
||||
|
||||
|
||||
char szTemp[256];
|
||||
sprintf(szTemp, "count: %i", count);
|
||||
SendMessage(g_VideoInitialize.hStatusBar, SB_SETTEXT,0,(LPARAM)szTemp);
|
||||
|
||||
static bool bWaitStep = false;
|
||||
if (count == 24800)
|
||||
{
|
||||
bWaitStep = true;
|
||||
Renderer::Flush();
|
||||
}
|
||||
if (GetAsyncKeyState('J'))
|
||||
bWaitStep = true;
|
||||
if (GetAsyncKeyState('U'))
|
||||
bWaitStep = false;
|
||||
|
||||
if (bWaitStep)
|
||||
{
|
||||
static bool bKey = false;
|
||||
while (GetAsyncKeyState('H') == 0)
|
||||
{
|
||||
if (GetAsyncKeyState(VK_SPACE))
|
||||
_asm int 3;
|
||||
if (GetAsyncKeyState('U'))
|
||||
{
|
||||
bWaitStep = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Renderer::Flush();
|
||||
// wait for key release
|
||||
while (GetAsyncKeyState ('H')){
|
||||
};
|
||||
}
|
||||
}
|
||||
*/
|
||||
// old = bpmem.combiners[0].colorC.hex;
|
||||
@@ -0,0 +1,51 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CPStructs.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "DecodedVArray.h"
|
||||
|
||||
extern float shiftLookup[32];
|
||||
|
||||
struct UV
|
||||
{
|
||||
float u,v,w;
|
||||
};
|
||||
|
||||
struct D3DVertex {
|
||||
Vec3 pos;
|
||||
Vec3 normal;
|
||||
u32 colors[2];
|
||||
UV uv[8];
|
||||
};
|
||||
|
||||
enum Collection
|
||||
{
|
||||
C_NOTHING=0,
|
||||
C_TRIANGLES=1,
|
||||
C_LINES=2,
|
||||
C_POINTS=3
|
||||
};
|
||||
extern const Collection collectionTypeLUT[8];
|
||||
|
||||
class CVertexHandler
|
||||
{
|
||||
private:
|
||||
static Collection collection;
|
||||
// Pipeline
|
||||
|
||||
static void PrepareRender();
|
||||
static void AddIndices(int _primitive, int _numVertices);
|
||||
|
||||
public:
|
||||
static void Init();
|
||||
static void Shutdown();
|
||||
|
||||
static void BeginFrame();
|
||||
|
||||
static void CreateDeviceObjects();
|
||||
static void DestroyDeviceObjects();
|
||||
|
||||
static void DrawVertices(int _primitive, int _numVertices, const DecodedVArray *varray);
|
||||
static void Flush();
|
||||
};
|
||||
@@ -0,0 +1,408 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "x64Emitter.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "VertexHandler.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "XFStructs.h"
|
||||
#include "BPStructs.h"
|
||||
#include "DataReader.h"
|
||||
#include "DecodedVArray.h"
|
||||
|
||||
//these don't need to be saved
|
||||
float posScale;
|
||||
float tcScale[8];
|
||||
int tcElements[8];
|
||||
int tcFormat[8];
|
||||
int colElements[2];
|
||||
float tcScaleU[8];
|
||||
float tcScaleV[8];
|
||||
int tcIndex;
|
||||
int colIndex;
|
||||
u32 addr;
|
||||
|
||||
DecodedVArray *varray;
|
||||
|
||||
int ComputeVertexSize(u32 comp)
|
||||
{
|
||||
int size = 0;
|
||||
if (comp & VB_HAS_POSMTXIDX)
|
||||
size += 4;
|
||||
if (comp & (VB_HAS_TEXMTXIDX0 | VB_HAS_TEXMTXIDX1 | VB_HAS_TEXMTXIDX2 | VB_HAS_TEXMTXIDX3))
|
||||
size += 4;
|
||||
if (comp & (VB_HAS_TEXMTXIDX4 | VB_HAS_TEXMTXIDX5 | VB_HAS_TEXMTXIDX6 | VB_HAS_TEXMTXIDX7))
|
||||
size += 4;
|
||||
if (comp & VB_HAS_NRM0)
|
||||
size += 4;
|
||||
if (comp & (VB_HAS_NRM1|VB_HAS_NRM2)) //combine into single check for speed
|
||||
size += 8;
|
||||
if (comp & VB_HAS_COL0)
|
||||
size += 4;
|
||||
if (comp & VB_HAS_COL1)
|
||||
size += 4;
|
||||
for (int i = 0; i < 8; i++)
|
||||
if (comp & (VB_HAS_UV0 << i))
|
||||
size += 8;
|
||||
return size;
|
||||
}
|
||||
|
||||
void VertexLoader::SetVArray(DecodedVArray *_varray)
|
||||
{
|
||||
varray = _varray;
|
||||
}
|
||||
/*
|
||||
inline u8 ReadBuffer8() { return fifo.Read8(); }
|
||||
inline u16 ReadBuffer16() { return fifo.Read16(); }
|
||||
inline u32 ReadBuffer32() { return fifo.Read32(); }
|
||||
inline float ReadBuffer32F() { return fifo.Read32F(); }
|
||||
*/
|
||||
inline u8 ReadBuffer8()
|
||||
{
|
||||
return g_pDataReader->Read8();
|
||||
}
|
||||
|
||||
inline u16 ReadBuffer16()
|
||||
{
|
||||
//PowerPC byte ordering :(
|
||||
return g_pDataReader->Read16();
|
||||
}
|
||||
|
||||
inline u32 ReadBuffer32()
|
||||
{
|
||||
//PowerPC byte ordering :(
|
||||
return g_pDataReader->Read32();
|
||||
}
|
||||
|
||||
inline float ReadBuffer32F()
|
||||
{
|
||||
u32 temp = g_pDataReader->Read32();
|
||||
return *(float*)(&temp);
|
||||
}
|
||||
|
||||
#include "VertexLoader_MtxIndex.h"
|
||||
#include "VertexLoader_Position.h"
|
||||
#include "VertexLoader_Normal.h"
|
||||
#include "VertexLoader_Color.h"
|
||||
#include "VertexLoader_textCoord.h"
|
||||
|
||||
VertexLoader g_VertexLoaders[8];
|
||||
TVtxDesc VertexLoader::m_VtxDesc;
|
||||
bool VertexLoader::m_DescDirty = true;
|
||||
|
||||
VertexLoader::VertexLoader()
|
||||
{
|
||||
m_numPipelineStates = 0;
|
||||
m_VertexSize = 0;
|
||||
m_AttrDirty = true;
|
||||
VertexLoader_Normal::Init();
|
||||
}
|
||||
|
||||
VertexLoader::~VertexLoader()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void VertexLoader::Setup()
|
||||
{
|
||||
if (!m_AttrDirty && !m_DescDirty)
|
||||
return;
|
||||
|
||||
DVSTARTPROFILE();
|
||||
|
||||
// Reset pipeline
|
||||
m_VertexSize = 0;
|
||||
m_numPipelineStates = 0;
|
||||
m_components = 0;
|
||||
|
||||
// Position Matrix Index
|
||||
if (m_VtxDesc.PosMatIdx)
|
||||
{
|
||||
m_PipelineStates[m_numPipelineStates++] = PosMtx_ReadDirect_UByte;
|
||||
m_VertexSize += 1;
|
||||
m_components |= VB_HAS_POSMTXIDX;
|
||||
}
|
||||
|
||||
// Texture matrix indices
|
||||
if (m_VtxDesc.Tex0MatIdx) {m_components|=VB_HAS_TEXMTXIDX0; WriteCall(TexMtx_ReadDirect_UByte0); m_VertexSize+=1;}
|
||||
if (m_VtxDesc.Tex1MatIdx) {m_components|=VB_HAS_TEXMTXIDX1; WriteCall(TexMtx_ReadDirect_UByte1); m_VertexSize+=1;}
|
||||
if (m_VtxDesc.Tex2MatIdx) {m_components|=VB_HAS_TEXMTXIDX2; WriteCall(TexMtx_ReadDirect_UByte2); m_VertexSize+=1;}
|
||||
if (m_VtxDesc.Tex3MatIdx) {m_components|=VB_HAS_TEXMTXIDX3; WriteCall(TexMtx_ReadDirect_UByte3); m_VertexSize+=1;}
|
||||
if (m_VtxDesc.Tex4MatIdx) {m_components|=VB_HAS_TEXMTXIDX4; WriteCall(TexMtx_ReadDirect_UByte4); m_VertexSize+=1;}
|
||||
if (m_VtxDesc.Tex5MatIdx) {m_components|=VB_HAS_TEXMTXIDX5; WriteCall(TexMtx_ReadDirect_UByte5); m_VertexSize+=1;}
|
||||
if (m_VtxDesc.Tex6MatIdx) {m_components|=VB_HAS_TEXMTXIDX6; WriteCall(TexMtx_ReadDirect_UByte6); m_VertexSize+=1;}
|
||||
if (m_VtxDesc.Tex7MatIdx) {m_components|=VB_HAS_TEXMTXIDX7; WriteCall(TexMtx_ReadDirect_UByte7); m_VertexSize+=1;}
|
||||
|
||||
// Position
|
||||
switch (m_VtxDesc.Position)
|
||||
{
|
||||
case NOT_PRESENT: {_assert_msg_(0,"Vertex descriptor without position!","WTF?");} break;
|
||||
case DIRECT:
|
||||
{
|
||||
int SizePro = 0;
|
||||
switch (m_VtxAttr.PosFormat)
|
||||
{
|
||||
case FORMAT_UBYTE: SizePro=1; WriteCall(Pos_ReadDirect_UByte); break;
|
||||
case FORMAT_BYTE: SizePro=1; WriteCall(Pos_ReadDirect_Byte); break;
|
||||
case FORMAT_USHORT: SizePro=2; WriteCall(Pos_ReadDirect_UShort); break;
|
||||
case FORMAT_SHORT: SizePro=2; WriteCall(Pos_ReadDirect_Short); break;
|
||||
case FORMAT_FLOAT: SizePro=4; WriteCall(Pos_ReadDirect_Float); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
if (m_VtxAttr.PosElements == 1)
|
||||
m_VertexSize += SizePro * 3;
|
||||
else
|
||||
m_VertexSize += SizePro * 2;
|
||||
}
|
||||
break;
|
||||
case INDEX8:
|
||||
m_VertexSize+=1;
|
||||
switch (m_VtxAttr.PosFormat)
|
||||
{
|
||||
case FORMAT_UBYTE: WriteCall(Pos_ReadIndex8_UByte); break; //WTF?
|
||||
case FORMAT_BYTE: WriteCall(Pos_ReadIndex8_Byte); break;
|
||||
case FORMAT_USHORT: WriteCall(Pos_ReadIndex8_UShort); break;
|
||||
case FORMAT_SHORT: WriteCall(Pos_ReadIndex8_Short); break;
|
||||
case FORMAT_FLOAT: WriteCall(Pos_ReadIndex8_Float); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
break;
|
||||
case INDEX16:
|
||||
m_VertexSize+=2;
|
||||
switch (m_VtxAttr.PosFormat)
|
||||
{
|
||||
case FORMAT_UBYTE: WriteCall(Pos_ReadIndex16_UByte); break;
|
||||
case FORMAT_BYTE: WriteCall(Pos_ReadIndex16_Byte); break;
|
||||
case FORMAT_USHORT: WriteCall(Pos_ReadIndex16_UShort); break;
|
||||
case FORMAT_SHORT: WriteCall(Pos_ReadIndex16_Short); break;
|
||||
case FORMAT_FLOAT: WriteCall(Pos_ReadIndex16_Float); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Normals
|
||||
if (m_VtxDesc.Normal != NOT_PRESENT)
|
||||
{
|
||||
VertexLoader_Normal::index3 = m_VtxAttr.NormalIndex3 ? true : false;
|
||||
unsigned int uSize = VertexLoader_Normal::GetSize(m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements);
|
||||
TPipelineFunction pFunc = VertexLoader_Normal::GetFunction(m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements);
|
||||
if (pFunc == 0)
|
||||
{
|
||||
char temp[256];
|
||||
sprintf(temp,"%i %i %i", m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements);
|
||||
MessageBox(0,"VertexLoader_Normal::GetFunction returned zero!",temp,0);
|
||||
}
|
||||
WriteCall(pFunc);
|
||||
m_VertexSize += uSize;
|
||||
int m_numNormals = (m_VtxAttr.NormalElements==1) ? NRM_THREE : NRM_ONE;
|
||||
m_components |= VB_HAS_NRM0;
|
||||
if (m_numNormals == NRM_THREE)
|
||||
m_components |= VB_HAS_NRM1 | VB_HAS_NRM2;
|
||||
}
|
||||
|
||||
// Colors
|
||||
int col[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1};
|
||||
for (int i = 0; i < 2; i++)
|
||||
SetupColor(i,col[i], m_VtxAttr.color[i].Comp, m_VtxAttr.color[i].Elements);
|
||||
|
||||
// TextureCoord
|
||||
int tc[8] = {
|
||||
m_VtxDesc.Tex0Coord, m_VtxDesc.Tex1Coord, m_VtxDesc.Tex2Coord, m_VtxDesc.Tex3Coord,
|
||||
m_VtxDesc.Tex4Coord, m_VtxDesc.Tex5Coord, m_VtxDesc.Tex6Coord, m_VtxDesc.Tex7Coord,
|
||||
};
|
||||
for (int i = 0; i < 8; i++)
|
||||
SetupTexCoord(i, tc[i],
|
||||
m_VtxAttr.texCoord[i].Format,
|
||||
m_VtxAttr.texCoord[i].Elements,
|
||||
m_VtxAttr.texCoord[i].Frac);
|
||||
|
||||
Compile();
|
||||
//RET();
|
||||
/*
|
||||
char temp[256];
|
||||
sprintf(temp,"Size: %08x Pos: %i Norm:%i Col0: %i Col1: %i",m_VertexSize,m_VtxDesc.Position,m_VtxDesc.Normal,m_VtxDesc.Color0,m_VtxDesc.Color1);
|
||||
g_VideoInitialize.pLog(temp);
|
||||
sprintf(temp,"Pos: %i Norm:%i Col0: %i Col1: %i",_VtxAttr.PosFormat,_VtxAttr.NormalFormat,_VtxAttr.color[0].Comp,_VtxAttr.color[1].Comp);
|
||||
g_VideoInitialize.pLog(temp);*/
|
||||
}
|
||||
|
||||
void VertexLoader::SetupColor(int num, int mode, int format, int elements)
|
||||
{
|
||||
m_components |= VB_HAS_COL0 << num;
|
||||
switch (mode)
|
||||
{
|
||||
case NOT_PRESENT:
|
||||
m_components &= ~(VB_HAS_COL0 << num);
|
||||
break;
|
||||
case DIRECT:
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_16B_565: m_VertexSize+=2; WriteCall(Color_ReadDirect_16b_565); break;
|
||||
case FORMAT_24B_888: m_VertexSize+=3; WriteCall(Color_ReadDirect_24b_888); break;
|
||||
case FORMAT_32B_888x: m_VertexSize+=4; WriteCall(Color_ReadDirect_32b_888x); break;
|
||||
case FORMAT_16B_4444: m_VertexSize+=2; WriteCall(Color_ReadDirect_16b_4444); break;
|
||||
case FORMAT_24B_6666: m_VertexSize+=3; WriteCall(Color_ReadDirect_24b_6666); break;
|
||||
case FORMAT_32B_8888: m_VertexSize+=4; WriteCall(Color_ReadDirect_32b_8888); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
break;
|
||||
case INDEX8:
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_16B_565: WriteCall(Color_ReadIndex8_16b_565); break;
|
||||
case FORMAT_24B_888: WriteCall(Color_ReadIndex8_24b_888); break;
|
||||
case FORMAT_32B_888x: WriteCall(Color_ReadIndex8_32b_888x); break;
|
||||
case FORMAT_16B_4444: WriteCall(Color_ReadIndex8_16b_4444); break;
|
||||
case FORMAT_24B_6666: WriteCall(Color_ReadIndex8_24b_6666); break;
|
||||
case FORMAT_32B_8888: WriteCall(Color_ReadIndex8_32b_8888); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
m_VertexSize+=1;
|
||||
break;
|
||||
case INDEX16:
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_16B_565: WriteCall(Color_ReadIndex16_16b_565); break;
|
||||
case FORMAT_24B_888: WriteCall(Color_ReadIndex16_24b_888); break;
|
||||
case FORMAT_32B_888x: WriteCall(Color_ReadIndex16_32b_888x); break;
|
||||
case FORMAT_16B_4444: WriteCall(Color_ReadIndex16_16b_4444); break;
|
||||
case FORMAT_24B_6666: WriteCall(Color_ReadIndex16_24b_6666); break;
|
||||
case FORMAT_32B_8888: WriteCall(Color_ReadIndex16_32b_8888); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
m_VertexSize+=2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VertexLoader::SetupTexCoord(int num, int mode, int format, int elements, int _iFrac)
|
||||
{
|
||||
m_components |= VB_HAS_UV0 << num;
|
||||
switch (mode)
|
||||
{
|
||||
case NOT_PRESENT:
|
||||
m_components &= ~(VB_HAS_UV0 << num);
|
||||
break;
|
||||
case DIRECT:
|
||||
{
|
||||
int sizePro=0;
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_UBYTE: sizePro=1; WriteCall(TexCoord_ReadDirect_UByte); break;
|
||||
case FORMAT_BYTE: sizePro=1; WriteCall(TexCoord_ReadDirect_Byte); break;
|
||||
case FORMAT_USHORT: sizePro=2; WriteCall(TexCoord_ReadDirect_UShort); break;
|
||||
case FORMAT_SHORT: sizePro=2; WriteCall(TexCoord_ReadDirect_Short); break;
|
||||
case FORMAT_FLOAT: sizePro=4; WriteCall(TexCoord_ReadDirect_Float); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
m_VertexSize += sizePro * (elements?2:1);
|
||||
}
|
||||
break;
|
||||
case INDEX8:
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_UBYTE: WriteCall(TexCoord_ReadIndex8_UByte); break;
|
||||
case FORMAT_BYTE: WriteCall(TexCoord_ReadIndex8_Byte); break;
|
||||
case FORMAT_USHORT: WriteCall(TexCoord_ReadIndex8_UShort); break;
|
||||
case FORMAT_SHORT: WriteCall(TexCoord_ReadIndex8_Short); break;
|
||||
case FORMAT_FLOAT: WriteCall(TexCoord_ReadIndex8_Float); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
m_VertexSize+=1;
|
||||
break;
|
||||
case INDEX16:
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_UBYTE: WriteCall(TexCoord_ReadIndex16_UByte); break;
|
||||
case FORMAT_BYTE: WriteCall(TexCoord_ReadIndex16_Byte); break;
|
||||
case FORMAT_USHORT: WriteCall(TexCoord_ReadIndex16_UShort); break;
|
||||
case FORMAT_SHORT: WriteCall(TexCoord_ReadIndex16_Short); break;
|
||||
case FORMAT_FLOAT: WriteCall(TexCoord_ReadIndex16_Float); break;
|
||||
default: _assert_(0);
|
||||
}
|
||||
m_VertexSize+=2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VertexLoader::WriteCall(void (LOADERDECL *func)(void *))
|
||||
{
|
||||
m_PipelineStates[m_numPipelineStates++] = func;;
|
||||
}
|
||||
|
||||
using namespace Gen;
|
||||
|
||||
// See comment in RunVertices
|
||||
void VertexLoader::Compile()
|
||||
{
|
||||
return;
|
||||
/* Gen::SetCodePtr(m_compiledCode);
|
||||
//INT3();
|
||||
Gen::Util::EmitPrologue(0);
|
||||
|
||||
const u8 *loopStart = Gen::GetCodePtr();
|
||||
MOV(32, M(&tcIndex), Imm32(0));
|
||||
MOV(32, M(&colIndex), Imm32(0));
|
||||
|
||||
for (int i = 0; i < m_numPipelineStates; i++)
|
||||
{
|
||||
PUSH(32, Imm32((u32)&m_VtxAttr));
|
||||
CALL(m_PipelineStates[i]);
|
||||
ADD(32, R(ESP), Imm8(4));
|
||||
}
|
||||
|
||||
ADD(32, M(&varray->count), Imm8(1));
|
||||
SUB(32, M(&this->m_counter), Imm8(1));
|
||||
J_CC(CC_NZ, loopStart, true);
|
||||
// Epilogue
|
||||
Gen::Util::EmitEpilogue(0);
|
||||
if (Gen::GetCodePtr()-(u8*)m_compiledCode > sizeof(m_compiledCode))
|
||||
{
|
||||
Crash();
|
||||
}*/
|
||||
}
|
||||
|
||||
void VertexLoader::PrepareRun()
|
||||
{
|
||||
posScale = shiftLookup[m_VtxAttr.PosFrac];
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
tcScaleU[i] = shiftLookup[m_VtxAttr.texCoord[i].Frac];
|
||||
tcScaleV[i] = shiftLookup[m_VtxAttr.texCoord[i].Frac];
|
||||
tcElements[i] = m_VtxAttr.texCoord[i].Elements;
|
||||
tcFormat[i] = m_VtxAttr.texCoord[i].Format;
|
||||
}
|
||||
for (int i = 0; i < 2; i++)
|
||||
colElements[i] = m_VtxAttr.color[i].Elements;
|
||||
|
||||
varray->Reset();
|
||||
varray->SetComponents(m_components);
|
||||
}
|
||||
|
||||
void VertexLoader::RunVertices(int count)
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
|
||||
for (int v = 0; v < count; v++)
|
||||
{
|
||||
tcIndex = 0;
|
||||
colIndex = 0;
|
||||
for (int i = 0; i < m_numPipelineStates; i++)
|
||||
{
|
||||
m_PipelineStates[i](&m_VtxAttr);
|
||||
}
|
||||
varray->Next();
|
||||
}
|
||||
/*
|
||||
This is not the bottleneck ATM, so compiling etc doesn't really help.
|
||||
At least not when all we do is compile it to a list of function calls.
|
||||
Should help more when we inline, but this requires the new vertex format.
|
||||
Maybe later, and with smarter caching.
|
||||
|
||||
if (count)
|
||||
{
|
||||
this->m_counter = count;
|
||||
((void (*)())((void*)&m_compiledCode[0]))();
|
||||
}*/
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
#ifndef _VERTEXLOADER_H
|
||||
#define _VERTEXLOADER_H
|
||||
|
||||
/*
|
||||
Ideas for new intermediate vertex format
|
||||
|
||||
Produce a mask specifying with components are present.
|
||||
|
||||
Decoder always produces a canonical format for all components:
|
||||
|
||||
Ubyte4 for matrix indices (x,y,z,w) and colors
|
||||
|
||||
FloatN for all others, texcoords are always XY at this stage
|
||||
|
||||
The decoders will write a continuous stream of vertices, to take maximum
|
||||
advantage of write combining hardware
|
||||
|
||||
a map<mask, vdecl> will keep track of vertex declarations
|
||||
|
||||
this time, we are going to minimize transfers to the gfx card
|
||||
|
||||
it turns out that with PS2.0 we can easily do all the pipeline in hardware.
|
||||
The decision will be how granular to be with the number of shaders and lighting settin
|
||||
|
||||
*/
|
||||
|
||||
enum {
|
||||
VB_HAS_POSMTXIDX =(1<<1),
|
||||
VB_HAS_TEXMTXIDX0=(1<<2),
|
||||
VB_HAS_TEXMTXIDX1=(1<<3),
|
||||
VB_HAS_TEXMTXIDX2=(1<<4),
|
||||
VB_HAS_TEXMTXIDX3=(1<<5),
|
||||
VB_HAS_TEXMTXIDX4=(1<<6),
|
||||
VB_HAS_TEXMTXIDX5=(1<<7),
|
||||
VB_HAS_TEXMTXIDX6=(1<<8),
|
||||
VB_HAS_TEXMTXIDX7=(1<<9),
|
||||
//VB_HAS_POS=0, // Implied, it always has pos! don't bother testing
|
||||
VB_HAS_NRM0=(1<<10),
|
||||
VB_HAS_NRM1=(1<<11),
|
||||
VB_HAS_NRM2=(1<<12),
|
||||
|
||||
VB_HAS_COL0=(1<<13),
|
||||
VB_HAS_COL1=(1<<14),
|
||||
|
||||
VB_HAS_UV0=(1<<15),
|
||||
VB_HAS_UV1=(1<<16),
|
||||
VB_HAS_UV2=(1<<17),
|
||||
VB_HAS_UV3=(1<<18),
|
||||
VB_HAS_UV4=(1<<19),
|
||||
VB_HAS_UV5=(1<<20),
|
||||
VB_HAS_UV6=(1<<21),
|
||||
VB_HAS_UV7=(1<<22),
|
||||
};
|
||||
|
||||
int ComputeVertexSize(u32 components);
|
||||
|
||||
#include "CPStructs.h"
|
||||
#include "DecodedVArray.h"
|
||||
|
||||
#define LOADERDECL __cdecl
|
||||
typedef void (LOADERDECL *TPipelineFunction)(void*);
|
||||
|
||||
class VertexLoader
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
NRM_ZERO = 0,
|
||||
NRM_ONE = 1,
|
||||
NRM_THREE = 3
|
||||
};
|
||||
|
||||
private:
|
||||
TPipelineFunction m_PipelineStates[32];
|
||||
int m_numPipelineStates;
|
||||
int m_VertexSize;
|
||||
int m_counter;
|
||||
u8 m_compiledCode[1024];
|
||||
|
||||
u32 m_components;
|
||||
|
||||
UVAT_group0 m_group0;
|
||||
UVAT_group1 m_group1;
|
||||
UVAT_group2 m_group2;
|
||||
|
||||
bool m_AttrDirty;
|
||||
|
||||
TVtxAttr m_VtxAttr; //Decoded into easy format
|
||||
|
||||
//common for all loaders
|
||||
static TVtxDesc m_VtxDesc;
|
||||
static bool m_DescDirty;
|
||||
|
||||
// seup the pipeline with this vertex fmt
|
||||
void SetupColor(int num, int _iMode, int _iFormat, int _iElements);
|
||||
void SetupTexCoord(int num, int _iMode, int _iFormat, int _iElements, int _iFrac);
|
||||
|
||||
public:
|
||||
// constructor
|
||||
VertexLoader();
|
||||
~VertexLoader();
|
||||
// run the pipeline
|
||||
static void SetVArray(DecodedVArray *_varray);
|
||||
void Setup();
|
||||
void Compile();
|
||||
void PrepareRun();
|
||||
void RunVertices(int count);
|
||||
void WriteCall(void (LOADERDECL *func)(void *));
|
||||
int GetVertexSize(){return m_VertexSize;}
|
||||
|
||||
//VtxDesc - global
|
||||
static void SetVtxDesc_Lo(u32 _iValue)
|
||||
{
|
||||
u64 old = m_VtxDesc.Hex;
|
||||
m_VtxDesc.Hex &= ~0x1FFFF; // keep the Upper bits
|
||||
m_VtxDesc.Hex |= _iValue;
|
||||
if (m_VtxDesc.Hex != old)
|
||||
m_DescDirty = true;
|
||||
};
|
||||
|
||||
static void SetVtxDesc_Hi(u32 _iValue)
|
||||
{
|
||||
u64 old = m_VtxDesc.Hex;
|
||||
m_VtxDesc.Hex &= 0x1FFFF; // keep the lower 17Bits
|
||||
m_VtxDesc.Hex |= (u64)_iValue << 17;
|
||||
if (m_VtxDesc.Hex != old)
|
||||
m_DescDirty = true;
|
||||
};
|
||||
|
||||
static TVtxDesc &GetVtxDesc() {return m_VtxDesc;}
|
||||
|
||||
void SetVAT_group0(u32 _group0)
|
||||
{
|
||||
if (!m_AttrDirty && m_group0.Hex == _group0)
|
||||
return;
|
||||
m_AttrDirty = true;
|
||||
m_group0.Hex = _group0;
|
||||
|
||||
m_VtxAttr.PosElements = m_group0.PosElements;
|
||||
m_VtxAttr.PosFormat = m_group0.PosFormat;
|
||||
m_VtxAttr.PosFrac = m_group0.PosFrac;
|
||||
m_VtxAttr.NormalElements = m_group0.NormalElements;
|
||||
m_VtxAttr.NormalFormat = m_group0.NormalFormat;
|
||||
m_VtxAttr.color[0].Elements = m_group0.Color0Elements;
|
||||
m_VtxAttr.color[0].Comp = m_group0.Color0Comp;
|
||||
m_VtxAttr.color[1].Elements = m_group0.Color1Elements;
|
||||
m_VtxAttr.color[1].Comp = m_group0.Color1Comp;
|
||||
m_VtxAttr.texCoord[0].Elements = m_group0.Tex0CoordElements;
|
||||
m_VtxAttr.texCoord[0].Format = m_group0.Tex0CoordFormat;
|
||||
m_VtxAttr.texCoord[0].Frac = m_group0.Tex0Frac;
|
||||
m_VtxAttr.ByteDequant = m_group0.ByteDequant;
|
||||
m_VtxAttr.NormalIndex3 = m_group0.NormalIndex3;
|
||||
};
|
||||
|
||||
void SetVAT_group1(u32 _group1)
|
||||
{
|
||||
if (m_group1.Hex == _group1)
|
||||
return;
|
||||
m_AttrDirty = true;
|
||||
m_group1.Hex = _group1;
|
||||
|
||||
m_VtxAttr.texCoord[1].Elements = m_group1.Tex1CoordElements;
|
||||
m_VtxAttr.texCoord[1].Format = m_group1.Tex1CoordFormat;
|
||||
m_VtxAttr.texCoord[1].Frac = m_group1.Tex1Frac;
|
||||
m_VtxAttr.texCoord[2].Elements = m_group1.Tex2CoordElements;
|
||||
m_VtxAttr.texCoord[2].Format = m_group1.Tex2CoordFormat;
|
||||
m_VtxAttr.texCoord[2].Frac = m_group1.Tex2Frac;
|
||||
m_VtxAttr.texCoord[3].Elements = m_group1.Tex3CoordElements;
|
||||
m_VtxAttr.texCoord[3].Format = m_group1.Tex3CoordFormat;
|
||||
m_VtxAttr.texCoord[3].Frac = m_group1.Tex3Frac;
|
||||
m_VtxAttr.texCoord[4].Elements = m_group1.Tex4CoordElements;
|
||||
m_VtxAttr.texCoord[4].Format = m_group1.Tex4CoordFormat;
|
||||
};
|
||||
|
||||
void SetVAT_group2(u32 _group2)
|
||||
{
|
||||
if (m_group2.Hex == _group2)
|
||||
return;
|
||||
m_AttrDirty = true;
|
||||
m_group2.Hex = _group2;
|
||||
|
||||
m_VtxAttr.texCoord[4].Frac = m_group2.Tex4Frac;
|
||||
m_VtxAttr.texCoord[5].Elements = m_group2.Tex5CoordElements;
|
||||
m_VtxAttr.texCoord[5].Format = m_group2.Tex5CoordFormat;
|
||||
m_VtxAttr.texCoord[5].Frac = m_group2.Tex5Frac;
|
||||
m_VtxAttr.texCoord[6].Elements = m_group2.Tex6CoordElements;
|
||||
m_VtxAttr.texCoord[6].Format = m_group2.Tex6CoordFormat;
|
||||
m_VtxAttr.texCoord[6].Frac = m_group2.Tex6Frac;
|
||||
m_VtxAttr.texCoord[7].Elements = m_group2.Tex7CoordElements;
|
||||
m_VtxAttr.texCoord[7].Format = m_group2.Tex7CoordFormat;
|
||||
m_VtxAttr.texCoord[7].Frac = m_group2.Tex7Frac;
|
||||
};
|
||||
};
|
||||
|
||||
extern VertexLoader g_VertexLoaders[8];
|
||||
extern DecodedVArray* varray;
|
||||
extern inline u8 ReadBuffer8();
|
||||
extern inline u16 ReadBuffer16();
|
||||
extern inline u32 ReadBuffer32();
|
||||
extern inline float ReadBuffer32F();
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,206 @@
|
||||
#pragma once
|
||||
|
||||
#include "Utils.h"
|
||||
|
||||
#define RSHIFT 16
|
||||
#define GSHIFT 8
|
||||
#define BSHIFT 0
|
||||
#define ASHIFT 24
|
||||
|
||||
extern DecodedVArray *varray;
|
||||
extern int colIndex;
|
||||
|
||||
inline void _SetCol(u32 val)
|
||||
{
|
||||
varray->SetColor(colIndex, val);
|
||||
colIndex++;
|
||||
}
|
||||
|
||||
void _SetCol4444(u16 val)
|
||||
{
|
||||
u32 col = lut4to8[(val>>0)&0xF]<<ASHIFT;
|
||||
col |= lut4to8[(val>>12)&0xF] <<RSHIFT;
|
||||
col |= lut4to8[(val>>8)&0xF] <<GSHIFT;
|
||||
col |= lut4to8[(val>>4)&0xF] <<BSHIFT;
|
||||
_SetCol(col);
|
||||
}
|
||||
|
||||
void _SetCol6666(u32 val)
|
||||
{
|
||||
u32 col = lut6to8[(val>>18)&0x3F] << RSHIFT;
|
||||
col |= lut6to8[(val>>12)&0x3F] << GSHIFT;
|
||||
col |= lut6to8[(val>>6)&0x3F] << BSHIFT;
|
||||
col |= lut6to8[(val>>0)&0x3F] << ASHIFT;
|
||||
_SetCol(col);
|
||||
}
|
||||
|
||||
void _SetCol565(u16 val)
|
||||
{
|
||||
u32 col = lut5to8[(val>>11)&0x1f] << RSHIFT;
|
||||
col |= lut6to8[(val>>5 )&0x3f] << GSHIFT;
|
||||
col |= lut5to8[(val )&0x1f] << BSHIFT;
|
||||
_SetCol(col | (0xFF<<ASHIFT));
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline u32 _Read24(u32 iAddress)
|
||||
{
|
||||
u32 col = Memory_Read_U8(iAddress) << RSHIFT; //should just get a pointer to main memory instead of going thru slow memhandler
|
||||
col |= Memory_Read_U8(iAddress+1) << GSHIFT; //we can guarantee that it is reading from main memory
|
||||
col |= Memory_Read_U8(iAddress+2) << BSHIFT;
|
||||
return col | (0xFF<<ASHIFT);
|
||||
}
|
||||
|
||||
inline u32 _Read32(u32 iAddress)
|
||||
{
|
||||
u32 col = Memory_Read_U8(iAddress) << RSHIFT; //should just get a pointer to main memory instead of going thru slow memhandler
|
||||
col |= Memory_Read_U8(iAddress+1) << GSHIFT; //we can guarantee that it is reading from main memory
|
||||
col |= Memory_Read_U8(iAddress+2) << BSHIFT;
|
||||
col |= Memory_Read_U8(iAddress+3) << ASHIFT;
|
||||
return col;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void LOADERDECL Color_ReadDirect_24b_888(void* _p)
|
||||
{
|
||||
u32 col = ReadBuffer8()<<RSHIFT;
|
||||
col |= ReadBuffer8()<<GSHIFT;
|
||||
col |= ReadBuffer8()<<BSHIFT;
|
||||
_SetCol(col | (0xFF<<ASHIFT));
|
||||
}
|
||||
|
||||
void LOADERDECL Color_ReadDirect_32b_888x(void* _p){
|
||||
u32 col = ReadBuffer8()<<RSHIFT;
|
||||
col |= ReadBuffer8()<<GSHIFT;
|
||||
col |= ReadBuffer8()<<BSHIFT;
|
||||
_SetCol(col | (0xFF<<ASHIFT));
|
||||
ReadBuffer8();
|
||||
}
|
||||
void LOADERDECL Color_ReadDirect_16b_565(void* _p)
|
||||
{
|
||||
_SetCol565(ReadBuffer16());
|
||||
}
|
||||
void LOADERDECL Color_ReadDirect_16b_4444(void *_p)
|
||||
{
|
||||
_SetCol4444(ReadBuffer16());
|
||||
}
|
||||
void LOADERDECL Color_ReadDirect_24b_6666(void* _p)
|
||||
{
|
||||
u32 val = ReadBuffer8()<<16;
|
||||
val|=ReadBuffer8()<<8;
|
||||
val|=ReadBuffer8();
|
||||
_SetCol6666(val);
|
||||
}
|
||||
|
||||
// F|RES: i am not 100 percent show, but the colElements seems to be important for rendering only
|
||||
// at least it fixes mario party 4
|
||||
//
|
||||
// if (colElements[colIndex])
|
||||
// else
|
||||
// col |= 0xFF<<ASHIFT;
|
||||
//
|
||||
void LOADERDECL Color_ReadDirect_32b_8888(void* _p)
|
||||
{
|
||||
u32 col = ReadBuffer8()<<RSHIFT;
|
||||
col |= ReadBuffer8()<<GSHIFT;
|
||||
col |= ReadBuffer8()<<BSHIFT;
|
||||
col |= ReadBuffer8()<<ASHIFT;
|
||||
|
||||
// "kill" the alpha
|
||||
if (!colElements[colIndex])
|
||||
col |= 0xFF<<ASHIFT;
|
||||
|
||||
_SetCol(col);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void LOADERDECL Color_ReadIndex8_16b_565(void* _p)
|
||||
{
|
||||
u8 Index = ReadBuffer8();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
u16 val = Memory_Read_U16(iAddress);
|
||||
_SetCol565(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex8_24b_888(void* _p)
|
||||
{
|
||||
u8 Index = ReadBuffer8();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
_SetCol(_Read24(iAddress));
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex8_32b_888x(void* _p)
|
||||
{
|
||||
u8 Index = ReadBuffer8();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR]+colIndex);
|
||||
_SetCol(_Read24(iAddress));
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex8_16b_4444(void* _p)
|
||||
{
|
||||
u8 Index = ReadBuffer8();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
u16 val = Memory_Read_U16(iAddress);
|
||||
_SetCol4444(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex8_24b_6666(void* _p)
|
||||
{
|
||||
u8 Index = ReadBuffer8();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
u32 val = Memory_Read_U8(iAddress+2) |
|
||||
(Memory_Read_U8(iAddress+1)<<8) |
|
||||
(Memory_Read_U8(iAddress)<<16);
|
||||
|
||||
_SetCol6666(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex8_32b_8888(void* _p)
|
||||
{
|
||||
u8 Index = ReadBuffer8();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
_SetCol(_Read32(iAddress));
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void LOADERDECL Color_ReadIndex16_16b_565(void* _p)
|
||||
{
|
||||
u16 Index = ReadBuffer16();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
u16 val = Memory_Read_U16(iAddress);
|
||||
_SetCol565(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex16_24b_888(void* _p)
|
||||
{
|
||||
u16 Index = ReadBuffer16();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
_SetCol(_Read24(iAddress));
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex16_32b_888x(void* _p)
|
||||
{
|
||||
u16 Index = ReadBuffer16();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
_SetCol(_Read24(iAddress));
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex16_16b_4444(void* _p)
|
||||
{
|
||||
u16 Index = ReadBuffer16();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
u16 val = Memory_Read_U16(iAddress);
|
||||
_SetCol4444(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex16_24b_6666(void* _p)
|
||||
{
|
||||
u16 Index = ReadBuffer16();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
u32 val = Memory_Read_U8(iAddress+2) |
|
||||
(Memory_Read_U8(iAddress+1)<<8) |
|
||||
(Memory_Read_U8(iAddress)<<16);
|
||||
_SetCol6666(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex16_32b_8888(void* _p)
|
||||
{
|
||||
u16 Index = ReadBuffer16();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
_SetCol(_Read32(iAddress));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "TransformEngine.h"
|
||||
|
||||
// ==============================================================================
|
||||
// Direct
|
||||
// ==============================================================================
|
||||
void LOADERDECL PosMtx_ReadDirect_UByte(void* _p)
|
||||
{
|
||||
TVtxAttr* pVtxAttr = (TVtxAttr*)_p;
|
||||
int index = ReadBuffer8();
|
||||
float *flipmem = (float *)xfmem;
|
||||
varray->SetPosNrmIdx(index);
|
||||
}
|
||||
|
||||
#define MAKETEX(n) \
|
||||
void LOADERDECL TexMtx_ReadDirect_UByte##n(void* _p) \
|
||||
{ \
|
||||
TVtxAttr* pVtxAttr = (TVtxAttr*)_p; \
|
||||
int index = ReadBuffer8(); \
|
||||
varray->SetTcIdx(n, index); \
|
||||
}
|
||||
|
||||
MAKETEX(0)
|
||||
MAKETEX(1)
|
||||
MAKETEX(2)
|
||||
MAKETEX(3)
|
||||
MAKETEX(4)
|
||||
MAKETEX(5)
|
||||
MAKETEX(6)
|
||||
MAKETEX(7)
|
||||
@@ -0,0 +1,475 @@
|
||||
//__________________________________________________________________________________________________
|
||||
// F|RES 2003-2005
|
||||
//
|
||||
|
||||
#include "main.h"
|
||||
#include "Utils.h"
|
||||
#include "DecodedVArray.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "VertexLoader_Normal.h"
|
||||
|
||||
BYTE VertexLoader_Normal::m_sizeTable[NUM_NRM_TYPE][NUM_NRM_FORMAT][NUM_NRM_ELEMENTS];
|
||||
TPipelineFunction VertexLoader_Normal::m_funcTable[NUM_NRM_TYPE][NUM_NRM_FORMAT][NUM_NRM_ELEMENTS];
|
||||
|
||||
bool VertexLoader_Normal::index3;
|
||||
// __________________________________________________________________________________________________
|
||||
// Init
|
||||
//
|
||||
void VertexLoader_Normal::Init(void)
|
||||
{
|
||||
// size table
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT] = 3;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT] = 3;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT] = 6;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT] = 6;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT] = 12;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT3] = 9;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT3] = 9;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT3] = 18;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT3] = 18;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT3] = 36;
|
||||
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT] = 1;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT] = 1;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT] = 1;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT] = 1;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT] = 1;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT3] = 3;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT3] = 3;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT3] = 3;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT3] = 3;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT3] = 3;
|
||||
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT] = 2;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT] = 2;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT] = 2;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT] = 2;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT] = 2;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT3] = 6;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT3] = 6;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT3] = 6;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT3] = 6;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT3] = 6;
|
||||
|
||||
// function table
|
||||
m_funcTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT] = Normal_DirectByte; //HACK
|
||||
m_funcTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT] = Normal_DirectByte;
|
||||
m_funcTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT] = Normal_DirectShort; //HACK
|
||||
m_funcTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT] = Normal_DirectShort;
|
||||
m_funcTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT] = Normal_DirectFloat;
|
||||
m_funcTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT3] = Normal_DirectByte3; //HACK
|
||||
m_funcTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT3] = Normal_DirectByte3;
|
||||
m_funcTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT3] = Normal_DirectShort3; //HACK
|
||||
m_funcTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT3] = Normal_DirectShort3;
|
||||
m_funcTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT3] = Normal_DirectFloat3;
|
||||
|
||||
m_funcTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT] = Normal_Index8_Byte; //HACK
|
||||
m_funcTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT] = Normal_Index8_Byte;
|
||||
m_funcTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT] = Normal_Index8_Short; //HACK
|
||||
m_funcTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT] = Normal_Index8_Short;
|
||||
m_funcTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT] = Normal_Index8_Float;
|
||||
m_funcTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT3] = Normal_Index8_Byte3; //HACK
|
||||
m_funcTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT3] = Normal_Index8_Byte3;
|
||||
m_funcTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT3] = Normal_Index8_Short3; //HACK
|
||||
m_funcTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT3] = Normal_Index8_Short3;
|
||||
m_funcTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT3] = Normal_Index8_Float3;
|
||||
|
||||
m_funcTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT] = Normal_Index16_Byte; //HACK
|
||||
m_funcTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT] = Normal_Index16_Byte;
|
||||
m_funcTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT] = Normal_Index16_Short; //HACK
|
||||
m_funcTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT] = Normal_Index16_Short;
|
||||
m_funcTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT] = Normal_Index16_Float;
|
||||
m_funcTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT3] = Normal_Index16_Byte3; //HACK
|
||||
m_funcTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT3] = Normal_Index16_Byte3;
|
||||
m_funcTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT3] = Normal_Index16_Short3; //HACK
|
||||
m_funcTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT3] = Normal_Index16_Short3;
|
||||
m_funcTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT3] = Normal_Index16_Float3;
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// GetSize
|
||||
//
|
||||
unsigned int
|
||||
VertexLoader_Normal::GetSize(unsigned int _type, unsigned int _format, unsigned int _elements)
|
||||
{
|
||||
return m_sizeTable[_type][_format][_elements];
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// GetFunction
|
||||
//
|
||||
TPipelineFunction
|
||||
VertexLoader_Normal::GetFunction(unsigned int _type, unsigned int _format, unsigned int _elements)
|
||||
{
|
||||
TPipelineFunction pFunc = m_funcTable[_type][_format][_elements];
|
||||
return pFunc;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// --- Direct ---
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_DirectByte
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_DirectByte(void* _p)
|
||||
{
|
||||
varray->SetNormalX(0, ((float)(signed char)ReadBuffer8()+0.5f) / 127.5f);
|
||||
varray->SetNormalY(0, ((float)(signed char)ReadBuffer8()+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(0, ((float)(signed char)ReadBuffer8()+0.5f) / 127.5f);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_DirectShort
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_DirectShort(void* _p)
|
||||
{
|
||||
varray->SetNormalX(0, ((float)(signed short)ReadBuffer16()+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(0, ((float)(signed short)ReadBuffer16()+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(0, ((float)(signed short)ReadBuffer16()+0.5f) / 32767.5f);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_DirectFloat
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_DirectFloat(void* _p)
|
||||
{
|
||||
varray->SetNormalX(0, ReadBuffer32F());
|
||||
varray->SetNormalY(0, ReadBuffer32F());
|
||||
varray->SetNormalZ(0, ReadBuffer32F());
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_DirectByte3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_DirectByte3(void* _p)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
varray->SetNormalX(i, ((float)(signed char)ReadBuffer8()+0.5f) / 127.5f);
|
||||
varray->SetNormalY(i, ((float)(signed char)ReadBuffer8()+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed char)ReadBuffer8()+0.5f) / 127.5f);
|
||||
}
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_DirectShort3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_DirectShort3(void* _p)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
varray->SetNormalX(i, ((float)(signed short)ReadBuffer16()+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(i, ((float)(signed short)ReadBuffer16()+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed short)ReadBuffer16()+0.5f) / 32767.5f);
|
||||
}
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_DirectFloat3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_DirectFloat3(void* _p)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
varray->SetNormalX(i, ReadBuffer32F());
|
||||
varray->SetNormalY(i, ReadBuffer32F());
|
||||
varray->SetNormalZ(i, ReadBuffer32F());
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// --- Index8 ---
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index8_Byte
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index8_Byte(void* _p)
|
||||
{
|
||||
u8 Index = ReadBuffer8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
|
||||
varray->SetNormalX(0, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
|
||||
varray->SetNormalY(0, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(0, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index8_Short
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index8_Short(void* _p)
|
||||
{
|
||||
u8 Index = ReadBuffer8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
|
||||
varray->SetNormalX(0, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(0, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(0, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index8_Float
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index8_Float(void* _p)
|
||||
{
|
||||
u8 Index = ReadBuffer8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
|
||||
varray->SetNormalX(0, Memory_Read_Float(iAddress));
|
||||
varray->SetNormalY(0, Memory_Read_Float(iAddress+4));
|
||||
varray->SetNormalZ(0, Memory_Read_Float(iAddress+8));
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index8_Byte3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index8_Byte3(void* _p)
|
||||
{
|
||||
if (index3)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u8 Index = ReadBuffer8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
|
||||
varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 Index = ReadBuffer8();
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
|
||||
varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index8_Short3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index8_Short3(void* _p)
|
||||
{
|
||||
if (index3)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u8 Index = ReadBuffer8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 Index = ReadBuffer8();
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index8_Float3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index8_Float3(void* _p)
|
||||
{
|
||||
if (index3)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u8 Index = ReadBuffer8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
|
||||
|
||||
varray->SetNormalX(i, Memory_Read_Float(iAddress));
|
||||
varray->SetNormalY(i, Memory_Read_Float(iAddress+4));
|
||||
varray->SetNormalZ(i, Memory_Read_Float(iAddress+8));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 Index = ReadBuffer8();
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
|
||||
|
||||
varray->SetNormalX(i, Memory_Read_Float(iAddress));
|
||||
varray->SetNormalY(i, Memory_Read_Float(iAddress+4));
|
||||
varray->SetNormalZ(i, Memory_Read_Float(iAddress+8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// --- Index16 ---
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index16_Byte
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index16_Byte(void* _p)
|
||||
{
|
||||
u16 Index = ReadBuffer16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
|
||||
varray->SetNormalX(0, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
|
||||
varray->SetNormalY(0, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(0, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index16_Short
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index16_Short(void* _p)
|
||||
{
|
||||
u16 Index = ReadBuffer16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
|
||||
varray->SetNormalX(0, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(0, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(0, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index8_Float
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index16_Float(void* _p)
|
||||
{
|
||||
u16 Index = ReadBuffer16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
|
||||
varray->SetNormalX(0, Memory_Read_Float(iAddress));
|
||||
varray->SetNormalY(0, Memory_Read_Float(iAddress+4));
|
||||
varray->SetNormalZ(0, Memory_Read_Float(iAddress+8));
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index16_Byte3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index16_Byte3(void* _p)
|
||||
{
|
||||
if (index3)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u16 Index = ReadBuffer16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
|
||||
varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u16 Index = ReadBuffer16();
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
|
||||
varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index16_Short3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index16_Short3(void* _p)
|
||||
{
|
||||
if (index3)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u16 Index = ReadBuffer16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u16 Index = ReadBuffer16();
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index16_Float3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index16_Float3(void* _p)
|
||||
{
|
||||
if (index3)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u16 Index = ReadBuffer16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
|
||||
|
||||
varray->SetNormalX(i, Memory_Read_Float(iAddress ));
|
||||
varray->SetNormalY(i, Memory_Read_Float(iAddress+4));
|
||||
varray->SetNormalZ(i, Memory_Read_Float(iAddress+8));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u16 Index = ReadBuffer16();
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
|
||||
|
||||
varray->SetNormalX(i, Memory_Read_Float(iAddress ));
|
||||
varray->SetNormalY(i, Memory_Read_Float(iAddress+4));
|
||||
varray->SetNormalZ(i, Memory_Read_Float(iAddress+8));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
//__________________________________________________________________________________________________
|
||||
// F|RES 2003-2005
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
class VertexLoader_Normal
|
||||
{
|
||||
public:
|
||||
|
||||
static bool index3;
|
||||
// Init
|
||||
static void Init(void);
|
||||
|
||||
// GetSize
|
||||
static unsigned int GetSize(unsigned int _type, unsigned int _format, unsigned int _elements);
|
||||
|
||||
// GetFunction
|
||||
static TPipelineFunction GetFunction(unsigned int _type, unsigned int _format, unsigned int _elements);
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
enum ENormalElements
|
||||
{
|
||||
NRM_NBT = 0,
|
||||
NRM_NBT3 = 1,
|
||||
NUM_NRM_ELEMENTS
|
||||
};
|
||||
|
||||
// tables
|
||||
static BYTE m_sizeTable[NUM_NRM_TYPE][NUM_NRM_FORMAT][NUM_NRM_ELEMENTS];
|
||||
static TPipelineFunction m_funcTable[NUM_NRM_TYPE][NUM_NRM_FORMAT][NUM_NRM_ELEMENTS];
|
||||
|
||||
// direct
|
||||
static void LOADERDECL Normal_DirectByte(void* _p);
|
||||
static void LOADERDECL Normal_DirectShort(void* _p);
|
||||
static void LOADERDECL Normal_DirectFloat(void* _p);
|
||||
static void LOADERDECL Normal_DirectByte3(void* _p);
|
||||
static void LOADERDECL Normal_DirectShort3(void* _p);
|
||||
static void LOADERDECL Normal_DirectFloat3(void* _p);
|
||||
|
||||
// index8
|
||||
static void LOADERDECL Normal_Index8_Byte(void* _p);
|
||||
static void LOADERDECL Normal_Index8_Short(void* _p);
|
||||
static void LOADERDECL Normal_Index8_Float(void* _p);
|
||||
static void LOADERDECL Normal_Index8_Byte3(void* _p);
|
||||
static void LOADERDECL Normal_Index8_Short3(void* _p);
|
||||
static void LOADERDECL Normal_Index8_Float3(void* _p);
|
||||
|
||||
// index16
|
||||
static void LOADERDECL Normal_Index16_Byte(void* _p);
|
||||
static void LOADERDECL Normal_Index16_Short(void* _p);
|
||||
static void LOADERDECL Normal_Index16_Float(void* _p);
|
||||
static void LOADERDECL Normal_Index16_Byte3(void* _p);
|
||||
static void LOADERDECL Normal_Index16_Short3(void* _p);
|
||||
static void LOADERDECL Normal_Index16_Float3(void* _p);
|
||||
};
|
||||
@@ -0,0 +1,196 @@
|
||||
#ifndef VERTEXHANDLER_POSITION_H
|
||||
#define VERTEXHANDLER_POSITION_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "Utils.h"
|
||||
|
||||
|
||||
// ==============================================================================
|
||||
// Direct
|
||||
// ==============================================================================
|
||||
|
||||
template<class T>
|
||||
inline void LOADERDECL _ReadPos8Mem(int iAddress, TVtxAttr* pVtxAttr)
|
||||
{
|
||||
varray->SetPosX(((float)(T)Memory_Read_U8(iAddress)) * posScale);
|
||||
varray->SetPosY(((float)(T)Memory_Read_U8(iAddress+1)) * posScale);
|
||||
if (pVtxAttr->PosElements)
|
||||
varray->SetPosZ(((float)(T)Memory_Read_U8(iAddress+2)) * posScale);
|
||||
else
|
||||
varray->SetPosZ(1.0);
|
||||
}
|
||||
template<class T>
|
||||
inline void LOADERDECL _ReadPos16Mem(int iAddress, TVtxAttr* pVtxAttr)
|
||||
{
|
||||
varray->SetPosX(((float)(T)Memory_Read_U16(iAddress)) * posScale);
|
||||
varray->SetPosY(((float)(T)Memory_Read_U16(iAddress+2)) * posScale);
|
||||
if (pVtxAttr->PosElements)
|
||||
varray->SetPosZ(((float)(T)Memory_Read_U16(iAddress+4)) * posScale);
|
||||
else
|
||||
varray->SetPosZ(1.0);
|
||||
}
|
||||
|
||||
void LOADERDECL _ReadPosFloatMem(int iAddress, TVtxAttr* pVtxAttr)
|
||||
{
|
||||
u32 uTemp;
|
||||
uTemp = Memory_Read_U32(iAddress );
|
||||
varray->SetPosX(*(float*)&uTemp);
|
||||
uTemp = Memory_Read_U32(iAddress+4);
|
||||
varray->SetPosY(*(float*)&uTemp);
|
||||
if (pVtxAttr->PosElements)
|
||||
{
|
||||
uTemp = Memory_Read_U32(iAddress+8);
|
||||
varray->SetPosZ(*(float*)&uTemp);
|
||||
}
|
||||
else
|
||||
varray->SetPosZ(1.0);
|
||||
}
|
||||
|
||||
void LOADERDECL Pos_ReadDirect_UByte(void* _p)
|
||||
{
|
||||
TVtxAttr* pVtxAttr = (TVtxAttr*)_p;
|
||||
varray->SetPosX((float)ReadBuffer8() * posScale);
|
||||
varray->SetPosY((float)ReadBuffer8() * posScale);
|
||||
|
||||
if (pVtxAttr->PosElements)
|
||||
varray->SetPosZ((float)ReadBuffer8() * posScale);
|
||||
else
|
||||
varray->SetPosZ(1.0);
|
||||
}
|
||||
|
||||
void LOADERDECL Pos_ReadDirect_Byte(void* _p)
|
||||
{
|
||||
TVtxAttr* pVtxAttr = (TVtxAttr*)_p;
|
||||
varray->SetPosX((float)(s8)ReadBuffer8() * posScale);
|
||||
varray->SetPosY((float)(s8)ReadBuffer8() * posScale);
|
||||
|
||||
if (pVtxAttr->PosElements)
|
||||
varray->SetPosZ((float)(s8)ReadBuffer8() * posScale);
|
||||
else
|
||||
varray->SetPosZ(1.0);
|
||||
}
|
||||
|
||||
void LOADERDECL Pos_ReadDirect_UShort(void* _p)
|
||||
{
|
||||
TVtxAttr* pVtxAttr = (TVtxAttr*)_p;
|
||||
|
||||
varray->SetPosX((float)ReadBuffer16() * posScale);
|
||||
varray->SetPosY((float)ReadBuffer16() * posScale);
|
||||
|
||||
if (pVtxAttr->PosElements)
|
||||
varray->SetPosZ((float)ReadBuffer16() * posScale);
|
||||
else
|
||||
varray->SetPosZ(1.0);
|
||||
}
|
||||
|
||||
void LOADERDECL Pos_ReadDirect_Short(void* _p)
|
||||
{
|
||||
TVtxAttr* pVtxAttr = (TVtxAttr*)_p;
|
||||
|
||||
varray->SetPosX((float)(s16)ReadBuffer16() * posScale);
|
||||
varray->SetPosY((float)(s16)ReadBuffer16() * posScale);
|
||||
|
||||
if (pVtxAttr->PosElements)
|
||||
varray->SetPosZ((float)(s16)ReadBuffer16() * posScale);
|
||||
else
|
||||
varray->SetPosZ(1.0);
|
||||
}
|
||||
|
||||
void LOADERDECL Pos_ReadDirect_Float(void* _p)
|
||||
{
|
||||
TVtxAttr* pVtxAttr = (TVtxAttr*)_p;
|
||||
|
||||
varray->SetPosX(ReadBuffer32F());
|
||||
varray->SetPosY(ReadBuffer32F());
|
||||
|
||||
if (pVtxAttr->PosElements)
|
||||
varray->SetPosZ(ReadBuffer32F());
|
||||
else
|
||||
varray->SetPosZ(1.0);
|
||||
}
|
||||
|
||||
// ==============================================================================
|
||||
// Index 8
|
||||
// ==============================================================================
|
||||
|
||||
void LOADERDECL Pos_ReadIndex8_UByte(void* _p)
|
||||
{
|
||||
TVtxAttr* pVtxAttr = (TVtxAttr*)_p;
|
||||
u8 Index = ReadBuffer8();
|
||||
u32 iAddress = arraybases[ARRAY_POSITION] + (Index * arraystrides[ARRAY_POSITION]);
|
||||
_ReadPos8Mem<u8>(iAddress, pVtxAttr);
|
||||
}
|
||||
void LOADERDECL Pos_ReadIndex8_Byte(void* _p)
|
||||
{
|
||||
TVtxAttr* pVtxAttr = (TVtxAttr*)_p;
|
||||
u8 Index = ReadBuffer8();
|
||||
u32 iAddress = arraybases[ARRAY_POSITION] + (Index * arraystrides[ARRAY_POSITION]);
|
||||
_ReadPos8Mem<s8>(iAddress, pVtxAttr);
|
||||
}
|
||||
|
||||
void LOADERDECL Pos_ReadIndex8_UShort(void* _p)
|
||||
{
|
||||
TVtxAttr* pVtxAttr = (TVtxAttr*)_p;
|
||||
u8 Index = ReadBuffer8();
|
||||
u32 iAddress = arraybases[ARRAY_POSITION] + (Index * arraystrides[ARRAY_POSITION]);
|
||||
_ReadPos16Mem<u16>(iAddress, pVtxAttr);
|
||||
}
|
||||
|
||||
void LOADERDECL Pos_ReadIndex8_Short(void* _p)
|
||||
{
|
||||
TVtxAttr* pVtxAttr = (TVtxAttr*)_p;
|
||||
u8 Index = ReadBuffer8();
|
||||
u32 iAddress = arraybases[ARRAY_POSITION] + (Index * arraystrides[ARRAY_POSITION]);
|
||||
_ReadPos16Mem<s16>(iAddress, pVtxAttr);
|
||||
}
|
||||
|
||||
void LOADERDECL Pos_ReadIndex8_Float(void* _p)
|
||||
{
|
||||
TVtxAttr* pVtxAttr = (TVtxAttr*)_p;
|
||||
u8 Index = ReadBuffer8();
|
||||
u32 iAddress = arraybases[ARRAY_POSITION] + (Index * arraystrides[ARRAY_POSITION]);
|
||||
_ReadPosFloatMem(iAddress, pVtxAttr);
|
||||
}
|
||||
|
||||
// ==============================================================================
|
||||
// Index 16
|
||||
// ==============================================================================
|
||||
|
||||
void LOADERDECL Pos_ReadIndex16_UByte(void* _p){
|
||||
TVtxAttr* pVtxAttr = (TVtxAttr*)_p;
|
||||
u16 Index = ReadBuffer16();
|
||||
u32 iAddress = arraybases[ARRAY_POSITION] + (Index * arraystrides[ARRAY_POSITION]);
|
||||
_ReadPos8Mem<u8>(iAddress, pVtxAttr);
|
||||
}
|
||||
|
||||
void LOADERDECL Pos_ReadIndex16_Byte(void* _p){
|
||||
TVtxAttr* pVtxAttr = (TVtxAttr*)_p;
|
||||
u16 Index = ReadBuffer16();
|
||||
u32 iAddress = arraybases[ARRAY_POSITION] + (Index * arraystrides[ARRAY_POSITION]);
|
||||
_ReadPos8Mem<s8>(iAddress, pVtxAttr);
|
||||
}
|
||||
|
||||
void LOADERDECL Pos_ReadIndex16_UShort(void* _p){
|
||||
TVtxAttr* pVtxAttr = (TVtxAttr*)_p;
|
||||
u16 Index = ReadBuffer16();
|
||||
u32 iAddress = arraybases[ARRAY_POSITION] + (Index * arraystrides[ARRAY_POSITION]);
|
||||
_ReadPos16Mem<u16>(iAddress, pVtxAttr);
|
||||
}
|
||||
|
||||
void LOADERDECL Pos_ReadIndex16_Short(void* _p)
|
||||
{
|
||||
TVtxAttr* pVtxAttr = (TVtxAttr*)_p;
|
||||
u16 Index = ReadBuffer16();
|
||||
u32 iAddress = arraybases[ARRAY_POSITION] + (Index * arraystrides[ARRAY_POSITION]);
|
||||
_ReadPos16Mem<s16>(iAddress, pVtxAttr);
|
||||
}
|
||||
|
||||
void LOADERDECL Pos_ReadIndex16_Float(void* _p)
|
||||
{
|
||||
TVtxAttr* pVtxAttr = (TVtxAttr*)_p;
|
||||
u16 Index = ReadBuffer16();
|
||||
u32 iAddress = arraybases[ARRAY_POSITION] + (Index * arraystrides[ARRAY_POSITION]);
|
||||
_ReadPosFloatMem(iAddress, pVtxAttr);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,185 @@
|
||||
#ifndef VERTEXHANDLER_TEXCOORD_H
|
||||
#define VERTEXHANDLER_TEXCOORD_H
|
||||
|
||||
extern int tcIndex;
|
||||
|
||||
void LOADERDECL TexCoord_ReadDirect_UByte(void* _p)
|
||||
{
|
||||
varray->SetU(tcIndex, ReadBuffer8() * tcScaleU[tcIndex]);
|
||||
if (tcElements[tcIndex])
|
||||
varray->SetV(tcIndex, ReadBuffer8() * tcScaleV[tcIndex]);
|
||||
tcIndex++;
|
||||
}
|
||||
|
||||
void LOADERDECL TexCoord_ReadDirect_Byte(void* _p)
|
||||
{
|
||||
varray->SetU(tcIndex, (s8)ReadBuffer8() * tcScaleU[tcIndex]);
|
||||
if (tcElements[tcIndex])
|
||||
varray->SetV(tcIndex, (s8)ReadBuffer8() * tcScaleV[tcIndex]);
|
||||
tcIndex++;
|
||||
}
|
||||
|
||||
void LOADERDECL TexCoord_ReadDirect_UShort(void* _p)
|
||||
{
|
||||
varray->SetU(tcIndex, ReadBuffer16() * tcScaleU[tcIndex]);
|
||||
if (tcElements[tcIndex])
|
||||
varray->SetV(tcIndex, ReadBuffer16() * tcScaleV[tcIndex]);
|
||||
tcIndex++;
|
||||
}
|
||||
|
||||
void LOADERDECL TexCoord_ReadDirect_Short(void* _p)
|
||||
{
|
||||
varray->SetU(tcIndex, (s16)ReadBuffer16() * tcScaleU[tcIndex]);
|
||||
if (tcElements[tcIndex])
|
||||
varray->SetV(tcIndex, (s16)ReadBuffer16() * tcScaleV[tcIndex]);
|
||||
tcIndex++;
|
||||
}
|
||||
void LOADERDECL TexCoord_ReadDirect_Float(void* _p)
|
||||
{
|
||||
varray->SetU(tcIndex, ReadBuffer32F() * tcScaleU[tcIndex]);
|
||||
if (tcElements[tcIndex])
|
||||
varray->SetV(tcIndex, ReadBuffer32F() * tcScaleV[tcIndex]);
|
||||
tcIndex++;
|
||||
}
|
||||
|
||||
// ==================================================================================
|
||||
void LOADERDECL TexCoord_ReadIndex8_UByte(void* _p)
|
||||
{
|
||||
u8 Index = ReadBuffer8();
|
||||
u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
|
||||
|
||||
varray->SetU(tcIndex, (float)(u8)Memory_Read_U8(iAddress) * tcScaleU[tcIndex]);
|
||||
if (tcElements[tcIndex])
|
||||
varray->SetV(tcIndex, (float)(u8)Memory_Read_U8(iAddress+1) * tcScaleV[tcIndex]);
|
||||
tcIndex++;
|
||||
}
|
||||
void LOADERDECL TexCoord_ReadIndex8_Byte(void* _p)
|
||||
{
|
||||
u8 Index = ReadBuffer8();
|
||||
u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
|
||||
|
||||
varray->SetU(tcIndex, (float)(s8)Memory_Read_U8(iAddress) * tcScaleU[tcIndex]);
|
||||
if (tcElements[tcIndex])
|
||||
varray->SetV(tcIndex, (float)(s8)Memory_Read_U8(iAddress+1) * tcScaleV[tcIndex]);
|
||||
|
||||
tcIndex++;
|
||||
}
|
||||
void LOADERDECL TexCoord_ReadIndex8_UShort(void* _p)
|
||||
{
|
||||
u8 Index = ReadBuffer8();
|
||||
u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
|
||||
|
||||
varray->SetU(tcIndex, (float)(u16)Memory_Read_U16(iAddress) * tcScaleU[tcIndex]);
|
||||
if (tcElements[tcIndex])
|
||||
varray->SetV(tcIndex, (float)(u16)Memory_Read_U16(iAddress+2) * tcScaleV[tcIndex]);
|
||||
tcIndex++;
|
||||
}
|
||||
void LOADERDECL TexCoord_ReadIndex8_Short(void* _p)
|
||||
{
|
||||
u8 Index = ReadBuffer8();
|
||||
u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
|
||||
|
||||
varray->SetU(tcIndex, (float)(s16)Memory_Read_U16(iAddress) * tcScaleU[tcIndex]);
|
||||
if (tcElements[tcIndex])
|
||||
varray->SetV(tcIndex, (float)(s16)Memory_Read_U16(iAddress+2) * tcScaleV[tcIndex]);
|
||||
tcIndex++;
|
||||
}
|
||||
void LOADERDECL TexCoord_ReadIndex8_Float(void* _p)
|
||||
{
|
||||
u16 Index = ReadBuffer8();
|
||||
u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
|
||||
u32 uTemp;
|
||||
uTemp = Memory_Read_U32(iAddress );
|
||||
varray->SetU(tcIndex, *(float*)&uTemp * tcScaleU[tcIndex]);
|
||||
if (tcElements[tcIndex])
|
||||
{
|
||||
uTemp = Memory_Read_U32(iAddress+4);
|
||||
varray->SetV(tcIndex, *(float*)&uTemp * tcScaleV[tcIndex]);
|
||||
}
|
||||
tcIndex++;
|
||||
}
|
||||
|
||||
|
||||
// ==================================================================================
|
||||
void LOADERDECL TexCoord_ReadIndex16_UByte(void* _p)
|
||||
{
|
||||
u16 Index = ReadBuffer16();
|
||||
u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
|
||||
|
||||
u32 uTemp;
|
||||
uTemp = (u8)Memory_Read_U8(iAddress );
|
||||
varray->SetU(tcIndex, float(uTemp)* tcScaleU[tcIndex]);
|
||||
|
||||
if (tcElements[tcIndex])
|
||||
{
|
||||
uTemp = (u8)Memory_Read_U8(iAddress+1);
|
||||
varray->SetV(tcIndex, float(uTemp)* tcScaleV[tcIndex]);
|
||||
}
|
||||
tcIndex++;
|
||||
}
|
||||
void LOADERDECL TexCoord_ReadIndex16_Byte(void* _p)
|
||||
{
|
||||
u16 Index = ReadBuffer16();
|
||||
u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
|
||||
|
||||
u32 uTemp;
|
||||
uTemp = (s8)Memory_Read_U8(iAddress );
|
||||
varray->SetU(tcIndex, float(uTemp)* tcScaleU[tcIndex]);
|
||||
|
||||
if (tcElements[tcIndex])
|
||||
{
|
||||
uTemp = (s8)Memory_Read_U8(iAddress+1);
|
||||
varray->SetV(tcIndex, float(uTemp)* tcScaleV[tcIndex]);
|
||||
}
|
||||
tcIndex++;
|
||||
}
|
||||
|
||||
void LOADERDECL TexCoord_ReadIndex16_UShort(void* _p)
|
||||
{
|
||||
TVtxAttr* pVtxAttr = (TVtxAttr*)_p;
|
||||
u16 Index = ReadBuffer16();
|
||||
u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
|
||||
|
||||
float uTemp;
|
||||
uTemp = (float)(u16)Memory_Read_U16(iAddress );
|
||||
varray->SetU(tcIndex, uTemp * tcScaleU[tcIndex]);
|
||||
|
||||
if (tcElements[tcIndex])
|
||||
{
|
||||
uTemp = (float)(u16)Memory_Read_U16(iAddress+2);
|
||||
varray->SetV(tcIndex, uTemp * tcScaleV[tcIndex]);
|
||||
}
|
||||
tcIndex++;
|
||||
}
|
||||
void LOADERDECL TexCoord_ReadIndex16_Short(void* _p)
|
||||
{
|
||||
u16 Index = ReadBuffer16();
|
||||
u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
|
||||
|
||||
float uTemp;
|
||||
uTemp = (float)(s16)Memory_Read_U16(iAddress );
|
||||
varray->SetU(tcIndex, uTemp * tcScaleU[tcIndex]);
|
||||
|
||||
if (tcElements[tcIndex])
|
||||
{
|
||||
uTemp = (float)(s16)Memory_Read_U16(iAddress+2);
|
||||
varray->SetV(tcIndex, uTemp * tcScaleV[tcIndex]);
|
||||
}
|
||||
tcIndex++;
|
||||
}
|
||||
void LOADERDECL TexCoord_ReadIndex16_Float(void* _p)
|
||||
{
|
||||
u16 Index = ReadBuffer16();
|
||||
u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
|
||||
u32 uTemp;
|
||||
uTemp = Memory_Read_U32(iAddress );
|
||||
varray->SetU(tcIndex, *(float*)&uTemp * tcScaleU[tcIndex]);
|
||||
if (tcElements[tcIndex])
|
||||
{
|
||||
uTemp = Memory_Read_U32(iAddress+4);
|
||||
varray->SetV(tcIndex, *(float*)&uTemp * tcScaleV[tcIndex]);
|
||||
}
|
||||
tcIndex++;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,119 @@
|
||||
#include "stdafx.h"
|
||||
#include "D3DShader.h"
|
||||
#include "VertexShader.h"
|
||||
#include "BPStructs.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//I hope we don't get too many hash collisions :p
|
||||
//all these magic numbers are primes, it should help a bit
|
||||
xformhash GetCurrentXForm()
|
||||
{
|
||||
//return 0;
|
||||
xformhash hash = bpmem.genMode.numtexgens*8*17;
|
||||
/*
|
||||
for (int i=0; i<bpmem.genMode.numtevstages+1; i++)
|
||||
{
|
||||
hash = _rotl(hash,3) ^ (bpmem.combiners[i].colorC.hex*13);
|
||||
hash = _rotl(hash,7) ^ ((bpmem.combiners[i].alphaC.hex&0xFFFFFFFC)*3);
|
||||
}
|
||||
for (int i=0; i<bpmem.genMode.numtevstages/2+1; i++)
|
||||
{
|
||||
hash = _rotl(hash,13) ^ (bpmem.tevorders[i].hex*7);
|
||||
}
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
hash = _rotl(hash,3) ^ bpmem.tevksel[i].swap1;
|
||||
hash = _rotl(hash,3) ^ bpmem.tevksel[i].swap2;
|
||||
}*/
|
||||
|
||||
// to hash: bpmem.tevorders[j/2].getTexCoord(j&1);
|
||||
// also texcoords array
|
||||
return hash;
|
||||
}
|
||||
|
||||
char text2[65536];
|
||||
#define WRITE p+=sprintf
|
||||
|
||||
void WriteTexgen(char *&p, int n);
|
||||
|
||||
LPDIRECT3DVERTEXSHADER9 GenerateVertexShader()
|
||||
{
|
||||
int numColors = 2;
|
||||
int numUV = 8;
|
||||
int numTexgen = bpmem.genMode.numtexgens;
|
||||
int numNormals = 3;
|
||||
bool fogEnable = false;
|
||||
bool hasNormal = true;
|
||||
|
||||
char *p = text2;
|
||||
WRITE(p,"//Vertex Shader\n");
|
||||
WRITE(p,"//%i uv->%i texgens, %i colors\n",numUV,numTexgen,numColors);
|
||||
WRITE(p,"\n");
|
||||
|
||||
WRITE(p,"struct VS_INPUT {\n");
|
||||
WRITE(p," float4 pos : POSITION;\n");
|
||||
WRITE(p," float3 normal : NORMAL;\n");
|
||||
if (numColors)
|
||||
WRITE(p," float4 colors[%i] : COLOR0;\n",numColors);
|
||||
if (numUV)
|
||||
WRITE(p," float3 uv[%i] : TEXCOORD0;\n",numUV);
|
||||
WRITE(p,"};\n");
|
||||
WRITE(p,"\n");
|
||||
|
||||
WRITE(p,"struct VS_OUTPUT {\n");
|
||||
WRITE(p," float4 pos : POSITION;\n");
|
||||
WRITE(p," float4 colors[%i] : COLOR0;\n",numColors);
|
||||
if (numTexgen)
|
||||
WRITE(p," float4 uv[%i] : TEXCOORD0;\n",numTexgen);
|
||||
if (fogEnable)
|
||||
WRITE(p," float fog : FOG;\n",numTexgen);
|
||||
WRITE(p,"};\n");
|
||||
WRITE(p,"\n");
|
||||
|
||||
WRITE(p,"uniform matrix matWorldViewProj : register(c0);\n");
|
||||
|
||||
WRITE(p,"\n");
|
||||
|
||||
WRITE(p,"VS_OUTPUT main(const VS_INPUT input)\n");
|
||||
WRITE(p,"{\n");
|
||||
WRITE(p," VS_OUTPUT output;");
|
||||
WRITE(p,"\n");
|
||||
|
||||
WRITE(p," output.pos = mul(matWorldViewProj, input.pos);\n");
|
||||
|
||||
for (int i = 0; i < (int)bpmem.genMode.numtexgens; i++)
|
||||
{
|
||||
//build the equation for this stage
|
||||
WriteTexgen(p,i);
|
||||
}
|
||||
|
||||
WRITE(p," for (int i=0; i<2; i++)\n output.colors[i] = input.colors[i];\n");
|
||||
// WRITE(p," output.fog = 0.0f;");
|
||||
WRITE(p,"return output;\n");
|
||||
WRITE(p,"}\n");
|
||||
WRITE(p,"\0");
|
||||
|
||||
// MessageBox(0,text2,0,0);
|
||||
return D3D::CompileVShader(text2,(int)(p-text2));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* xform->vertexshader ideas
|
||||
|
||||
*/
|
||||
|
||||
void WriteTexgen(char *&p, int n)
|
||||
{
|
||||
WRITE(p," output.uv[%i] = float4(input.uv[%i].xy,0,input.uv[%i].z);\n",n,n,n);
|
||||
}
|
||||
|
||||
|
||||
void WriteLight(int color, int component)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef _VERTEXSHADER_H
|
||||
#define _VERTEXSHADER_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
typedef u32 xformhash;
|
||||
|
||||
xformhash GetCurrentXForm();
|
||||
LPDIRECT3DVERTEXSHADER9 GenerateVertexShader();
|
||||
|
||||
#define PS_CONST_COLORS 0
|
||||
#define PS_CONST_KCOLORS 4
|
||||
#define PS_CONST_CONSTALPHA 8
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,265 @@
|
||||
#include "ChunkFile.h"
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
ChunkFile::ChunkFile(const TCHAR *filename, bool _read)
|
||||
{
|
||||
data=0;
|
||||
fastMode=false;
|
||||
if (file.Open(filename,_read ? FILE_READ : FILE_WRITE))
|
||||
{
|
||||
didFail=false;
|
||||
}
|
||||
else
|
||||
{
|
||||
didFail=true;
|
||||
return;
|
||||
}
|
||||
|
||||
int fSize = file.GetSize();
|
||||
|
||||
fastMode = _read ? true : false;
|
||||
|
||||
if (fastMode)
|
||||
{
|
||||
data = new char[fSize];
|
||||
file.Read(data,fSize);
|
||||
file.Close();
|
||||
// MessageBox(theApp->getHWND(),TEXT("FILECLOSED"),TEXT("MOSJ"),0);
|
||||
}
|
||||
|
||||
eof=fSize;
|
||||
numLevels=0;
|
||||
read=_read;
|
||||
pos=0;
|
||||
didFail=false;
|
||||
}
|
||||
|
||||
ChunkFile::~ChunkFile()
|
||||
{
|
||||
if (fastMode && data)
|
||||
delete [] data;
|
||||
else
|
||||
file.Close();
|
||||
}
|
||||
|
||||
|
||||
int ChunkFile::ReadInt()
|
||||
{
|
||||
if (pos<eof)
|
||||
{
|
||||
/*
|
||||
int temp = *(int *)(data+pos);
|
||||
pos+=4;
|
||||
*/
|
||||
pos+=4;
|
||||
if (fastMode)
|
||||
return *(int *)(data+pos-4);
|
||||
else
|
||||
return file.ReadInt();
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ChunkFile::WriteInt(int i)
|
||||
{
|
||||
/*
|
||||
*(int *)(data+pos) = i;
|
||||
pos+=4;
|
||||
*/
|
||||
file.WriteInt(i);
|
||||
pos+=4;
|
||||
}
|
||||
|
||||
//let's get into the business
|
||||
bool ChunkFile::Descend(unsigned int id)
|
||||
{
|
||||
id=flipID(id);
|
||||
if (read)
|
||||
{
|
||||
bool found = false;
|
||||
int startPos = pos;
|
||||
ChunkInfo temp = stack[numLevels];
|
||||
|
||||
//save information to restore after the next Ascend
|
||||
stack[numLevels].parentStartLocation = pos;
|
||||
stack[numLevels].parentEOF = eof;
|
||||
|
||||
|
||||
int firstID = 0;
|
||||
//let's search through children..
|
||||
while(pos<eof)
|
||||
{
|
||||
stack[numLevels].ID = ReadInt();
|
||||
if (firstID == 0) firstID=stack[numLevels].ID|1;
|
||||
stack[numLevels].length = ReadInt();
|
||||
stack[numLevels].startLocation = pos;
|
||||
|
||||
if (stack[numLevels].ID == id)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
SeekTo(pos + stack[numLevels].length); //try next block
|
||||
}
|
||||
}
|
||||
|
||||
//if we found nothing, return false so the caller can skip this
|
||||
if (!found)
|
||||
{
|
||||
/*
|
||||
pos = startPos;
|
||||
char temp1[5]; TCHAR temp2[5];
|
||||
temp1[4]=0; temp2[4]=0;
|
||||
*(int *)temp1 =id;
|
||||
TCHAR tempx[256];
|
||||
|
||||
for (int i=0; i<4; i++)
|
||||
temp2[i]=temp1[i];
|
||||
|
||||
_stprintf(tempx,TEXT("Couldn't find chunk \"%s\" in file"),temp2);
|
||||
|
||||
MessageBox(theApp->getHWND(),tempx,0,0);
|
||||
*/
|
||||
stack[numLevels]=temp;
|
||||
SeekTo(stack[numLevels].parentStartLocation);
|
||||
return false;
|
||||
}
|
||||
|
||||
//descend into it
|
||||
//pos was set inside the loop above
|
||||
eof = stack[numLevels].startLocation + stack[numLevels].length;
|
||||
numLevels++;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//write a chunk id, and prepare for filling in length later
|
||||
WriteInt(id);
|
||||
WriteInt(0); //will be filled in by Ascend
|
||||
stack[numLevels].startLocation=pos;
|
||||
numLevels++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void ChunkFile::SeekTo(int _pos)
|
||||
{
|
||||
if (!fastMode)
|
||||
file.SeekBeg(_pos);
|
||||
pos=_pos;
|
||||
}
|
||||
|
||||
//let's Ascend out
|
||||
void ChunkFile::Ascend()
|
||||
{
|
||||
if (read)
|
||||
{
|
||||
//Ascend, and restore information
|
||||
numLevels--;
|
||||
SeekTo(stack[numLevels].parentStartLocation);
|
||||
eof = stack[numLevels].parentEOF;
|
||||
}
|
||||
else
|
||||
{
|
||||
numLevels--;
|
||||
//now fill in the written length automatically
|
||||
int posNow = pos;
|
||||
SeekTo(stack[numLevels].startLocation - 4);
|
||||
WriteInt(posNow-stack[numLevels].startLocation);
|
||||
SeekTo(posNow);
|
||||
}
|
||||
}
|
||||
|
||||
//read a block
|
||||
void ChunkFile::ReadData(void *what, int count)
|
||||
{
|
||||
|
||||
if (fastMode)
|
||||
memcpy(what,data+pos,count);
|
||||
else
|
||||
file.Read(what,count);
|
||||
|
||||
pos+=count;
|
||||
char temp[4]; //discarded
|
||||
count &= 3;
|
||||
if (count)
|
||||
{
|
||||
count=4-count;
|
||||
if (!fastMode)
|
||||
file.Read(temp,count);
|
||||
pos+=count;
|
||||
}
|
||||
}
|
||||
|
||||
//write a block
|
||||
void ChunkFile::WriteData(void *what, int count)
|
||||
{
|
||||
/*
|
||||
memcpy(data+pos,what,count);
|
||||
pos += count;
|
||||
*/
|
||||
file.Write(what,count);
|
||||
pos+=count;
|
||||
char temp[5]={0,0,0,0,0};
|
||||
count &= 3;
|
||||
if (count)
|
||||
{
|
||||
count=4-count;
|
||||
file.Write(temp,count);
|
||||
pos+=count;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void ChunkFile::WriteString(String str)
|
||||
{
|
||||
wchar_t *text;
|
||||
int len=str.length();
|
||||
#ifdef UNICODE
|
||||
text = str.getPointer();
|
||||
#else
|
||||
text=new wchar_t[len+1];
|
||||
str.toUnicode(text);
|
||||
#endif
|
||||
WriteInt(len);
|
||||
WriteData((char *)text,len*sizeof(wchar_t));
|
||||
#ifndef UNICODE
|
||||
delete [] text;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
String ChunkFile::readString()
|
||||
{
|
||||
int len=ReadInt();
|
||||
wchar_t *text = new wchar_t[len+1];
|
||||
ReadData((char *)text,len*sizeof(wchar_t));
|
||||
text[len]=0;
|
||||
#ifdef UNICODE
|
||||
String s(text);
|
||||
delete [] text;
|
||||
return s;
|
||||
#else
|
||||
String temp;
|
||||
temp.fromUnicode(text);
|
||||
delete [] text;
|
||||
return temp;
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
|
||||
int ChunkFile::GetCurrentChunkSize()
|
||||
{
|
||||
if (numLevels)
|
||||
return stack[numLevels-1].length;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
//TO REMEMBER WHEN USING:
|
||||
|
||||
//EITHER a chunk contains ONLY data
|
||||
//OR it contains ONLY other chunks
|
||||
//otherwise the scheme breaks...
|
||||
#include "File.h"
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
inline unsigned int flipID(unsigned int id)
|
||||
{
|
||||
return ((id>>24)&0xFF) | ((id>>8)&0xFF00) | ((id<<8)&0xFF0000) | ((id<<24)&0xFF000000);
|
||||
}
|
||||
|
||||
class ChunkFile
|
||||
{
|
||||
File file;
|
||||
struct ChunkInfo
|
||||
{
|
||||
int startLocation;
|
||||
int parentStartLocation;
|
||||
int parentEOF;
|
||||
unsigned int ID;
|
||||
int length;
|
||||
};
|
||||
ChunkInfo stack[8];
|
||||
int numLevels;
|
||||
|
||||
char *data;
|
||||
int pos,eof;
|
||||
bool fastMode;
|
||||
bool read;
|
||||
bool didFail;
|
||||
|
||||
void SeekTo(int _pos);
|
||||
int GetPos() {return pos;}
|
||||
public:
|
||||
ChunkFile(const TCHAR *filename, bool _read);
|
||||
~ChunkFile();
|
||||
|
||||
bool Descend(unsigned int id);
|
||||
void Ascend();
|
||||
|
||||
int ReadInt();
|
||||
void ReadInt(int &i) {i = ReadInt();}
|
||||
void ReadData(void *data, int count);
|
||||
// String ReadString();
|
||||
|
||||
void WriteInt(int i);
|
||||
//void WriteString(String str);
|
||||
void WriteData(void *data, int count);
|
||||
|
||||
int GetCurrentChunkSize();
|
||||
bool Failed() {return didFail;}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#include <windows.h>
|
||||
#include <vector>
|
||||
#include "DialogManager.h"
|
||||
|
||||
typedef std::vector <HWND> WindowList;
|
||||
WindowList dialogs;
|
||||
|
||||
void DialogManager::AddDlg(HWND hDialog)
|
||||
{
|
||||
dialogs.push_back(hDialog);
|
||||
}
|
||||
|
||||
bool DialogManager::IsDialogMessage(LPMSG message)
|
||||
{
|
||||
WindowList::iterator iter;
|
||||
for (iter=dialogs.begin(); iter!=dialogs.end(); iter++)
|
||||
{
|
||||
if (::IsDialogMessage(*iter,message))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DialogManager::EnableAll(BOOL enable)
|
||||
{
|
||||
WindowList::iterator iter;
|
||||
for (iter=dialogs.begin(); iter!=dialogs.end(); iter++)
|
||||
EnableWindow(*iter,enable);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
class DialogManager
|
||||
{
|
||||
public:
|
||||
static void AddDlg(HWND hDialog);
|
||||
static bool IsDialogMessage(LPMSG message);
|
||||
static void EnableAll(BOOL enable);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "File.h"
|
||||
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
|
||||
File::File()
|
||||
{
|
||||
fileHandle = INVALID_HANDLE_VALUE;
|
||||
isOpen=false;
|
||||
}
|
||||
|
||||
File::~File()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool File::Open(const TCHAR *filename, eFileMode _mode)
|
||||
{
|
||||
mode = _mode;
|
||||
//it's time to open the file
|
||||
fileHandle = CreateFile(filename,
|
||||
mode==FILE_READ ? GENERIC_READ : GENERIC_WRITE, //open mode
|
||||
mode == FILE_READ ? FILE_SHARE_READ : NULL, //sharemode
|
||||
NULL, //security
|
||||
mode==FILE_READ ? OPEN_EXISTING : CREATE_ALWAYS, //create mode
|
||||
FILE_ATTRIBUTE_NORMAL, //atrributes
|
||||
NULL); //template
|
||||
|
||||
if (fileHandle == INVALID_HANDLE_VALUE)
|
||||
isOpen=false;
|
||||
else
|
||||
isOpen=true;
|
||||
|
||||
return isOpen;
|
||||
}
|
||||
|
||||
|
||||
void File::Close()
|
||||
{
|
||||
if (isOpen)
|
||||
{
|
||||
//close the file and reset variables
|
||||
CloseHandle(fileHandle);
|
||||
fileHandle=INVALID_HANDLE_VALUE;
|
||||
isOpen=false;
|
||||
}
|
||||
}
|
||||
|
||||
int File::GetSize()
|
||||
{
|
||||
if (!isOpen) //of course
|
||||
return 0;
|
||||
else
|
||||
return GetFileSize(fileHandle,0);
|
||||
}
|
||||
|
||||
int File::Write(void *data, int size) //let's do some writing
|
||||
{
|
||||
if (isOpen)
|
||||
{
|
||||
DWORD written;
|
||||
WriteFile(fileHandle, data, size, &written,0);
|
||||
return written; //we return the number of bytes that actually got written
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int File::Read(void *data, int size)
|
||||
{
|
||||
if (isOpen)
|
||||
{
|
||||
DWORD wasRead;
|
||||
ReadFile(fileHandle, data, size, &wasRead,0);
|
||||
return wasRead; //we return the number of bytes that actually was read
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int File::WR(void *data, int size)
|
||||
{
|
||||
if (mode==FILE_READ)
|
||||
return Read(data,size);
|
||||
else
|
||||
return Write(data,size);
|
||||
}
|
||||
bool File::MagicCookie(int cookie)
|
||||
{
|
||||
if (mode==FILE_READ)
|
||||
{
|
||||
if (ReadInt()!=cookie)
|
||||
{
|
||||
char mojs[5],temp[256];
|
||||
mojs[4]=0;
|
||||
*(int*)mojs=cookie;
|
||||
sprintf(temp,"W32Util::File: Magic Cookie %s is bad!",mojs);
|
||||
MessageBox(0,temp,"Error reading file",MB_ICONERROR);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else if (mode==FILE_WRITE)
|
||||
{
|
||||
WriteInt(cookie);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int File::ReadInt()
|
||||
{
|
||||
int temp;
|
||||
if (Read(&temp, sizeof(int)))
|
||||
return temp;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void File::WriteInt(int i)
|
||||
{
|
||||
Write(&i,sizeof(int));
|
||||
}
|
||||
|
||||
char File::ReadChar()
|
||||
{
|
||||
char temp;
|
||||
if (Read(&temp, sizeof(char)))
|
||||
return temp;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void File::WriteChar(char i)
|
||||
{
|
||||
Write(&i,sizeof(char));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#ifndef __LAMEFILE_H__
|
||||
#define __LAMEFILE_H__
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
#include <windows.h>
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
|
||||
enum eFileMode
|
||||
{
|
||||
FILE_READ=5,
|
||||
FILE_WRITE=6,
|
||||
FILE_ERROR=0xff
|
||||
};
|
||||
|
||||
class File
|
||||
{
|
||||
HANDLE fileHandle;
|
||||
eFileMode mode;
|
||||
bool isOpen;
|
||||
public:
|
||||
File();
|
||||
virtual ~File();
|
||||
|
||||
bool Open(const TCHAR *filename, eFileMode mode);
|
||||
void Adopt(HANDLE h) { fileHandle = h;}
|
||||
void Close();
|
||||
|
||||
void WriteInt(int i);
|
||||
void WriteChar(char i);
|
||||
int Write(void *data, int size);
|
||||
|
||||
|
||||
int ReadInt();
|
||||
char ReadChar();
|
||||
int Read(void *data, int size);
|
||||
|
||||
int WR(void *data, int size); //write or read depending on open mode
|
||||
bool MagicCookie(int cookie);
|
||||
|
||||
int GetSize();
|
||||
eFileMode GetMode() {return mode;}
|
||||
void SeekBeg(int pos)
|
||||
{
|
||||
if (isOpen) SetFilePointer(fileHandle,pos,0,FILE_BEGIN);
|
||||
}
|
||||
void SeekEnd(int pos)
|
||||
{
|
||||
if (isOpen) SetFilePointer(fileHandle,pos,0,FILE_END);
|
||||
}
|
||||
void SeekCurrent(int pos)
|
||||
{
|
||||
if (isOpen) SetFilePointer(fileHandle,pos,0,FILE_CURRENT);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif //__LAMEFILE_H__
|
||||
@@ -0,0 +1,102 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "Misc.h"
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
//shamelessly taken from http://www.catch22.org.uk/tuts/tips.asp
|
||||
void CenterWindow(HWND hwnd)
|
||||
{
|
||||
HWND hwndParent;
|
||||
RECT rect, rectP;
|
||||
int width, height;
|
||||
int screenwidth, screenheight;
|
||||
int x, y;
|
||||
|
||||
//make the window relative to its parent
|
||||
hwndParent = GetParent(hwnd);
|
||||
if (!hwndParent)
|
||||
return;
|
||||
|
||||
GetWindowRect(hwnd, &rect);
|
||||
GetWindowRect(hwndParent, &rectP);
|
||||
|
||||
width = rect.right - rect.left;
|
||||
height = rect.bottom - rect.top;
|
||||
|
||||
x = ((rectP.right-rectP.left) - width) / 2 + rectP.left;
|
||||
y = ((rectP.bottom-rectP.top) - height) / 2 + rectP.top;
|
||||
|
||||
screenwidth = GetSystemMetrics(SM_CXSCREEN);
|
||||
screenheight = GetSystemMetrics(SM_CYSCREEN);
|
||||
|
||||
//make sure that the dialog box never moves outside of
|
||||
//the screen
|
||||
if(x < 0) x = 0;
|
||||
if(y < 0) y = 0;
|
||||
if(x + width > screenwidth) x = screenwidth - width;
|
||||
if(y + height > screenheight) y = screenheight - height;
|
||||
|
||||
MoveWindow(hwnd, x, y, width, height, FALSE);
|
||||
}
|
||||
|
||||
HBITMAP CreateBitmapFromARGB(HWND someHwnd, DWORD *image, int w, int h)
|
||||
{
|
||||
BITMAPINFO *bitmap_header;
|
||||
static char bitmapbuffer[sizeof(BITMAPINFO)+16];
|
||||
memset(bitmapbuffer,0,sizeof(BITMAPINFO)+16);
|
||||
bitmap_header=(BITMAPINFO *)bitmapbuffer;
|
||||
bitmap_header->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bitmap_header->bmiHeader.biPlanes = 1;
|
||||
bitmap_header->bmiHeader.biBitCount = 32;
|
||||
bitmap_header->bmiHeader.biCompression = BI_RGB;
|
||||
bitmap_header->bmiHeader.biWidth = w;
|
||||
bitmap_header->bmiHeader.biHeight = -h;
|
||||
|
||||
((unsigned long *)bitmap_header->bmiColors)[0] = 0x00FF0000;
|
||||
((unsigned long *)bitmap_header->bmiColors)[1] = 0x0000FF00;
|
||||
((unsigned long *)bitmap_header->bmiColors)[2] = 0x000000FF;
|
||||
|
||||
HDC dc = GetDC(someHwnd);
|
||||
HBITMAP bitmap = CreateDIBitmap(dc,&bitmap_header->bmiHeader,CBM_INIT,image,bitmap_header,DIB_RGB_COLORS);
|
||||
ReleaseDC(someHwnd,dc);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
void NiceSizeFormat(size_t size, char *out)
|
||||
{
|
||||
char *sizes[] = {"b","KB","MB","GB","TB","PB","EB"};
|
||||
int s = 0;
|
||||
int frac = 0;
|
||||
while (size>1024)
|
||||
{
|
||||
s++;
|
||||
frac = (int)size & 1023;
|
||||
size /= 1024;
|
||||
}
|
||||
float f = (float)size + ((float)frac / 1024.0f);
|
||||
sprintf(out,"%3.1f %s",f,sizes[s]);
|
||||
}
|
||||
BOOL CopyTextToClipboard(HWND hwnd, TCHAR *text)
|
||||
{
|
||||
OpenClipboard(hwnd);
|
||||
EmptyClipboard();
|
||||
HANDLE hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (strlen(text) + 1) * sizeof(TCHAR));
|
||||
if (hglbCopy == NULL)
|
||||
{
|
||||
CloseClipboard();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Lock the handle and copy the text to the buffer.
|
||||
|
||||
TCHAR *lptstrCopy = (TCHAR *)GlobalLock(hglbCopy);
|
||||
strcpy(lptstrCopy, text);
|
||||
lptstrCopy[strlen(text)] = (TCHAR) 0; // null character
|
||||
GlobalUnlock(hglbCopy);
|
||||
SetClipboardData(CF_TEXT,hglbCopy);
|
||||
CloseClipboard();
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
void CenterWindow(HWND hwnd);
|
||||
HBITMAP CreateBitmapFromARGB(HWND someHwnd, DWORD *image, int w, int h);
|
||||
void NiceSizeFormat(size_t size, char *out);
|
||||
BOOL CopyTextToClipboard(HWND hwnd, TCHAR *text);
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
#include "Misc.h"
|
||||
#include "PropertySheet.h"
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
bool centered;
|
||||
|
||||
PropSheet::PropSheet()
|
||||
{
|
||||
watermark = 0;
|
||||
header = 0;
|
||||
icon = 0;
|
||||
}
|
||||
|
||||
int CALLBACK PropSheet::Callback(HWND hwndDlg, UINT uMsg, LPARAM lParam)
|
||||
{
|
||||
switch (uMsg) {
|
||||
case PSCB_PRECREATE:
|
||||
{
|
||||
if (uMsg == PSCB_PRECREATE)
|
||||
{
|
||||
/*
|
||||
if (lParam)
|
||||
{
|
||||
DLGTEMPLATE *pDlgTemplate;
|
||||
DLGTEMPLATEEX *pDlgTemplateEx;
|
||||
|
||||
pDlgTemplateEx = (DLGTEMPLATEEX *)lParam;
|
||||
if (pDlgTemplateEx->signature == 0xFFFF)
|
||||
{
|
||||
// pDlgTemplateEx points to an extended
|
||||
// dialog template structure.
|
||||
|
||||
//pDlgTemplate->style |= DS_SETFONT;
|
||||
u8 *tmp1 = (u8*)&pDlgTemplateEx + sizeof(DLGTEMPLATEEX);
|
||||
u16 *tmp = (u16*)tmp1;
|
||||
tmp++; //skip menu
|
||||
tmp++; //skip dlg class
|
||||
//Crash();
|
||||
//Here we should bash in Segoe UI
|
||||
//It turns out to be way complicated though
|
||||
//Not worth it
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is a standard dialog template
|
||||
// structure.
|
||||
pDlgTemplate = (DLGTEMPLATE *)lParam;
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case PSCB_INITIALIZED:
|
||||
{
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PropSheet::Show(HINSTANCE hInstance, HWND hParent, std::string title, int startpage, bool floating, bool wizard)
|
||||
{
|
||||
HPROPSHEETPAGE *pages = new HPROPSHEETPAGE[list.size()];
|
||||
PROPSHEETPAGE page;
|
||||
//common settings
|
||||
memset((void*)&page,0,sizeof(PROPSHEETPAGE));
|
||||
page.dwSize = sizeof(PROPSHEETPAGE);
|
||||
page.hInstance = hInstance;
|
||||
|
||||
int i=0;
|
||||
for (DlgList::iterator iter = list.begin(); iter != list.end(); iter++, i++)
|
||||
{
|
||||
if (wizard)
|
||||
{
|
||||
if (i == 0 || i == list.size()-1)
|
||||
page.dwFlags = PSP_HIDEHEADER;
|
||||
else
|
||||
page.dwFlags = PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
page.dwFlags = PSP_USETITLE;
|
||||
}
|
||||
page.pszTemplate = iter->resource;
|
||||
page.pfnDlgProc = Tab::TabDlgProc;
|
||||
page.pszTitle = iter->title;
|
||||
page.pszHeaderTitle = wizard?iter->title:0;
|
||||
page.pszHeaderSubTitle = wizard?iter->hdrSubTitle:0;
|
||||
page.lParam = (LPARAM)iter->tab;
|
||||
pages[i] = CreatePropertySheetPage(&page);
|
||||
}
|
||||
|
||||
PROPSHEETHEADER sheet;
|
||||
memset(&sheet,0,sizeof(sheet));
|
||||
sheet.dwSize = sizeof(PROPSHEETHEADER);
|
||||
sheet.hInstance = hInstance;
|
||||
sheet.hwndParent = hParent;
|
||||
sheet.pszbmWatermark = watermark;
|
||||
sheet.pszbmHeader = header;
|
||||
|
||||
if (icon)
|
||||
sheet.hIcon = icon;
|
||||
|
||||
if (wizard)
|
||||
sheet.dwFlags = PSH_USECALLBACK | PSH_WIZARD97 | (watermark?PSH_WATERMARK:0) | (header?PSH_HEADER:0);
|
||||
else
|
||||
sheet.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE;
|
||||
|
||||
sheet.dwFlags |= PSH_NOCONTEXTHELP;
|
||||
|
||||
if (floating)
|
||||
sheet.dwFlags |= PSH_MODELESS;
|
||||
//else
|
||||
// sheet.dwFlags |= PSH_NOAPPLYNOW;
|
||||
|
||||
if (icon)
|
||||
sheet.dwFlags |= PSH_USEHICON;
|
||||
|
||||
sheet.pszCaption = title.c_str();
|
||||
sheet.nPages = (UINT)list.size();
|
||||
sheet.phpage = pages;
|
||||
sheet.nStartPage = startpage;
|
||||
sheet.pfnCallback = (PFNPROPSHEETCALLBACK)Callback;
|
||||
|
||||
NONCLIENTMETRICS ncm = {0};
|
||||
ncm.cbSize = sizeof(ncm);
|
||||
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
|
||||
hDialogFont = CreateFontIndirect(&ncm.lfMessageFont);
|
||||
|
||||
if (wizard)
|
||||
{
|
||||
|
||||
//Create the intro/end title font
|
||||
LOGFONT TitleLogFont = ncm.lfMessageFont;
|
||||
TitleLogFont.lfWeight = FW_BOLD;
|
||||
lstrcpy(TitleLogFont.lfFaceName, TEXT("Verdana Bold"));
|
||||
//StringCchCopy(TitleLogFont.lfFaceName, 32, TEXT("Verdana Bold"));
|
||||
|
||||
HDC hdc = GetDC(NULL); //gets the screen DC
|
||||
INT FontSize = 12;
|
||||
TitleLogFont.lfHeight = 0 - GetDeviceCaps(hdc, LOGPIXELSY) * FontSize / 72;
|
||||
hTitleFont = CreateFontIndirect(&TitleLogFont);
|
||||
ReleaseDC(NULL, hdc);
|
||||
}
|
||||
else
|
||||
hTitleFont = 0;
|
||||
|
||||
centered=false;
|
||||
PropertySheet(&sheet);
|
||||
if (!floating)
|
||||
{
|
||||
for (DlgList::iterator iter = list.begin(); iter != list.end(); iter++)
|
||||
{
|
||||
delete iter->tab;
|
||||
}
|
||||
DeleteObject(hTitleFont);
|
||||
}
|
||||
DeleteObject(hDialogFont);
|
||||
delete [] pages;
|
||||
}
|
||||
void PropSheet::Add(Tab *tab, LPCTSTR resource, LPCTSTR title, LPCTSTR subtitle)
|
||||
{
|
||||
tab->sheet = this;
|
||||
list.push_back(Page(tab,resource,title,subtitle));
|
||||
}
|
||||
|
||||
|
||||
void WizExteriorPage::Init(HWND hDlg)
|
||||
{
|
||||
HWND hwndControl = GetDlgItem(hDlg, captionID);
|
||||
//SetWindowFont(hwndControl, sheet->GetTitleFont(), TRUE);
|
||||
SendMessage(hwndControl,WM_SETFONT,(WPARAM)sheet->GetTitleFont(),0);
|
||||
}
|
||||
|
||||
INT_PTR Tab::TabDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
Tab *tab = (Tab *)GetWindowLongPtr(hDlg, GWLP_USERDATA);
|
||||
switch(message)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
if (!centered) //HACK
|
||||
{
|
||||
CenterWindow(GetParent(hDlg));
|
||||
centered=true;
|
||||
}
|
||||
LPARAM l = ((LPPROPSHEETPAGE)lParam)->lParam;
|
||||
tab = (Tab *)l;
|
||||
SetWindowLongPtr(hDlg, GWLP_USERDATA, (DWORD_PTR)l);
|
||||
tab->Init(hDlg);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
tab->Command(hDlg,wParam);
|
||||
break;
|
||||
case WM_NOTIFY:
|
||||
{
|
||||
LPPSHNOTIFY lppsn = (LPPSHNOTIFY) lParam;
|
||||
HWND sheet = lppsn->hdr.hwndFrom;
|
||||
switch(lppsn->hdr.code) {
|
||||
case PSN_APPLY:
|
||||
tab->Apply(hDlg);
|
||||
break;
|
||||
case PSN_SETACTIVE:
|
||||
PropSheet_SetWizButtons(GetParent(hDlg),
|
||||
(tab->HasPrev()?PSWIZB_BACK:0) |
|
||||
(tab->HasNext()?PSWIZB_NEXT:0) |
|
||||
(tab->HasFinish()?PSWIZB_FINISH:0));
|
||||
break;
|
||||
case PSN_WIZNEXT:
|
||||
tab->Apply(hDlg); //maybe not always good
|
||||
break;
|
||||
case PSN_WIZBACK:
|
||||
case PSN_RESET: //cancel
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
class PropSheet;
|
||||
|
||||
class Tab
|
||||
{
|
||||
public:
|
||||
PropSheet *sheet; //back pointer ..
|
||||
virtual void Init(HWND hDlg) {}
|
||||
virtual void Command(HWND hDlg, WPARAM wParam) {}
|
||||
virtual void Apply(HWND hDlg) {}
|
||||
virtual bool HasPrev() {return true;}
|
||||
virtual bool HasFinish() {return false;}
|
||||
virtual bool HasNext() {return true;}
|
||||
static INT_PTR __stdcall TabDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
};
|
||||
|
||||
|
||||
class WizExteriorPage : public Tab
|
||||
{
|
||||
INT captionID;
|
||||
public:
|
||||
WizExteriorPage(INT caption) {captionID = caption;}
|
||||
void Init(HWND hDlg);
|
||||
};
|
||||
|
||||
|
||||
class WizFirstPage : public WizExteriorPage
|
||||
{
|
||||
public:
|
||||
WizFirstPage(INT caption) : WizExteriorPage(caption) {}
|
||||
bool HasPrev() {return false;}
|
||||
};
|
||||
|
||||
|
||||
class WizLastPage : public WizExteriorPage
|
||||
{
|
||||
public:
|
||||
WizLastPage(INT caption) : WizExteriorPage(caption) {}
|
||||
bool HasNext() {return false;}
|
||||
bool HasFinish() {return true;}
|
||||
};
|
||||
|
||||
|
||||
class WizInteriorPage : public Tab
|
||||
{
|
||||
public:
|
||||
};
|
||||
|
||||
class PropSheet
|
||||
{
|
||||
LPCTSTR watermark;
|
||||
LPCTSTR header;
|
||||
HFONT hTitleFont;
|
||||
HFONT hDialogFont;
|
||||
HICON icon;
|
||||
struct Page
|
||||
{
|
||||
Page(Tab *_tab, LPCTSTR _resource, LPCTSTR _title, LPCTSTR _subtitle = 0)
|
||||
: tab(_tab), resource(_resource), title(_title), hdrSubTitle(_subtitle) {}
|
||||
Tab *tab;
|
||||
LPCTSTR resource;
|
||||
LPCTSTR title;
|
||||
LPCTSTR hdrSubTitle;
|
||||
};
|
||||
public:
|
||||
PropSheet();
|
||||
typedef std::vector<Page> DlgList;
|
||||
DlgList list;
|
||||
void SetWaterMark(LPCTSTR _watermark) {watermark=_watermark;}
|
||||
void SetHeader(LPCTSTR _header) {header=_header;}
|
||||
void SetIcon(HICON _icon) {icon = _icon;}
|
||||
void Add(Tab *tab, LPCTSTR resource, LPCTSTR title, LPCTSTR subtitle = 0);
|
||||
void Show(HINSTANCE hInstance, HWND hParent, std::string title, int startpage=0, bool floating = false, bool wizard = false);
|
||||
HFONT GetTitleFont() {return hTitleFont;}
|
||||
HFONT GetFont() {return hDialogFont;}
|
||||
static int CALLBACK Callback(HWND hwndDlg, UINT uMsg, LPARAM lParam);
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
#include "shlobj.h"
|
||||
|
||||
#include <xstring>
|
||||
#include <string>
|
||||
#include "ShellUtil.h"
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
std::string BrowseForFolder(HWND parent, char *title)
|
||||
{
|
||||
BROWSEINFO info;
|
||||
memset(&info,0,sizeof(info));
|
||||
info.hwndOwner = parent;
|
||||
info.lpszTitle = title;
|
||||
info.ulFlags = BIF_EDITBOX | BIF_RETURNONLYFSDIRS;
|
||||
|
||||
//info.pszDisplayName
|
||||
LPCITEMIDLIST idList = SHBrowseForFolder(&info);
|
||||
|
||||
char temp[MAX_PATH];
|
||||
SHGetPathFromIDList(idList, temp);
|
||||
if (strlen(temp))
|
||||
{
|
||||
return temp;
|
||||
}
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// function WinBrowseForFileName
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
bool BrowseForFileName (bool _bLoad, HWND _hParent, const char *_pTitle,
|
||||
const char *_pInitialFolder,const char *_pFilter,const char *_pExtension,
|
||||
std::string& _strFileName)
|
||||
{
|
||||
char szFile [MAX_PATH+1];
|
||||
char szFileTitle [MAX_PATH+1];
|
||||
|
||||
strcpy (szFile,"");
|
||||
strcpy (szFileTitle,"");
|
||||
|
||||
OPENFILENAME ofn;
|
||||
|
||||
ZeroMemory (&ofn,sizeof (ofn));
|
||||
|
||||
ofn.lStructSize = sizeof (OPENFILENAME);
|
||||
ofn.lpstrInitialDir = _pInitialFolder;
|
||||
ofn.lpstrFilter = _pFilter;
|
||||
ofn.nMaxFile = sizeof (szFile);
|
||||
ofn.lpstrFile = szFile;
|
||||
ofn.lpstrFileTitle = szFileTitle;
|
||||
ofn.nMaxFileTitle = sizeof (szFileTitle);
|
||||
ofn.lpstrDefExt = _pExtension;
|
||||
ofn.hwndOwner = _hParent;
|
||||
ofn.Flags = OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_HIDEREADONLY;
|
||||
|
||||
if (_strFileName.size () != 0)
|
||||
ofn.lpstrFile = (char *)_strFileName.c_str();
|
||||
|
||||
if (((_bLoad)?GetOpenFileName (&ofn):GetSaveFileName (&ofn)))
|
||||
{
|
||||
_strFileName = ofn.lpstrFile;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> BrowseForFileNameMultiSelect(bool _bLoad, HWND _hParent, const char *_pTitle,
|
||||
const char *_pInitialFolder,const char *_pFilter,const char *_pExtension)
|
||||
{
|
||||
char szFile [MAX_PATH+1+2048*2];
|
||||
char szFileTitle [MAX_PATH+1];
|
||||
|
||||
strcpy (szFile,"");
|
||||
strcpy (szFileTitle,"");
|
||||
|
||||
OPENFILENAME ofn;
|
||||
|
||||
ZeroMemory (&ofn,sizeof (ofn));
|
||||
|
||||
ofn.lStructSize = sizeof (OPENFILENAME);
|
||||
ofn.lpstrInitialDir = _pInitialFolder;
|
||||
ofn.lpstrFilter = _pFilter;
|
||||
ofn.nMaxFile = sizeof (szFile);
|
||||
ofn.lpstrFile = szFile;
|
||||
ofn.lpstrFileTitle = szFileTitle;
|
||||
ofn.nMaxFileTitle = sizeof (szFileTitle);
|
||||
ofn.lpstrDefExt = _pExtension;
|
||||
ofn.hwndOwner = _hParent;
|
||||
ofn.Flags = OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT ;
|
||||
|
||||
std::vector<std::string> files;
|
||||
|
||||
if (((_bLoad)?GetOpenFileName (&ofn):GetSaveFileName (&ofn)))
|
||||
{
|
||||
std::string directory = ofn.lpstrFile;
|
||||
char *temp = ofn.lpstrFile;
|
||||
char *oldtemp = temp;
|
||||
temp+=strlen(temp)+1;
|
||||
if (*temp==0)
|
||||
{
|
||||
//we only got one file
|
||||
files.push_back(std::string(oldtemp));
|
||||
}
|
||||
else
|
||||
{
|
||||
while (*temp)
|
||||
{
|
||||
files.push_back(directory+"\\"+std::string(temp));
|
||||
temp+=strlen(temp)+1;
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
else
|
||||
return std::vector<std::string>(); // empty vector;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <xstring>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
std::string BrowseForFolder(HWND parent, char *title);
|
||||
bool BrowseForFileName (bool _bLoad, HWND _hParent, const char *_pTitle,
|
||||
const char *_pInitialFolder,const char *_pFilter,const char *_pExtension,
|
||||
std::string& _strFileName);
|
||||
std::vector<std::string> BrowseForFileNameMultiSelect(bool _bLoad, HWND _hParent, const char *_pTitle,
|
||||
const char *_pInitialFolder,const char *_pFilter,const char *_pExtension);
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
#include <commctrl.h>
|
||||
|
||||
#include "TabControl.h"
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
// __________________________________________________________________________________________________
|
||||
// constructor
|
||||
//
|
||||
TabControl::TabControl(HINSTANCE _hInstance, HWND _hTabCtrl,DLGPROC _lpDialogFunc) :
|
||||
m_hInstance(_hInstance),
|
||||
m_hTabCtrl(_hTabCtrl),
|
||||
m_numDialogs(0)
|
||||
{
|
||||
for (int i=0; i<MAX_WIN_DIALOGS; i++)
|
||||
m_WinDialogs[i] = NULL;
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// destructor
|
||||
//
|
||||
TabControl::~TabControl(void)
|
||||
{}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// AddItem
|
||||
//
|
||||
HWND TabControl::AddItem (char* _szText,int _iResource,DLGPROC _lpDialogFunc)
|
||||
{
|
||||
TCITEM tcItem;
|
||||
|
||||
ZeroMemory (&tcItem,sizeof (tcItem));
|
||||
|
||||
tcItem.mask = TCIF_TEXT | TCIF_IMAGE;
|
||||
tcItem.dwState = 0;
|
||||
tcItem.pszText = _szText;
|
||||
tcItem.cchTextMax = sizeof (_szText);
|
||||
tcItem.iImage = -1;
|
||||
|
||||
int nResult = TabCtrl_InsertItem (m_hTabCtrl,TabCtrl_GetItemCount (m_hTabCtrl),&tcItem);
|
||||
|
||||
|
||||
HWND hDialog = CreateDialog(m_hInstance,(LPCSTR)_iResource,m_hTabCtrl,_lpDialogFunc);
|
||||
RECT rectInnerWindow = {0,0,0,0};
|
||||
|
||||
GetWindowRect (m_hTabCtrl,&rectInnerWindow);
|
||||
|
||||
TabCtrl_AdjustRect (m_hTabCtrl,FALSE,&rectInnerWindow);
|
||||
|
||||
POINT pntPosition = {rectInnerWindow.left,rectInnerWindow.top};
|
||||
ScreenToClient(m_hTabCtrl, &pntPosition);
|
||||
|
||||
SetWindowPos(hDialog, 0,
|
||||
pntPosition.x, pntPosition.y,
|
||||
rectInnerWindow.right - rectInnerWindow.left,rectInnerWindow.bottom - rectInnerWindow.top,0);
|
||||
ShowWindow(hDialog,SW_NORMAL);
|
||||
|
||||
m_WinDialogs[m_numDialogs] = hDialog;
|
||||
m_numDialogs++;
|
||||
|
||||
SelectDialog (0);
|
||||
|
||||
return hDialog;
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// SelectDialog
|
||||
//
|
||||
void TabControl::SelectDialog (int _nDialogId)
|
||||
{
|
||||
for (int i = 0 ; i < m_numDialogs ; i ++)
|
||||
if (m_WinDialogs[i] != NULL)
|
||||
ShowWindow(m_WinDialogs[i],i == _nDialogId ? SW_NORMAL : SW_HIDE);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// MessageHandler
|
||||
//
|
||||
void TabControl::MessageHandler(UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (message == WM_NOTIFY)
|
||||
{
|
||||
NMHDR* pNotifyMessage = NULL;
|
||||
pNotifyMessage = (LPNMHDR)lParam;
|
||||
if (pNotifyMessage->hwndFrom == m_hTabCtrl)
|
||||
{
|
||||
int iPage = TabCtrl_GetCurSel (m_hTabCtrl);
|
||||
SelectDialog (iPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
#define MAX_WIN_DIALOGS 32
|
||||
|
||||
|
||||
class TabControl
|
||||
{
|
||||
private:
|
||||
|
||||
HINSTANCE m_hInstance;
|
||||
HWND m_hWndParent;
|
||||
HWND m_hTabCtrl;
|
||||
|
||||
HWND m_WinDialogs[MAX_WIN_DIALOGS];
|
||||
int m_numDialogs;
|
||||
|
||||
public:
|
||||
|
||||
TabControl(HINSTANCE _hInstance, HWND _hTabCtrl,DLGPROC _lpDialogFunc);
|
||||
|
||||
~TabControl(void);
|
||||
|
||||
//
|
||||
// --- tools ---
|
||||
//
|
||||
|
||||
HWND AddItem (char* _szText,int _iResource,DLGPROC _lpDialogFunc);
|
||||
|
||||
void SelectDialog (int _nDialogId);
|
||||
|
||||
void MessageHandler(UINT message, WPARAM wParam, LPARAM lParam);
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
#include "Thread.h"
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
// __________________________________________________________________________________________________
|
||||
// Constructor
|
||||
//
|
||||
Thread::Thread ( DWORD (WINAPI * pFun) (void* arg), void* pArg)
|
||||
{
|
||||
_handle = CreateThread (
|
||||
0, // Security attributes
|
||||
0, // Stack size
|
||||
pFun,
|
||||
pArg,
|
||||
CREATE_SUSPENDED,
|
||||
&_tid);
|
||||
}
|
||||
// __________________________________________________________________________________________________
|
||||
// Destructor
|
||||
//
|
||||
Thread::~Thread (void)
|
||||
{
|
||||
if (_handle != NULL)
|
||||
{
|
||||
if (CloseHandle (_handle) == FALSE)
|
||||
{
|
||||
Terminate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Resume
|
||||
//
|
||||
void
|
||||
Thread::Resume (void)
|
||||
{
|
||||
if (_handle != NULL)
|
||||
ResumeThread (_handle);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// WaitForDeath
|
||||
//
|
||||
void
|
||||
Thread::WaitForDeath (void)
|
||||
{
|
||||
if (_handle != NULL)
|
||||
WaitForSingleObject (_handle, 100);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Terminate
|
||||
//
|
||||
void
|
||||
Thread::Terminate (void)
|
||||
{
|
||||
if (_handle != NULL)
|
||||
TerminateThread (_handle, 0);
|
||||
_handle = NULL;
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// SetPriority
|
||||
//
|
||||
void
|
||||
Thread::SetPriority (int _nPriority)
|
||||
{
|
||||
if (_handle != NULL)
|
||||
SetThreadPriority(_handle, _nPriority);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Suspend
|
||||
//
|
||||
void
|
||||
Thread::Suspend (void)
|
||||
{
|
||||
if (_handle != NULL)
|
||||
SuspendThread(_handle);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
class Thread
|
||||
{
|
||||
private:
|
||||
HANDLE _handle;
|
||||
DWORD _tid; // thread id
|
||||
|
||||
public:
|
||||
Thread ( DWORD (WINAPI * pFun) (void* arg), void* pArg);
|
||||
~Thread () ;
|
||||
|
||||
//
|
||||
// --- tools ---
|
||||
//
|
||||
|
||||
void Resume(void);
|
||||
|
||||
void Suspend(void);
|
||||
|
||||
void WaitForDeath(void);
|
||||
|
||||
void Terminate(void);
|
||||
|
||||
void SetPriority(int _nPriority);
|
||||
|
||||
bool IsActive (void);
|
||||
|
||||
HANDLE GetHandle(void) {return _handle;}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,625 @@
|
||||
// Windows Template Library - WTL version 7.0
|
||||
// Copyright (C) 1997-2002 Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is a part of the Windows Template Library.
|
||||
// The code and information is provided "as-is" without
|
||||
// warranty of any kind, either expressed or implied.
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tchar.h>
|
||||
//#include <tmschema.h>
|
||||
#include <uxtheme.h>
|
||||
#pragma comment(lib, "uxtheme.lib")
|
||||
|
||||
// Note: To create an application that also runs on older versions of Windows,
|
||||
// use delay load of uxtheme.dll and ensure that no calls to the Theme API are
|
||||
// made if theming is not supported. It is enough to check if m_hTheme is NULL.
|
||||
// Example:
|
||||
// if(m_hTheme != NULL)
|
||||
// {
|
||||
// DrawThemeBackground(dc, BP_PUSHBUTTON, PBS_NORMAL, &rect, NULL);
|
||||
// DrawThemeText(dc, BP_PUSHBUTTON, PBS_NORMAL, L"Button", -1, DT_SINGLELINE | DT_CENTER | DT_VCENTER, 0, &rect);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// dc.DrawFrameControl(&rect, DFC_BUTTON, DFCS_BUTTONPUSH);
|
||||
// dc.DrawText(_T("Button"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
|
||||
// }
|
||||
//
|
||||
// Delay load is NOT AUTOMATIC for VC++ 7, you have to link to delayimp.lib,
|
||||
// and add uxtheme.dll in the Linker.Input.Delay Loaded DLLs section of the
|
||||
// project properties.
|
||||
#if (_MSC_VER < 1300) && !defined(_WTL_NO_THEME_DELAYLOAD)
|
||||
#pragma comment(lib, "delayimp.lib")
|
||||
#pragma comment(linker, "/delayload:uxtheme.dll")
|
||||
#endif //(_MSC_VER < 1300) && !defined(_WTL_NO_THEME_DELAYLOAD)
|
||||
|
||||
|
||||
// Classes in this file
|
||||
//
|
||||
// CTheme
|
||||
// CThemeImpl<T, TBase>
|
||||
|
||||
|
||||
namespace WTL
|
||||
{
|
||||
|
||||
// CTheme - wrapper for theme handle
|
||||
|
||||
class CTheme
|
||||
{
|
||||
public:
|
||||
// Data members
|
||||
HTHEME m_hTheme;
|
||||
static int m_nIsThemingSupported;
|
||||
|
||||
// Constructor
|
||||
CTheme() : m_hTheme(NULL)
|
||||
{
|
||||
IsThemingSupported();
|
||||
}
|
||||
|
||||
// Operators and helpers
|
||||
bool IsThemeNull() const
|
||||
{
|
||||
return (m_hTheme == NULL);
|
||||
}
|
||||
|
||||
CTheme& operator =(HTHEME hTheme)
|
||||
{
|
||||
m_hTheme = hTheme;
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator HTHEME() const
|
||||
{
|
||||
return m_hTheme;
|
||||
}
|
||||
|
||||
void Attach(HTHEME hTheme)
|
||||
{
|
||||
m_hTheme = hTheme;
|
||||
}
|
||||
|
||||
HTHEME Detach()
|
||||
{
|
||||
HTHEME hTheme = m_hTheme;
|
||||
m_hTheme = NULL;
|
||||
return hTheme;
|
||||
}
|
||||
|
||||
// Theme support helper
|
||||
static bool IsThemingSupported()
|
||||
{
|
||||
if(m_nIsThemingSupported == -1)
|
||||
{
|
||||
// ::EnterCriticalSection(&_Module.m_csStaticDataInit);
|
||||
if(m_nIsThemingSupported == -1)
|
||||
{
|
||||
HMODULE hThemeDLL = ::LoadLibrary(_T("uxtheme.dll"));
|
||||
m_nIsThemingSupported = (hThemeDLL != NULL) ? 1 : 0;
|
||||
if(hThemeDLL != NULL)
|
||||
::FreeLibrary(hThemeDLL);
|
||||
}
|
||||
// ::LeaveCriticalSection(&_Module.m_csStaticDataInit);
|
||||
}
|
||||
|
||||
//ATLASSERT(m_nIsThemingSupported != -1);
|
||||
return (m_nIsThemingSupported == 1);
|
||||
}
|
||||
|
||||
// Operations and theme properties
|
||||
HTHEME OpenThemeData(HWND hWnd, LPCWSTR pszClassList)
|
||||
{
|
||||
if(!IsThemingSupported())
|
||||
return NULL;
|
||||
|
||||
//ATLASSERT(m_hTheme == NULL);
|
||||
m_hTheme = ::OpenThemeData(hWnd, pszClassList);
|
||||
return m_hTheme;
|
||||
}
|
||||
|
||||
HRESULT CloseThemeData()
|
||||
{
|
||||
HRESULT hRet = S_FALSE;
|
||||
if(m_hTheme != NULL)
|
||||
{
|
||||
hRet = ::CloseThemeData(m_hTheme);
|
||||
if(SUCCEEDED(hRet))
|
||||
m_hTheme = NULL;
|
||||
}
|
||||
return hRet;
|
||||
}
|
||||
|
||||
HRESULT DrawThemeBackground(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, LPCRECT pClipRect = NULL)
|
||||
{
|
||||
return ::DrawThemeBackground(m_hTheme, hDC, nPartID, nStateID, pRect, pClipRect);
|
||||
}
|
||||
|
||||
HRESULT DrawThemeText(HDC hDC, int nPartID, int nStateID, LPCWSTR pszText, int nCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, LPCRECT pRect)
|
||||
{
|
||||
return ::DrawThemeText(m_hTheme, hDC, nPartID, nStateID, pszText, nCharCount, dwTextFlags, dwTextFlags2, pRect);
|
||||
}
|
||||
|
||||
HRESULT GetThemeBackgroundContentRect(HDC hDC, int nPartID, int nStateID, LPCRECT pBoundingRect, LPRECT pContentRect) const
|
||||
{
|
||||
return ::GetThemeBackgroundContentRect(m_hTheme, hDC, nPartID, nStateID, pBoundingRect, pContentRect);
|
||||
}
|
||||
|
||||
HRESULT GetThemeBackgroundExtent(HDC hDC, int nPartID, int nStateID, LPCRECT pContentRect, LPRECT pExtentRect) const
|
||||
{
|
||||
return ::GetThemeBackgroundExtent(m_hTheme, hDC, nPartID, nStateID, pContentRect, pExtentRect);
|
||||
}
|
||||
|
||||
HRESULT GetThemePartSize(HDC hDC, int nPartID, int nStateID, LPRECT pRect, enum THEMESIZE eSize, LPSIZE pSize) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemePartSize(m_hTheme, hDC, nPartID, nStateID, pRect, eSize, pSize);
|
||||
}
|
||||
|
||||
HRESULT GetThemeTextExtent(HDC hDC, int nPartID, int nStateID, LPCWSTR pszText, int nCharCount, DWORD dwTextFlags, LPCRECT pBoundingRect, LPRECT pExtentRect) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemeTextExtent(m_hTheme, hDC, nPartID, nStateID, pszText, nCharCount, dwTextFlags, pBoundingRect, pExtentRect);
|
||||
}
|
||||
|
||||
HRESULT GetThemeTextMetrics(HDC hDC, int nPartID, int nStateID, PTEXTMETRIC pTextMetric) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemeTextMetrics(m_hTheme, hDC, nPartID, nStateID, pTextMetric);
|
||||
}
|
||||
|
||||
HRESULT GetThemeBackgroundRegion(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, HRGN* pRegion) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemeBackgroundRegion(m_hTheme, hDC, nPartID, nStateID, pRect, pRegion);
|
||||
}
|
||||
|
||||
HRESULT HitTestThemeBackground(HDC hDC, int nPartID, int nStateID, DWORD dwOptions, LPCRECT pRect, HRGN hrgn, POINT ptTest, WORD* pwHitTestCode) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::HitTestThemeBackground(m_hTheme, hDC, nPartID, nStateID, dwOptions, pRect, hrgn, ptTest, pwHitTestCode);
|
||||
}
|
||||
|
||||
HRESULT DrawThemeEdge(HDC hDC, int nPartID, int nStateID, LPCRECT pDestRect, UINT uEdge, UINT uFlags, LPRECT pContentRect = NULL)
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::DrawThemeEdge(m_hTheme, hDC, nPartID, nStateID, pDestRect, uEdge, uFlags, pContentRect);
|
||||
}
|
||||
|
||||
HRESULT DrawThemeIcon(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, HIMAGELIST himl, int nImageIndex)
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::DrawThemeIcon(m_hTheme, hDC, nPartID, nStateID, pRect, himl, nImageIndex);
|
||||
}
|
||||
|
||||
BOOL IsThemePartDefined(int nPartID, int nStateID) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::IsThemePartDefined(m_hTheme, nPartID, nStateID);
|
||||
}
|
||||
|
||||
BOOL IsThemeBackgroundPartiallyTransparent(int nPartID, int nStateID) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::IsThemeBackgroundPartiallyTransparent(m_hTheme, nPartID, nStateID);
|
||||
}
|
||||
|
||||
HRESULT GetThemeColor(int nPartID, int nStateID, int nPropID, COLORREF* pColor) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemeColor(m_hTheme, nPartID, nStateID, nPropID, pColor);
|
||||
}
|
||||
|
||||
HRESULT GetThemeMetric(HDC hDC, int nPartID, int nStateID, int nPropID, int* pnVal) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemeMetric(m_hTheme, hDC, nPartID, nStateID, nPropID, pnVal);
|
||||
}
|
||||
|
||||
HRESULT GetThemeString(int nPartID, int nStateID, int nPropID, LPWSTR pszBuff, int cchMaxBuffChars) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemeString(m_hTheme, nPartID, nStateID, nPropID, pszBuff, cchMaxBuffChars);
|
||||
}
|
||||
|
||||
HRESULT GetThemeBool(int nPartID, int nStateID, int nPropID, BOOL* pfVal) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemeBool(m_hTheme, nPartID, nStateID, nPropID, pfVal);
|
||||
}
|
||||
|
||||
HRESULT GetThemeInt(int nPartID, int nStateID, int nPropID, int* pnVal) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemeInt(m_hTheme, nPartID, nStateID, nPropID, pnVal);
|
||||
}
|
||||
|
||||
HRESULT GetThemeEnumValue(int nPartID, int nStateID, int nPropID, int* pnVal) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemeEnumValue(m_hTheme, nPartID, nStateID, nPropID, pnVal);
|
||||
}
|
||||
|
||||
HRESULT GetThemePosition(int nPartID, int nStateID, int nPropID, LPPOINT pPoint) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemePosition(m_hTheme, nPartID, nStateID, nPropID, pPoint);
|
||||
}
|
||||
|
||||
HRESULT GetThemeFont(int nPartID, HDC hDC, int nStateID, int nPropID, LOGFONT* pFont) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemeFont(m_hTheme, hDC, nPartID, nStateID, nPropID, pFont);
|
||||
}
|
||||
|
||||
HRESULT GetThemeRect(int nPartID, int nStateID, int nPropID, LPRECT pRect) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemeRect(m_hTheme, nPartID, nStateID, nPropID, pRect);
|
||||
}
|
||||
|
||||
HRESULT GetThemeMargins(HDC hDC, int nPartID, int nStateID, int nPropID, LPRECT pRect, PMARGINS pMargins) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemeMargins(m_hTheme, hDC, nPartID, nStateID, nPropID, pRect, pMargins);
|
||||
}
|
||||
|
||||
HRESULT GetThemeIntList(int nPartID, int nStateID, int nPropID, INTLIST* pIntList) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemeIntList(m_hTheme, nPartID, nStateID, nPropID, pIntList);
|
||||
}
|
||||
|
||||
HRESULT GetThemePropertyOrigin(int nPartID, int nStateID, int nPropID, enum PROPERTYORIGIN* pOrigin) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemePropertyOrigin(m_hTheme, nPartID, nStateID, nPropID, pOrigin);
|
||||
}
|
||||
|
||||
HRESULT GetThemeFilename(int nPartID, int nStateID, int nPropID, LPWSTR pszThemeFileName, int cchMaxBuffChars) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemeFilename(m_hTheme, nPartID, nStateID, nPropID, pszThemeFileName, cchMaxBuffChars);
|
||||
}
|
||||
|
||||
COLORREF GetThemeSysColor(int nColorID) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemeSysColor(m_hTheme, nColorID);
|
||||
}
|
||||
|
||||
HBRUSH GetThemeSysColorBrush(int nColorID) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemeSysColorBrush(m_hTheme, nColorID);
|
||||
}
|
||||
|
||||
int GetThemeSysSize(int nSizeID) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemeSysSize(m_hTheme, nSizeID);
|
||||
}
|
||||
|
||||
BOOL GetThemeSysBool(int nBoolID) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemeSysBool(m_hTheme, nBoolID);
|
||||
}
|
||||
|
||||
HRESULT GetThemeSysFont(int nFontID, LOGFONT* plf) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemeSysFont(m_hTheme, nFontID, plf);
|
||||
}
|
||||
|
||||
HRESULT GetThemeSysString(int nStringID, LPWSTR pszStringBuff, int cchMaxStringChars) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemeSysString(m_hTheme, nStringID, pszStringBuff, cchMaxStringChars);
|
||||
}
|
||||
|
||||
HRESULT GetThemeSysInt(int nIntID, int* pnValue) const
|
||||
{
|
||||
//ATLASSERT(m_hTheme != NULL);
|
||||
return ::GetThemeSysInt(m_hTheme, nIntID, pnValue);
|
||||
}
|
||||
};
|
||||
|
||||
__declspec(selectany) int CTheme::m_nIsThemingSupported = -1;
|
||||
|
||||
|
||||
// CThemeImpl - theme support implementation
|
||||
|
||||
// Derive from this class to implement window with theme support.
|
||||
// Example:
|
||||
// class CMyThemeWindow : public CWindowImpl<CMyThemeWindow>, public CThemeImpl<CMyThemeWindow>
|
||||
// {
|
||||
// ...
|
||||
// BEGIN_MSG_MAP(CMyThemeWindow)
|
||||
// CHAIN_MSG_MAP(CThemeImpl<CMyThemeWindow>)
|
||||
// ...
|
||||
// END_MSG_MAP()
|
||||
// ...
|
||||
// };
|
||||
//
|
||||
// If you set theme class list, the class will automaticaly open/close/reopen theme data.
|
||||
|
||||
|
||||
// Helper for drawing theme client edge
|
||||
#if 0
|
||||
inline bool AtlDrawThemeClientEdge(HTHEME hTheme, HWND hWnd, HRGN hRgnUpdate = NULL, HBRUSH hBrush = NULL, int nPartID = 0, int nStateID = 0)
|
||||
{
|
||||
//ATLASSERT(hTheme != NULL);
|
||||
//ATLASSERT(::IsWindow(hWnd));
|
||||
|
||||
CWindowDC dc(hWnd);
|
||||
if(dc.IsNull())
|
||||
return false;
|
||||
|
||||
// Get border size
|
||||
int cxBorder = GetSystemMetrics(SM_CXBORDER);
|
||||
int cyBorder = GetSystemMetrics(SM_CYBORDER);
|
||||
if(SUCCEEDED(::GetThemeInt(hTheme, nPartID, nStateID, TMT_SIZINGBORDERWIDTH, &cxBorder)))
|
||||
cyBorder = cxBorder;
|
||||
|
||||
RECT rect;
|
||||
::GetWindowRect(hWnd, &rect);
|
||||
|
||||
// Remove the client edge from the update region
|
||||
int cxEdge = GetSystemMetrics(SM_CXEDGE);
|
||||
int cyEdge = GetSystemMetrics(SM_CYEDGE);
|
||||
::InflateRect(&rect, -cxEdge, -cyEdge);
|
||||
CRgn rgn;
|
||||
rgn.CreateRectRgnIndirect(&rect);
|
||||
if(rgn.IsNull())
|
||||
return false;
|
||||
|
||||
if(hRgnUpdate != NULL)
|
||||
rgn.CombineRgn(hRgnUpdate, rgn, RGN_AND);
|
||||
|
||||
::OffsetRect(&rect, -rect.left, -rect.top);
|
||||
|
||||
::OffsetRect(&rect, cxEdge, cyEdge);
|
||||
dc.ExcludeClipRect(&rect);
|
||||
::InflateRect(&rect, cxEdge, cyEdge);
|
||||
|
||||
::DrawThemeBackground(hTheme, dc, nPartID, nStateID, &rect, NULL);
|
||||
|
||||
// Use background brush too, since theme border might not cover everything
|
||||
if(cxBorder < cxEdge && cyBorder < cyEdge)
|
||||
{
|
||||
if(hBrush == NULL)
|
||||
// need conditional code because types don't match in winuser.h
|
||||
#ifdef _WIN64
|
||||
hBrush = (HBRUSH)::GetClassLongPtr(hWnd, GCLP_HBRBACKGROUND);
|
||||
#else
|
||||
hBrush = (HBRUSH)UlongToPtr(::GetClassLongPtr(hWnd, GCLP_HBRBACKGROUND));
|
||||
#endif
|
||||
|
||||
::InflateRect(&rect, cxBorder - cxEdge, cyBorder - cyEdge);
|
||||
dc.FillRect(&rect, hBrush);
|
||||
}
|
||||
|
||||
::DefWindowProc(hWnd, WM_NCPAINT, (WPARAM)rgn.m_hRgn, 0L);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Theme extended styles
|
||||
#define THEME_EX_3DCLIENTEDGE 0x00000001
|
||||
#define THEME_EX_THEMECLIENTEDGE 0x00000002
|
||||
|
||||
template <class T, class TBase = CTheme>
|
||||
class CThemeImpl : public TBase
|
||||
{
|
||||
public:
|
||||
// Data members
|
||||
LPWSTR m_lpstrThemeClassList;
|
||||
DWORD m_dwExtendedStyle; // theme specific extended styles
|
||||
|
||||
// Constructor & destructor
|
||||
CThemeImpl() : m_lpstrThemeClassList(NULL), m_dwExtendedStyle(0)
|
||||
{ }
|
||||
|
||||
~CThemeImpl()
|
||||
{
|
||||
delete m_lpstrThemeClassList;
|
||||
}
|
||||
|
||||
// Attributes
|
||||
bool SetThemeClassList(LPCWSTR lpstrThemeClassList)
|
||||
{
|
||||
if(m_lpstrThemeClassList != NULL)
|
||||
{
|
||||
delete m_lpstrThemeClassList;
|
||||
m_lpstrThemeClassList = NULL;
|
||||
}
|
||||
|
||||
if(lpstrThemeClassList == NULL)
|
||||
return true;
|
||||
|
||||
int cchLen = lstrlenW(lpstrThemeClassList) + 1;
|
||||
ATLTRY(m_lpstrThemeClassList = new WCHAR[cchLen]);
|
||||
if(m_lpstrThemeClassList == NULL)
|
||||
return false;
|
||||
|
||||
bool bRet = (lstrcpyW(m_lpstrThemeClassList, lpstrThemeClassList) != NULL);
|
||||
if(!bRet)
|
||||
{
|
||||
delete m_lpstrThemeClassList;
|
||||
m_lpstrThemeClassList = NULL;
|
||||
}
|
||||
return bRet;
|
||||
}
|
||||
|
||||
bool GetThemeClassList(LPWSTR lpstrThemeClassList, int cchListBuffer) const
|
||||
{
|
||||
int cchLen = lstrlenW(m_lpstrThemeClassList) + 1;
|
||||
if(cchListBuffer < cchLen)
|
||||
return false;
|
||||
|
||||
return (lstrcpyW(lpstrThemeClassList, m_lpstrThemeClassList) != NULL);
|
||||
}
|
||||
|
||||
LPCWSTR GetThemeClassList() const
|
||||
{
|
||||
return m_lpstrThemeClassList;
|
||||
}
|
||||
|
||||
DWORD SetThemeExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
|
||||
{
|
||||
DWORD dwPrevStyle = m_dwExtendedStyle;
|
||||
if(dwMask == 0)
|
||||
m_dwExtendedStyle = dwExtendedStyle;
|
||||
else
|
||||
m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
|
||||
return dwPrevStyle;
|
||||
}
|
||||
|
||||
DWORD GetThemeExtendedStyle() const
|
||||
{
|
||||
return m_dwExtendedStyle;
|
||||
}
|
||||
|
||||
// Operations
|
||||
HTHEME OpenThemeData()
|
||||
{
|
||||
T* pT = static_cast<T*>(this);
|
||||
//ATLASSERT(::IsWindow(pT->m_hWnd));
|
||||
//ATLASSERT(m_lpstrThemeClassList != NULL);
|
||||
if(m_lpstrThemeClassList == NULL)
|
||||
return NULL;
|
||||
CloseThemeData();
|
||||
return TBase::OpenThemeData(pT->m_hWnd, m_lpstrThemeClassList);
|
||||
}
|
||||
|
||||
HTHEME OpenThemeData(LPCWSTR pszClassList)
|
||||
{
|
||||
if(!SetThemeClassList(pszClassList))
|
||||
return NULL;
|
||||
return OpenThemeData();
|
||||
}
|
||||
|
||||
HRESULT SetWindowTheme(LPCWSTR pszSubAppName, LPCWSTR pszSubIDList)
|
||||
{
|
||||
if(!IsThemingSupported())
|
||||
return S_FALSE;
|
||||
|
||||
T* pT = static_cast<T*>(this);
|
||||
//ATLASSERT(::IsWindow(pT->m_hWnd));
|
||||
return ::SetWindowTheme(pT->m_hWnd, pszSubAppName, pszSubIDList);
|
||||
}
|
||||
|
||||
HTHEME GetWindowTheme() const
|
||||
{
|
||||
if(!IsThemingSupported())
|
||||
return NULL;
|
||||
|
||||
const T* pT = static_cast<const T*>(this);
|
||||
//ATLASSERT(::IsWindow(pT->m_hWnd));
|
||||
return ::GetWindowTheme(pT->m_hWnd);
|
||||
}
|
||||
|
||||
HRESULT EnableThemeDialogTexture(BOOL bEnable)
|
||||
{
|
||||
if(!IsThemingSupported())
|
||||
return S_FALSE;
|
||||
|
||||
T* pT = static_cast<T*>(this);
|
||||
//ATLASSERT(::IsWindow(pT->m_hWnd));
|
||||
return ::EnableThemeDialogTexture(pT->m_hWnd, bEnable);
|
||||
}
|
||||
|
||||
BOOL IsThemeDialogTextureEnabled() const
|
||||
{
|
||||
if(!IsThemingSupported())
|
||||
return FALSE;
|
||||
|
||||
const T* pT = static_cast<const T*>(this);
|
||||
//ATLASSERT(::IsWindow(pT->m_hWnd));
|
||||
return ::IsThemeDialogTextureEnabled(pT->m_hWnd);
|
||||
}
|
||||
|
||||
HRESULT DrawThemeParentBackground(HDC hDC, LPRECT pRect = NULL)
|
||||
{
|
||||
if(!IsThemingSupported())
|
||||
return S_FALSE;
|
||||
|
||||
T* pT = static_cast<T*>(this);
|
||||
//ATLASSERT(::IsWindow(pT->m_hWnd));
|
||||
return ::DrawThemeParentBackground(pT->m_hWnd, hDC, pRect);
|
||||
}
|
||||
|
||||
// Message map and handlers
|
||||
// Note: If you handle any of these messages in your derived class,
|
||||
// it is better to put CHAIN_MSG_MAP at the start of your message map.
|
||||
BEGIN_MSG_MAP(CThemeImpl)
|
||||
MESSAGE_HANDLER(WM_CREATE, OnCreate)
|
||||
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
|
||||
MESSAGE_HANDLER(WM_THEMECHANGED, OnThemeChanged)
|
||||
MESSAGE_HANDLER(WM_NCPAINT, OnNcPaint)
|
||||
END_MSG_MAP()
|
||||
|
||||
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
||||
{
|
||||
if(m_lpstrThemeClassList != NULL)
|
||||
OpenThemeData();
|
||||
bHandled = FALSE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
|
||||
{
|
||||
CloseThemeData();
|
||||
bHandled = FALSE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
LRESULT OnThemeChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
|
||||
{
|
||||
CloseThemeData();
|
||||
if(m_lpstrThemeClassList != NULL)
|
||||
OpenThemeData();
|
||||
bHandled = FALSE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
LRESULT OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
||||
{
|
||||
T* pT = static_cast<T*>(this);
|
||||
//ATLASSERT(::IsWindow(pT->m_hWnd));
|
||||
LRESULT lRet = 0;
|
||||
bHandled = FALSE;
|
||||
if(IsThemingSupported() && ((pT->GetExStyle() & WS_EX_CLIENTEDGE) != 0))
|
||||
{
|
||||
if((m_dwExtendedStyle & THEME_EX_3DCLIENTEDGE) != 0)
|
||||
{
|
||||
lRet = ::DefWindowProc(pT->m_hWnd, uMsg, wParam, lParam);
|
||||
bHandled = TRUE;
|
||||
}
|
||||
else if((m_hTheme != NULL) && ((m_dwExtendedStyle & THEME_EX_THEMECLIENTEDGE) != 0))
|
||||
{
|
||||
HRGN hRgn = (wParam != 1) ? (HRGN)wParam : NULL;
|
||||
if(pT->DrawThemeClientEdge(hRgn))
|
||||
bHandled = TRUE;
|
||||
}
|
||||
}
|
||||
return lRet;
|
||||
}
|
||||
|
||||
// Drawing helper
|
||||
bool DrawThemeClientEdge(HRGN hRgnUpdate)
|
||||
{
|
||||
T* pT = static_cast<T*>(this);
|
||||
return AtlDrawThemeClientEdge(m_hTheme, pT->m_hWnd, hRgnUpdate, NULL, 0, 0);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
}; //namespace WTL
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
#include "XFB.h"
|
||||
#include "Common.h"
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Video_UpdateXFB
|
||||
//
|
||||
|
||||
// TODO(ector): Write protect XFB. As soon as something pokes there,
|
||||
// switch to a mode where we actually display the XFB on top of the 3D.
|
||||
// If no writes have happened within 5 frames, revert to normal mode.
|
||||
|
||||
int bound(int i)
|
||||
{
|
||||
return (i>255)?255:((i<0)?0:i);
|
||||
}
|
||||
void yuv2rgb(int y, int u, int v, int &r, int &g, int &b)
|
||||
{
|
||||
b = bound((76283*(y - 16) + 132252*(u - 128))>>16);
|
||||
g = bound((76283*(y - 16) - 53281 *(v - 128) - 25624*(u - 128))>>16); //last one u?
|
||||
r = bound((76283*(y - 16) + 104595*(v - 128))>>16);
|
||||
}
|
||||
|
||||
void ConvertXFB(int *dst, const u8* _pXFB, int width, int height)
|
||||
{
|
||||
const unsigned char *src = _pXFB;
|
||||
for (int y=0; y < height; y++)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
int Y1 = *src++;
|
||||
int U = *src++;
|
||||
int Y2 = *src++;
|
||||
int V = *src++;
|
||||
|
||||
int r,g,b;
|
||||
yuv2rgb(Y1,U,V,r,g,b);
|
||||
*dst++ = 0xFF000000 | (r<<16) | (g<<8) | (b);
|
||||
yuv2rgb(Y2,U,V,r,g,b);
|
||||
*dst++ = 0xFF000000 | (r<<16) | (g<<8) | (b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef _XFB_H
|
||||
#define _XFB_H
|
||||
|
||||
#include "Common.h"
|
||||
void ConvertXFB(int *dst, const u8* _pXFB, int width, int height);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,155 @@
|
||||
#include "stdafx.h"
|
||||
#include "XFStructs.h"
|
||||
#include "Render.h"
|
||||
#include "main.h"
|
||||
#include "VertexHandler.h"
|
||||
#include "Utils.h"
|
||||
|
||||
|
||||
//XF state
|
||||
ColorChannel colChans[2]; //C0A0 C1A1
|
||||
TexCoordInfo texcoords[8];
|
||||
MiscXF miscxf;
|
||||
u32 xfmem[XFMEM_SIZE];
|
||||
|
||||
float rawViewPort[6];
|
||||
float rawProjection[7];
|
||||
|
||||
|
||||
|
||||
#define BEGINSAVELOAD char *optr=ptr;
|
||||
#define SAVELOAD(what,size) memcpy((void*)((save)?(void*)(ptr):(void*)(what)),(void*)((save)?(void*)(what):(void*)(ptr)),(size)); ptr+=(size);
|
||||
#define ENDSAVELOAD return ptr-optr;
|
||||
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// LoadXFReg 0x10
|
||||
//
|
||||
void LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData)
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
u32 address = baseAddress;
|
||||
for (int i=0; i<(int)transferSize; i++)
|
||||
{
|
||||
address = baseAddress + i;
|
||||
|
||||
// Setup a Matrix
|
||||
if (address < 0x1000)
|
||||
{
|
||||
u32* p1 = &xfmem[address];
|
||||
memcpy(p1, &pData[i], transferSize*4);
|
||||
i += transferSize;
|
||||
}
|
||||
else if (address<0x2000)
|
||||
{
|
||||
u32 data = pData[i];
|
||||
switch (address)
|
||||
{
|
||||
case 0x1006:
|
||||
//SetGPMetric
|
||||
break;
|
||||
case 0x1008: //__GXXfVtxSpecs, wrote 0004
|
||||
break;
|
||||
case 0x1009: //GXSetNumChans (no)
|
||||
break;
|
||||
case 0x100a: colChans[0].ambColor = data; break; //GXSetChanAmbientcolor
|
||||
case 0x100b: colChans[1].ambColor = data; break; //GXSetChanAmbientcolor
|
||||
case 0x100c: colChans[0].matColor = data; break; //GXSetChanMatcolor (rgba)
|
||||
case 0x100d: colChans[1].matColor = data; break; //GXSetChanMatcolor (rgba)
|
||||
|
||||
case 0x100e: colChans[0].color.hex = data; break; //color0
|
||||
case 0x100f: colChans[1].color.hex = data; break; //color1
|
||||
case 0x1010: colChans[0].alpha.hex = data; break; //alpha0
|
||||
case 0x1011: colChans[1].alpha.hex = data; break; //alpha1
|
||||
|
||||
case 0x1018:
|
||||
break;
|
||||
|
||||
case 0x101a:
|
||||
CVertexHandler::Flush();
|
||||
memcpy(rawViewPort,&pData[i],sizeof(rawViewPort));
|
||||
XFUpdateVP();
|
||||
i += 6;
|
||||
break;
|
||||
|
||||
case 0x1020:
|
||||
CVertexHandler::Flush();
|
||||
memcpy(rawProjection,&pData[i],sizeof(rawProjection));
|
||||
XFUpdatePJ();
|
||||
i += 7;
|
||||
return;
|
||||
|
||||
case 0x103f:
|
||||
miscxf.numTexGens = data;
|
||||
break;
|
||||
|
||||
case 0x1040: texcoords[0].texmtxinfo.hex = data; break;
|
||||
case 0x1041: texcoords[1].texmtxinfo.hex = data; break;
|
||||
case 0x1042: texcoords[2].texmtxinfo.hex = data; break;
|
||||
case 0x1043: texcoords[3].texmtxinfo.hex = data; break;
|
||||
case 0x1044: texcoords[4].texmtxinfo.hex = data; break;
|
||||
case 0x1045: texcoords[5].texmtxinfo.hex = data; break;
|
||||
case 0x1046: texcoords[6].texmtxinfo.hex = data; break;
|
||||
case 0x1047: texcoords[7].texmtxinfo.hex = data; break;
|
||||
|
||||
case 0x1050: texcoords[0].postmtxinfo.hex = data; break;
|
||||
case 0x1051: texcoords[1].postmtxinfo.hex = data; break;
|
||||
case 0x1052: texcoords[2].postmtxinfo.hex = data; break;
|
||||
case 0x1053: texcoords[3].postmtxinfo.hex = data; break;
|
||||
case 0x1054: texcoords[4].postmtxinfo.hex = data; break;
|
||||
case 0x1055: texcoords[5].postmtxinfo.hex = data; break;
|
||||
case 0x1056: texcoords[6].postmtxinfo.hex = data; break;
|
||||
case 0x1057: texcoords[7].postmtxinfo.hex = data; break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (address>=0x4000)
|
||||
{
|
||||
// MessageBox(NULL, "1", "1", MB_OK);
|
||||
//4010 __GXSetGenMode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check docs for this sucker...
|
||||
void LoadIndexedXF(u32 val, int array)
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
|
||||
int index = val>>16;
|
||||
int address = val&0xFFF; //check mask
|
||||
int size = ((val>>12)&0xF)+1;
|
||||
//load stuff from array to address in xf mem
|
||||
for (int i = 0; i < size; i++)
|
||||
xfmem[address + i] = Memory_Read_U32(arraybases[array] + arraystrides[array]*index + i*4);
|
||||
}
|
||||
|
||||
void XFUpdateVP()
|
||||
{
|
||||
Renderer::SetViewport(rawViewPort);
|
||||
}
|
||||
void XFUpdatePJ()
|
||||
{
|
||||
Renderer::SetProjection(rawProjection,0);
|
||||
}
|
||||
|
||||
size_t XFSaveLoadState(char *ptr, BOOL save)
|
||||
{
|
||||
BEGINSAVELOAD;
|
||||
SAVELOAD(colChans,2*sizeof(ColorChannel));
|
||||
SAVELOAD(texcoords,16*sizeof(TexCoordInfo));
|
||||
SAVELOAD(&miscxf,sizeof(MiscXF));
|
||||
SAVELOAD(rawViewPort,sizeof(rawViewPort));
|
||||
SAVELOAD(rawProjection,sizeof(rawProjection));
|
||||
SAVELOAD(xfmem,XFMEM_SIZE*sizeof(u32));
|
||||
|
||||
if (!save)
|
||||
{
|
||||
XFUpdateVP();
|
||||
XFUpdatePJ();
|
||||
}
|
||||
|
||||
ENDSAVELOAD;
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
#ifndef _XFSTRUCTS_H
|
||||
#define _XFSTRUCTS_H
|
||||
|
||||
|
||||
#include "Common.h"
|
||||
#include "Vec3.h"
|
||||
|
||||
|
||||
#pragma pack(4)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Lighting
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// xf_tex_projection_f enum
|
||||
#define XF_TEX_ST 0x00000000
|
||||
#define XF_TEX_STQ 0x00000001
|
||||
|
||||
// xf_tex_input_form_f enum
|
||||
#define XF_TEX_AB11 0x00000000
|
||||
#define XF_TEX_ABC1 0x00000001
|
||||
|
||||
// xf_tex_texgen_type_f enum
|
||||
#define XF_TEXGEN_REGULAR 0x00000000
|
||||
#define XF_TEXGEN_EMBOSS_MAP 0x00000001
|
||||
#define XF_TEXGEN_COLOR_STRGBC0 0x00000002
|
||||
#define XF_TEXGEN_COLOR_STRGBC1 0x00000003
|
||||
|
||||
// xf_tex_source_row_f enum
|
||||
#define XF_GEOM_INROW 0x00000000
|
||||
#define XF_NORMAL_INROW 0x00000001
|
||||
#define XF_COLORS_INROW 0x00000002
|
||||
#define XF_BINORMAL_T_INROW 0x00000003
|
||||
#define XF_BINORMAL_B_INROW 0x00000004
|
||||
#define XF_TEX0_INROW 0x00000005
|
||||
#define XF_TEX1_INROW 0x00000006
|
||||
#define XF_TEX2_INROW 0x00000007
|
||||
#define XF_TEX3_INROW 0x00000008
|
||||
#define XF_TEX4_INROW 0x00000009
|
||||
#define XF_TEX5_INROW 0x0000000a
|
||||
#define XF_TEX6_INROW 0x0000000b
|
||||
#define XF_TEX7_INROW 0x0000000c
|
||||
|
||||
|
||||
struct Light
|
||||
{
|
||||
u32 useless[3];
|
||||
//Vec3 direction;
|
||||
u32 color; //rgba
|
||||
float a0; //attenuation
|
||||
float a1;
|
||||
float a2;
|
||||
float k0; //k stuff
|
||||
float k1;
|
||||
float k2;
|
||||
union
|
||||
{
|
||||
struct {
|
||||
Vec3 dpos;
|
||||
Vec3 ddir;
|
||||
};
|
||||
struct {
|
||||
Vec3 sdir;
|
||||
Vec3 shalfangle;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
#define GX_SRC_REG 0
|
||||
#define GX_SRC_VTX 1
|
||||
|
||||
|
||||
|
||||
union LitChannel
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned matsource : 1;
|
||||
unsigned enablelighting : 1;
|
||||
unsigned lightMask0_3 : 4;
|
||||
unsigned ambsource : 1;
|
||||
unsigned diffusefunc : 2; //0=none 1=sign 2=clamp
|
||||
unsigned attnfunc : 2; //1=spec 3=spot 2=none ???
|
||||
unsigned lightMask4_7 : 4;
|
||||
};
|
||||
u32 hex;
|
||||
unsigned int GetFullLightMask()
|
||||
{
|
||||
return lightMask0_3 | (lightMask4_7 << 4);
|
||||
}
|
||||
};
|
||||
struct ColorChannel
|
||||
{
|
||||
u32 ambColor;
|
||||
u32 matColor;
|
||||
LitChannel color;
|
||||
LitChannel alpha;
|
||||
};
|
||||
struct MiscXF
|
||||
{
|
||||
int numTexGens;
|
||||
};
|
||||
union TexMtxInfo
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned unknown : 1;
|
||||
unsigned projection : 1;
|
||||
unsigned inputform : 2; //1 if three-component, 0 if two-component ?
|
||||
unsigned texgentype : 3; //0-POS 1-NRM 3-BINRM 4-TANGENT 5-TEX0 ...12-TEX7 13-COLOR
|
||||
unsigned sourcerow : 5;
|
||||
unsigned embosssourceshift : 3;
|
||||
unsigned embosslightshift : 3;
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
union PostMtxInfo
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned index : 8;
|
||||
unsigned normalize : 1;
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
struct TexCoordInfo
|
||||
{
|
||||
TexMtxInfo texmtxinfo;
|
||||
PostMtxInfo postmtxinfo;
|
||||
};
|
||||
|
||||
struct Viewport
|
||||
{
|
||||
float wd;
|
||||
float ht;
|
||||
float nearZ;
|
||||
float xOrig;
|
||||
float yOrig;
|
||||
float farZ;
|
||||
};
|
||||
|
||||
|
||||
#define XFMEM_SIZE 0x8000
|
||||
|
||||
|
||||
#define XFMEM_POSMATRICES 0x000
|
||||
#define XFMEM_NORMALMATRICES 0x400
|
||||
#define XFMEM_POSTMATRICES 0x500
|
||||
#define XFMEM_LIGHTS 0x600
|
||||
|
||||
|
||||
extern TexCoordInfo texcoords[8];
|
||||
extern ColorChannel colChans[2]; //C0A0 C1A1
|
||||
extern MiscXF miscxf;
|
||||
|
||||
extern unsigned __int32 xfmem[XFMEM_SIZE];
|
||||
|
||||
extern float rawViewPort[6];
|
||||
extern float rawProjection[7];
|
||||
|
||||
size_t XFSaveLoadState(char *ptr, BOOL save);
|
||||
void XFUpdateVP();
|
||||
void XFUpdatePJ();
|
||||
void LoadXFReg(u32 transferSize, u32 address, u32 *pData);
|
||||
void LoadIndexedXF(u32 val, int array);
|
||||
|
||||
#pragma pack()
|
||||
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,27 @@
|
||||
/* bmp_io.h 16 May 1999 */
|
||||
|
||||
#ifndef _BMP_IO_H
|
||||
#define _BMP_IO_H
|
||||
|
||||
int bmp_read ( char *filein_name, int *xsize, int *ysize, int **rarray,
|
||||
int **garray, int **barray );
|
||||
int bmp_read_data ( FILE *filein, int xsize, int ysize, int *rarray,
|
||||
int *garray, int *barray );
|
||||
int bmp_read_header ( FILE *filein, int *xsize, int *ysize, int *psize );
|
||||
int bmp_read_palette ( FILE *filein, int psize );
|
||||
int bmp_read_test ( char *filein_name );
|
||||
|
||||
int bmp_write ( char *fileout_name, int xsize, int ysize, char* rgba );
|
||||
int bmp_write_data ( FILE *fileout, int xsize, int ysize, char *rarray, char *garray, char *barray );
|
||||
|
||||
int bmp_write_header ( FILE *fileout, int xsize, int ysize );
|
||||
int bmp_write_test ( char *fileout_name );
|
||||
|
||||
int read_u_long_int ( unsigned long int *u_long_int_val, FILE *filein );
|
||||
int read_u_short_int ( unsigned short int *u_short_int_val, FILE *filein );
|
||||
|
||||
int write_u_long_int ( unsigned long int u_long_int_val, FILE *fileout );
|
||||
int write_u_short_int ( unsigned short int u_short_int_val, FILE *fileout );
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,262 @@
|
||||
#include <tchar.h>
|
||||
#include <windows.h>
|
||||
#include <d3dx9.h>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "resource.h"
|
||||
#include "main.h"
|
||||
#include "Globals.h"
|
||||
#include "Fifo.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "TextureCache.h"
|
||||
#include "BPStructs.h"
|
||||
#include "VertexHandler.h"
|
||||
#include "TransformEngine.h"
|
||||
#include "DlgSettings.h"
|
||||
#include "D3DPostProcess.h"
|
||||
#include "D3DTexture.h"
|
||||
#include "D3DUtil.h"
|
||||
#include "W32Util/misc.h"
|
||||
#include "EmuWindow.h"
|
||||
|
||||
#include "Utils.h"
|
||||
#include "XFB.h"
|
||||
|
||||
HINSTANCE g_hInstance = NULL;
|
||||
SVideoInitialize g_VideoInitialize;
|
||||
int initCount = 0;
|
||||
|
||||
BOOL APIENTRY DllMain( HINSTANCE hinstDLL, // DLL module handle
|
||||
DWORD dwReason, // reason called
|
||||
LPVOID lpvReserved) // reserved
|
||||
{
|
||||
switch (dwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
g_hInstance = hinstDLL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL Callback_PeekMessages()
|
||||
{
|
||||
//TODO: peekmessage
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
return FALSE;
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void UpdateFPSDisplay(const char *text)
|
||||
{
|
||||
SetWindowText(EmuWindow::GetWnd(), text);
|
||||
}
|
||||
|
||||
bool Init()
|
||||
{
|
||||
if (initCount==0)
|
||||
{
|
||||
// create the window
|
||||
// if( g_VideoInitialize.pWindowHandle == NULL ) // ignore parent for this plugin
|
||||
{
|
||||
// create the window
|
||||
g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create(NULL, g_hInstance, "Please wait...");
|
||||
if( g_VideoInitialize.pWindowHandle == NULL ) {
|
||||
MessageBox(GetActiveWindow(), "failed to create window", "Fatal Error", MB_OK);
|
||||
return false;
|
||||
}
|
||||
|
||||
g_VideoInitialize.pPeekMessages = Callback_PeekMessages;
|
||||
g_VideoInitialize.pUpdateFPSDisplay = UpdateFPSDisplay;
|
||||
EmuWindow::Show();
|
||||
}
|
||||
|
||||
if( g_VideoInitialize.pPeekMessages == NULL )
|
||||
return false;
|
||||
|
||||
if (FAILED(D3D::Init()))
|
||||
{
|
||||
MessageBox(GetActiveWindow(), "Cant Init D3d.\nYou probably havn't installed\nthe last version(9.0c)", "Fatal Error", MB_OK);
|
||||
return false;
|
||||
}
|
||||
InitLUTs();
|
||||
|
||||
}
|
||||
initCount++;
|
||||
g_Config.Load();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void DeInit()
|
||||
{
|
||||
initCount--;
|
||||
if (initCount==0)
|
||||
{
|
||||
D3D::Shutdown();
|
||||
EmuWindow::Close();
|
||||
}
|
||||
}
|
||||
|
||||
// ====================================================================================
|
||||
|
||||
void GetDllInfo (PLUGIN_INFO* _PluginInfo)
|
||||
{
|
||||
_PluginInfo->Version = 0x0100;
|
||||
_PluginInfo->Type = PLUGIN_TYPE_VIDEO;
|
||||
#ifdef DEBUGFAST
|
||||
sprintf_s(_PluginInfo->Name, 100, "Dolphin Video Plugin DebugFast (DX9)");
|
||||
#else
|
||||
#ifndef _DEBUG
|
||||
sprintf_s(_PluginInfo->Name, 100, "Dolphin Video Plugin (DX9)");
|
||||
#else
|
||||
sprintf_s(_PluginInfo->Name, 100, "Dolphin Video Plugin Debug (DX9)");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void DllAbout(HWND _hParent)
|
||||
{
|
||||
DialogBox(g_hInstance,(LPCSTR)IDD_ABOUT,_hParent,(DLGPROC)AboutProc);
|
||||
}
|
||||
|
||||
void DllConfig(HWND _hParent)
|
||||
{
|
||||
if (Init())
|
||||
{
|
||||
DlgSettings_Show(g_hInstance,_hParent);
|
||||
DeInit();
|
||||
}
|
||||
}
|
||||
|
||||
void Video_Initialize(SVideoInitialize* _pVideoInitialize)
|
||||
{
|
||||
if( _pVideoInitialize == NULL )
|
||||
return;
|
||||
|
||||
frameCount = 0;
|
||||
g_VideoInitialize = *_pVideoInitialize;
|
||||
Init();
|
||||
_pVideoInitialize->pPeekMessages = g_VideoInitialize.pPeekMessages;
|
||||
_pVideoInitialize->pUpdateFPSDisplay = g_VideoInitialize.pUpdateFPSDisplay;
|
||||
_pVideoInitialize->pWindowHandle = g_VideoInitialize.pWindowHandle;
|
||||
}
|
||||
|
||||
void Video_Prepare(void)
|
||||
{
|
||||
Renderer::Init(g_VideoInitialize);
|
||||
|
||||
TextureCache::Init();
|
||||
|
||||
BPInit();
|
||||
CVertexHandler::Init();
|
||||
OpcodeDecoder_Init();
|
||||
Fifo_Init();
|
||||
}
|
||||
|
||||
void Video_Shutdown(void)
|
||||
{
|
||||
Fifo_Shutdown();
|
||||
CVertexHandler::Shutdown();
|
||||
TextureCache::Shutdown();
|
||||
Renderer::Shutdown();
|
||||
OpcodeDecoder_Shutdown();
|
||||
DeInit();
|
||||
}
|
||||
|
||||
void Video_UpdateXFB(BYTE* _pXFB, DWORD _dwWidth, DWORD _dwHeight)
|
||||
{
|
||||
/*
|
||||
ConvertXFB(tempBuffer, _pXFB, _dwWidth, _dwHeight);
|
||||
|
||||
// blubb
|
||||
static LPDIRECT3DTEXTURE9 pTexture = D3D::CreateTexture2D((BYTE*)tempBuffer, _dwWidth, _dwHeight, _dwWidth, D3DFMT_A8R8G8B8);
|
||||
|
||||
D3D::ReplaceTexture2D(pTexture, (BYTE*)tempBuffer, _dwWidth, _dwHeight, _dwWidth, D3DFMT_A8R8G8B8);
|
||||
D3D::dev->SetTexture(0, pTexture);
|
||||
|
||||
D3D::quad2d(0,0,(float)Postprocess::GetWidth(),(float)Postprocess::GetHeight(), 0xFFFFFFFF);
|
||||
|
||||
D3D::EndFrame();
|
||||
D3D::BeginFrame();*/
|
||||
}
|
||||
|
||||
|
||||
void DebugLog(const char* _fmt, ...)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
char Msg[512];
|
||||
va_list ap;
|
||||
|
||||
va_start( ap, _fmt );
|
||||
vsprintf( Msg, _fmt, ap );
|
||||
va_end( ap );
|
||||
|
||||
g_VideoInitialize.pLog(Msg, FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void __Log(int log, const char *format, ...)
|
||||
{
|
||||
// char temp[512];
|
||||
//va_list args;
|
||||
//va_start(args, format);
|
||||
//CharArrayFromFormatV(temp, 512, format, args);
|
||||
//va_end(args);
|
||||
|
||||
DebugLog(format); //"%s", temp);
|
||||
}
|
||||
|
||||
|
||||
HRESULT ScreenShot(TCHAR *File)
|
||||
{
|
||||
if (D3D::dev == NULL)
|
||||
return S_FALSE;
|
||||
|
||||
D3DDISPLAYMODE DisplayMode;
|
||||
if (FAILED(D3D::dev->GetDisplayMode(0, &DisplayMode)))
|
||||
return S_FALSE;
|
||||
|
||||
LPDIRECT3DSURFACE9 surf;
|
||||
if (FAILED(D3D::dev->CreateOffscreenPlainSurface(DisplayMode.Width, DisplayMode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf, NULL)))
|
||||
return S_FALSE;
|
||||
|
||||
if (FAILED(D3D::dev->GetFrontBufferData(0, surf)))
|
||||
{
|
||||
surf->Release();
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
RECT rect;
|
||||
::GetWindowRect(EmuWindow::GetWnd(), &rect);
|
||||
if (FAILED(D3DXSaveSurfaceToFile(File, D3DXIFF_JPG, surf, NULL, &rect)))
|
||||
{
|
||||
surf->Release();
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
surf->Release();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
BOOL Video_Screenshot(TCHAR* _szFilename)
|
||||
{
|
||||
if (ScreenShot(_szFilename) == S_OK)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
#include "PluginSpecs_Video.h"
|
||||
#include "render.h"
|
||||
|
||||
extern SVideoInitialize g_VideoInitialize;
|
||||
|
||||
void DebugLog(const char* _fmt, ...);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,63 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by resource.rc
|
||||
//
|
||||
#define IDD_ABOUT 101
|
||||
#define IDD_SETTINGS 102
|
||||
#define IDD_DEBUGGER 103
|
||||
#define IDD_ADVANCED 104
|
||||
#define IDD_ENHANCEMENTS 105
|
||||
#define IDC_ENABLETEXTURING 1001
|
||||
#define IDC_CHECK2 1002
|
||||
#define IDC_WIREFRAME 1002
|
||||
#define IDC_USESHADERS 1002
|
||||
#define IDC_FORCEANISOTROPY 1002
|
||||
#define IDC_FULLSCREENENABLE 1002
|
||||
#define IDC_LIST1 1003
|
||||
#define IDC_FULLSCREENENABLE2 1003
|
||||
#define IDC_VSYNC 1003
|
||||
#define IDC_DEBUGSTEP 1004
|
||||
#define IDC_REGISTERS 1005
|
||||
#define IDC_ENABLEDEBUGGING 1006
|
||||
#define IDC_TAB1 1007
|
||||
#define IDC_REGISTERSELECT 1007
|
||||
#define IDC_ADAPTER 1008
|
||||
#define IDC_DEVICE 1009
|
||||
#define IDC_RESOLUTION 1010
|
||||
#define IDC_RESOLUTIONWINDOWED 1011
|
||||
#define IDC_ANTIALIASMODE 1012
|
||||
#define IDC_PPPARAM1 1013
|
||||
#define IDC_SHADERVERSION 1013
|
||||
#define IDC_PPPARAM2 1014
|
||||
#define IDC_CHECK1 1015
|
||||
#define IDC_POSTPROCESS 1016
|
||||
#define IDC_TRUFORM 1016
|
||||
#define IDC_PPPARAM1LABEL 1017
|
||||
#define IDC_POSTPROCESSEFFECT 1017
|
||||
#define IDC_PPPARAM2LABEL 1018
|
||||
#define IDC_PPPARAM1LABEL2 1018
|
||||
#define IDC_ANTIALIASQUALITY 1019
|
||||
#define IDC_ENABLEPOSTPROCESS 1020
|
||||
#define IDC_ANIMATE1 1021
|
||||
#define IDC_OVERLAYSTATS 1022
|
||||
#define IDC_DLOPTLEVEL 1023
|
||||
#define IDC_PREUPSCALETYPE 1024
|
||||
#define IDC_TRUFORMLEVEL 1025
|
||||
#define IDC_PREUPSCALE 1026
|
||||
#define IDC_SLIDER1 1027
|
||||
#define IDC_TEXDUMPPATH 1028
|
||||
#define IDC_TEXDUMP 1029
|
||||
#define IDC_FORCEFILTERING 1030
|
||||
#define IDC_BROWSETEXDUMPPATH 1031
|
||||
#define IDC_SHOWSHADERERRORS 1033
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 106
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1034
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,217 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Swedish resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_SVE)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_SWEDISH, SUBLANG_DEFAULT
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_ABOUT DIALOGEX 0, 0, 188, 81
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Dolphin D3D9 Video Plugin"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "Close",IDOK,131,60,50,14
|
||||
LTEXT "Code by ector",IDC_STATIC,7,7,85,9
|
||||
LTEXT "Hardware requirements: Radeon 9500 or better, or Geforce FX5200 or better.\nRadeon recommended.",IDC_STATIC,7,19,174,26
|
||||
LTEXT "Will not work correctly on older GPU:s.",IDC_STATIC,7,47,170,8
|
||||
END
|
||||
|
||||
IDD_SETTINGS DIALOGEX 0, 0, 231, 141
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
|
||||
FONT 8, "MS Shell Dlg", 0, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "&Graphics card:",IDC_STATIC,7,9,61,8
|
||||
COMBOBOX IDC_ADAPTER,68,7,156,84,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "&Fullscreen video mode:",IDC_STATIC,7,55,74,8
|
||||
COMBOBOX IDC_RESOLUTION,87,54,137,73,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "&Antialias mode:",IDC_STATIC,7,114,61,8
|
||||
COMBOBOX IDC_ANTIALIASMODE,68,113,156,73,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
CONTROL "&Rotate windowed mode 90 degrees (for Ikaruga)",IDC_CHECK1,
|
||||
"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_DISABLED | WS_TABSTOP,87,89,137,17
|
||||
LTEXT "&Windowed resolution:",IDC_STATIC,7,74,74,8
|
||||
COMBOBOX IDC_RESOLUTIONWINDOWED,87,73,137,73,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
CONTROL "&Fullscreen",IDC_FULLSCREENENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,68,25,141,8
|
||||
CONTROL "&V-Sync",IDC_VSYNC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,68,38,141,8
|
||||
END
|
||||
|
||||
IDD_DEBUGGER DIALOGEX 0, 0, 234, 254
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LISTBOX IDC_LIST1,7,16,70,231,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "&Command Stream",IDC_STATIC,7,7,70,8
|
||||
PUSHBUTTON "&Step",IDC_DEBUGSTEP,81,16,35,15
|
||||
CONTROL "",IDC_REGISTERS,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,81,68,146,179
|
||||
LTEXT "&Registers",IDC_STATIC,81,41,137,9
|
||||
CONTROL "&Enable debugging",IDC_ENABLEDEBUGGING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,121,19,70,8
|
||||
CONTROL "",IDC_REGISTERSELECT,"SysTabControl32",TCS_BUTTONS,80,52,145,13
|
||||
END
|
||||
|
||||
IDD_ADVANCED DIALOGEX 0, 0, 206, 144
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
|
||||
FONT 8, "MS Shell Dlg", 0, 0, 0x0
|
||||
BEGIN
|
||||
GROUPBOX "&Settings",IDC_STATIC,7,7,192,81
|
||||
CONTROL "&Wireframe",IDC_WIREFRAME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,19,79,9
|
||||
CONTROL "&Overlay some statistics",IDC_OVERLAYSTATS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,31,88,9
|
||||
LTEXT "&Default display list optimization level:",IDC_STATIC,14,57,137,9,WS_DISABLED
|
||||
COMBOBOX IDC_DLOPTLEVEL,14,67,178,63,CBS_DROPDOWNLIST | WS_DISABLED | WS_VSCROLL | WS_TABSTOP
|
||||
CONTROL "&Dump textures to:",IDC_TEXDUMP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,104,70,9
|
||||
EDITTEXT IDC_TEXDUMPPATH,25,116,148,12,ES_AUTOHSCROLL
|
||||
GROUPBOX "&Data dumping",IDC_STATIC,7,91,192,44
|
||||
PUSHBUTTON "...",IDC_BROWSETEXDUMPPATH,176,116,14,13
|
||||
CONTROL "Show s&hader compilation errors",IDC_SHOWSHADERERRORS,
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,43,127,9
|
||||
END
|
||||
|
||||
IDD_ENHANCEMENTS DIALOGEX 0, 0, 207, 175
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
GROUPBOX "Texture &enhancements",IDC_STATIC,7,61,193,34
|
||||
CONTROL "&Pre-upscale:",IDC_PREUPSCALE,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,16,76,54,10
|
||||
COMBOBOX IDC_PREUPSCALETYPE,74,74,117,49,CBS_DROPDOWNLIST | CBS_SORT | WS_DISABLED | WS_VSCROLL | WS_TABSTOP
|
||||
GROUPBOX "Texture &filtering",IDC_STATIC,7,7,193,50
|
||||
CONTROL "&Force bi/trilinear (may cause very small glitches)",IDC_FORCEFILTERING,
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,20,170,9
|
||||
GROUPBOX "&Postprocess image",IDC_STATIC,7,102,192,59
|
||||
LTEXT "&Effect:",IDC_STATIC,14,118,36,8
|
||||
COMBOBOX IDC_POSTPROCESSEFFECT,74,117,117,71,CBS_DROPDOWNLIST | WS_DISABLED | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "&Param 1",IDC_PPPARAM1LABEL2,14,141,35,8
|
||||
CONTROL "",IDC_PPPARAM1,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_DISABLED | WS_TABSTOP,68,137,127,15
|
||||
CONTROL "&Force 16x anisotropy filtering",IDC_FORCEANISOTROPY,
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,35,110,10
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DESIGNINFO
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO
|
||||
BEGIN
|
||||
IDD_ABOUT, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 181
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 74
|
||||
END
|
||||
|
||||
IDD_SETTINGS, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 224
|
||||
VERTGUIDE, 7
|
||||
VERTGUIDE, 68
|
||||
VERTGUIDE, 81
|
||||
VERTGUIDE, 87
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 134
|
||||
END
|
||||
|
||||
IDD_DEBUGGER, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 227
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 247
|
||||
END
|
||||
|
||||
IDD_ADVANCED, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 199
|
||||
VERTGUIDE, 14
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 137
|
||||
END
|
||||
|
||||
IDD_ENHANCEMENTS, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 200
|
||||
VERTGUIDE, 16
|
||||
VERTGUIDE, 74
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 168
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // Swedish resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#include "stdafx.h"
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#define _WIN32_WINNT 0x501
|
||||
#ifndef _WIN32_IE
|
||||
#define _WIN32_IE 0x0500 // Default value is 0x0400
|
||||
#endif
|
||||
|
||||
#include <tchar.h>
|
||||
#include <windows.h>
|
||||
|
||||
Reference in New Issue
Block a user