Initial megacommit.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard
2008-07-12 17:40:22 +00:00
parent a3be5d89ae
commit 775dc8a9c0
1920 changed files with 734652 additions and 0 deletions

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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();
}
}
}

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -0,0 +1,16 @@
#pragma once
namespace Postprocess
{
void Initialize();
void Cleanup();
void BeginFrame();
void FinalizeFrame();
int GetWidth();
int GetHeight();
const char **GetPostprocessingNames();
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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));
}
}

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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];
}

View File

@ -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

View File

@ -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();
}

View File

@ -0,0 +1,3 @@
#pragma once
void DlgSettings_Show(HINSTANCE hInstance, HWND parent);

View File

@ -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);
}
}

View File

@ -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

View File

@ -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--;
}
}
}
}

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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
};

View File

@ -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();
}
}

View File

@ -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

View File

@ -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;

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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);
};

View File

@ -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());
}

View File

@ -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();

View File

@ -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();
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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();
};

View File

@ -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]))();
}*/
}

View File

@ -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

View File

@ -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));
}

View File

@ -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)

View File

@ -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));
}
}
}

View File

@ -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);
};

View File

@ -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

View File

@ -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

View File

@ -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)
{
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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;}
};
}

View File

@ -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);
}

View File

@ -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);
};

View File

@ -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));
}
}

View File

@ -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__

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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);
};
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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);
}
}
}
}

View File

@ -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);
};
}

View File

@ -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);
}
}

View File

@ -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;}
};
}

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1 @@
#include "stdafx.h"

View File

@ -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>