From 5bcf69cbd672f26a3069b689fd70318089d2a90c Mon Sep 17 00:00:00 2001 From: omegadox Date: Mon, 22 Jun 2009 07:44:20 +0000 Subject: [PATCH] Forgot to add the source files... git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3532 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/VideoCommon/Src/SUFunctions.h | 60 ++ Source/Core/VideoCommon/Src/SUMemory.cpp | 68 ++ Source/Core/VideoCommon/Src/SUMemory.h | 914 ++++++++++++++++++ Source/Core/VideoCommon/Src/SUStructs.cpp | 595 ++++++++++++ Source/Core/VideoCommon/Src/SUStructs.h | 27 + .../Plugin_VideoDX9/Src/SUFunctions.cpp | 336 +++++++ .../Plugin_VideoOGL/Src/SUFunctions.cpp | 226 +++++ 7 files changed, 2226 insertions(+) create mode 100644 Source/Core/VideoCommon/Src/SUFunctions.h create mode 100644 Source/Core/VideoCommon/Src/SUMemory.cpp create mode 100644 Source/Core/VideoCommon/Src/SUMemory.h create mode 100644 Source/Core/VideoCommon/Src/SUStructs.cpp create mode 100644 Source/Core/VideoCommon/Src/SUStructs.h create mode 100644 Source/Plugins/Plugin_VideoDX9/Src/SUFunctions.cpp create mode 100644 Source/Plugins/Plugin_VideoOGL/Src/SUFunctions.cpp diff --git a/Source/Core/VideoCommon/Src/SUFunctions.h b/Source/Core/VideoCommon/Src/SUFunctions.h new file mode 100644 index 0000000000..5e259901b3 --- /dev/null +++ b/Source/Core/VideoCommon/Src/SUFunctions.h @@ -0,0 +1,60 @@ +// Copyright (C) 2003-2009 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +// ------------------------------------------ +// The plugins has to define these functions +// ------------------------------------------ + +#ifndef _SUFUNCTIONS_H_ +#define _SUFUNCTIONS_H_ + +#include "SUMemory.h" +#include "VideoCommon.h" + +namespace SUFunctions +{ + +enum +{ + CONFIG_ISWII = 0, + CONFIG_DISABLEFOG, + CONFIG_SHOWEFBREGIONS +}; + +void FlushPipeline(); +void SetGenerationMode(const BPCommand &bp); +void SetScissor(const BPCommand &bp); +void SetLineWidth(const BPCommand &bp); +void SetDepthMode(const BPCommand &bp); +void SetBlendMode(const BPCommand &bp); +void SetDitherMode(const BPCommand &bp); +void SetLogicOpMode(const BPCommand &bp); +void SetColorMask(const BPCommand &bp); +float GetRendererTargetScaleX(); +float GetRendererTargetScaleY(); +void CopyEFB(const BPCommand &bp, const TRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 ©fmt, const bool &scaleByHalf); +void RenderToXFB(const BPCommand &bp, const TRectangle &multirc, const float &yScale, const float &xfbLines, u8* pXFB, const u32 &dstWidth, const u32 &dstHeight); +void ClearScreen(const BPCommand &bp, const TRectangle &multirc); +void RestoreRenderState(const BPCommand &bp); +u8 *GetPointer(const u32 &address); +bool GetConfig(const int &type); +void SetSamplerState(const BPCommand &bp); +void SetInterlacingMode(const BPCommand &bp); +}; + +#endif // _SUFUNCTIONS_H_ \ No newline at end of file diff --git a/Source/Core/VideoCommon/Src/SUMemory.cpp b/Source/Core/VideoCommon/Src/SUMemory.cpp new file mode 100644 index 0000000000..cdb8f5749a --- /dev/null +++ b/Source/Core/VideoCommon/Src/SUMemory.cpp @@ -0,0 +1,68 @@ +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" + +#include "SUMemory.h" + +// SU state +// STATE_TO_SAVE +SUMemory sumem; + +// The plugin must implement this. +void SUWritten(const BPCommand& bp); + +// Call browser: OpcodeDecoding.cpp ExecuteDisplayList > Decode() > LoadSUReg() +void LoadSUReg(u32 value0) +{ + //handle the mask register + int opcode = value0 >> 24; + int oldval = ((u32*)&sumem)[opcode]; + int newval = (oldval & ~sumem.suMask) | (value0 & sumem.suMask); + int changes = (oldval ^ newval) & 0xFFFFFF; + + BPCommand bp = {opcode, changes, newval}; + + //reset the mask register + if (opcode != 0xFE) + sumem.suMask = 0xFFFFFF; + + SUWritten(bp); +} + +// Called when loading a saved state. +// Needs more testing though. +void SUReload() +{ + for (int i = 0; i < 254; i++) + { + switch (i) { + case 0x41: + case 0x45: //GXSetDrawDone + case 0x52: + case 0x65: + case 0x67: // set gp metric? + case SUMEM_PE_TOKEN_ID: + case SUMEM_PE_TOKEN_INT_ID: + // Cases in which we DON'T want to reload the BP + continue; + default: + BPCommand bp = {i, 0xFFFFFF, ((u32*)&sumem)[i]}; + SUWritten(bp); + } + } +} diff --git a/Source/Core/VideoCommon/Src/SUMemory.h b/Source/Core/VideoCommon/Src/SUMemory.h new file mode 100644 index 0000000000..4c1e81012c --- /dev/null +++ b/Source/Core/VideoCommon/Src/SUMemory.h @@ -0,0 +1,914 @@ +// Copyright (C) 2003-2009 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _SUMEMORY_H +#define _SUMEMORY_H + +#include "Common.h" + +#pragma pack(4) + +#define SUMEM_GENMODE 0x00 +#define SUMEM_DISPLAYCOPYFILER 0x01 // 0x01 + 4 +#define SUMEM_IND_MTXA 0x06 // 0x06 + (3 * 3) +#define SUMEM_IND_MTXB 0x07 // 0x07 + (3 * 3) +#define SUMEM_IND_MTXC 0x08 // 0x08 + (3 * 3) +#define SUMEM_IND_IMASK 0x0F +#define SUMEM_IND_CMD 0x10 // 0x10 + 16 +#define SUMEM_SCISSORTL 0x20 +#define SUMEM_SCISSORBR 0x21 +#define SUMEM_LINEPTWIDTH 0x22 +#define SUMEM_SU_COUNTER 0x23 +#define SUMEM_RAS_COUNTER 0x24 +#define SUMEM_RAS1_SS0 0x25 +#define SUMEM_RAS1_SS1 0x26 +#define SUMEM_IREF 0x27 +#define SUMEM_TREF 0x28 // 0x28 + 8 +#define SUMEM_SU_SSIZE 0x30 // 0x30 + (2 * 8) +#define SUMEM_SU_TSIZE 0x31 // 0x31 + (2 * 8) +#define SUMEM_ZMODE 0x40 +#define SUMEM_BLENDMODE 0x41 +#define SUMEM_CONSTANTALPHA 0x42 +#define SUMEM_ZCOMPARE 0x43 +#define SUMEM_FIELDMASK 0x44 +#define SUMEM_SETDRAWDONE 0x45 +#define SUMEM_CLOCK0 0x46 +#define SUMEM_PE_TOKEN_ID 0x47 +#define SUMEM_PE_TOKEN_INT_ID 0x48 +#define SUMEM_EFB_TL 0x49 +#define SUMEM_EFB_BR 0x4A +#define SUMEM_EFB_ADDR 0x4B +#define SUMEM_MIPMAP_STRIDE 0x4D +#define SUMEM_COPYYSCALE 0x4E +#define SUMEM_CLEAR_AR 0x4F +#define SUMEM_CLEAR_GB 0x50 +#define SUMEM_CLEAR_Z 0x51 +#define SUMEM_TRIGGER_EFB_COPY 0x52 +#define SUMEM_COPYFILTER0 0x53 +#define SUMEM_COPYFILTER1 0x54 +#define SUMEM_CLEARBBOX1 0x55 +#define SUMEM_CLEARBBOX2 0x56 +#define SUMEM_UNKNOWN 0x58 +#define SUMEM_SCISSOROFFSET 0x59 +#define SUMEM_UNKNOWN1 0x60 +#define SUMEM_UNKNOWN2 0x61 +#define SUMEM_UNKNOWN3 0x62 +#define SUMEM_UNKNOWN4 0x63 +#define SUMEM_LOADTLUT0 0x64 +#define SUMEM_LOADTLUT1 0x65 +#define SUMEM_TEXINVALIDATE 0x66 +#define SUMEM_SETGPMETRIC 0x67 +#define SUMEM_FIELDMODE 0x68 +#define SUMEM_CLOCK1 0x69 +#define SUMEM_TX_SETMODE0 0x80 // 0x80 + 4 +#define SUMEM_TX_SETMODE1 0x84 // 0x84 + 4 +#define SUMEM_TX_SETIMAGE0 0x88 // 0x88 + 4 +#define SUMEM_TX_SETIMAGE1 0x8C // 0x8C + 4 +#define SUMEM_TX_SETIMAGE2 0x90 // 0x90 + 4 +#define SUMEM_TX_SETIMAGE3 0x94 // 0x94 + 4 +#define SUMEM_TX_SETTLUT 0x98 // 0x98 + 4 +#define SUMEM_TX_SETMODE0_4 0xA0 // 0xA0 + 4 +#define SUMEM_TX_SETMODE1_4 0xA4 // 0xA4 + 4 +#define SUMEM_TX_SETIMAGE0_4 0xA8 // 0xA8 + 4 +#define SUMEM_TX_SETIMAGE1_4 0xAC // 0xA4 + 4 +#define SUMEM_TX_SETIMAGE2_4 0xB0 // 0xB0 + 4 +#define SUMEM_TX_SETIMAGE3_4 0xB4 // 0xB4 + 4 +#define SUMEM_TX_SETLUT_4 0xB8 // 0xB8 + 4 +#define SUMEM_TEV_COLOR_ENV 0xC0 // 0xC0 + (2 * 16) +#define SUMEM_TEV_ALPHA_ENV 0xC1 // 0xC1 + (2 * 16) +#define SUMEM_TEV_REGISTER_L 0xE0 // 0xE0 + (2 * 4) +#define SUMEM_TEV_REGISTER_H 0xE1 // 0xE1 + (2 * 4) +#define SUMEM_FOGRANGE 0xE8 +#define SUMEM_FOGPARAM0 0xEE +#define SUMEM_FOGBMAGNITUDE 0xEF +#define SUMEM_FOGBEXPONENT 0xF0 +#define SUMEM_FOGPARAM3 0xF1 +#define SUMEM_FOGCOLOR 0xF2 +#define SUMEM_ALPHACOMPARE 0xF3 +#define SUMEM_BIAS 0xF4 +#define SUMEM_ZTEX2 0xF5 +#define SUMEM_TEV_KSEL 0xF6 // 0xF6 + 8 +#define SUMEM_BP_MASK 0xFE + +////////////////////////////////////////////////////////////////////////// +// Tev/combiner things +////////////////////////////////////////////////////////////////////////// + +#define TEVOP_ADD 0 +#define TEVOP_SUB 1 +#define TEVCMP_R8_GT 8 +#define TEVCMP_R8_EQ 9 +#define TEVCMP_GR16_GT 10 +#define TEVCMP_GR16_EQ 11 +#define TEVCMP_BGR24_GT 12 +#define TEVCMP_BGR24_EQ 13 +#define TEVCMP_RGB8_GT 14 +#define TEVCMP_RGB8_EQ 15 +#define TEVCMP_A8_GT 14 +#define TEVCMP_A8_EQ 15 + +#define TEVCOLORARG_CPREV 0 +#define TEVCOLORARG_APREV 1 +#define TEVCOLORARG_C0 2 +#define TEVCOLORARG_A0 3 +#define TEVCOLORARG_C1 4 +#define TEVCOLORARG_A1 5 +#define TEVCOLORARG_C2 6 +#define TEVCOLORARG_A2 7 +#define TEVCOLORARG_TEXC 8 +#define TEVCOLORARG_TEXA 9 +#define TEVCOLORARG_RASC 10 +#define TEVCOLORARG_RASA 11 +#define TEVCOLORARG_ONE 12 +#define TEVCOLORARG_HALF 13 +#define TEVCOLORARG_KONST 14 +#define TEVCOLORARG_ZERO 15 + +#define TEVALPHAARG_APREV 0 +#define TEVALPHAARG_A0 1 +#define TEVALPHAARG_A1 2 +#define TEVALPHAARG_A2 3 +#define TEVALPHAARG_TEXA 4 +#define TEVALPHAARG_RASA 5 +#define TEVALPHAARG_KONST 6 +#define TEVALPHAARG_ZERO 7 + +#define ALPHACMP_NEVER 0 +#define ALPHACMP_LESS 1 +#define ALPHACMP_EQUAL 2 +#define ALPHACMP_LEQUAL 3 +#define ALPHACMP_GREATER 4 +#define ALPHACMP_NEQUAL 5 +#define ALPHACMP_GEQUAL 6 +#define ALPHACMP_ALWAYS 7 + +enum Compare +{ + COMPARE_NEVER = 0, + COMPARE_LESS, + COMPARE_EQUAL, + COMPARE_LEQUAL, + COMPARE_GREATER, + COMPARE_NEQUAL, + COMPARE_GEQUAL, + COMPARE_ALWAYS +}; + +#define ZTEXTURE_DISABLE 0 +#define ZTEXTURE_ADD 1 +#define ZTEXTURE_REPLACE 2 + +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, +}; + +union IND_MTXA +{ + struct + { + signed ma : 11; + signed mb : 11; + unsigned s0 : 2; // bits 0-1 of scale factor + unsigned rid : 8; + }; + u32 hex; +}; + +union IND_MTXB +{ + struct + { + signed mc : 11; + signed md : 11; + unsigned s1 : 2; // bits 2-3 of scale factor + unsigned rid : 8; + }; + u32 hex; +}; + +union IND_MTXC +{ + struct + { + signed me : 11; + signed mf : 11; + unsigned s2 : 2; // bits 4-5 of scale factor + unsigned rid : 8; + }; + u32 hex; +}; + +struct IND_MTX +{ + IND_MTXA col0; + IND_MTXB col1; + IND_MTXC col2; +}; + +union IND_IMASK +{ + struct + { + unsigned mask : 24; + unsigned rid : 8; + }; + u32 hex; +}; + +#define TEVSELCC_CPREV 0 +#define TEVSELCC_APREV 1 +#define TEVSELCC_C0 2 +#define TEVSELCC_A0 3 +#define TEVSELCC_C1 4 +#define TEVSELCC_A1 5 +#define TEVSELCC_C2 6 +#define TEVSELCC_A2 7 +#define TEVSELCC_TEXC 8 +#define TEVSELCC_TEXA 9 +#define TEVSELCC_RASC 10 +#define TEVSELCC_RASA 11 +#define TEVSELCC_ONE 12 +#define TEVSELCC_HALF 13 +#define TEVSELCC_KONST 14 +#define TEVSELCC_ZERO 15 + +#define TEVSELCA_APREV 0 +#define TEVSELCA_A0 1 +#define TEVSELCA_A1 2 +#define TEVSELCA_A2 3 +#define TEVSELCA_TEXA 4 +#define TEVSELCA_RASA 5 +#define TEVSELCA_KONST 6 +#define TEVSELCA_ZERO 7 + +struct TevStageCombiner +{ + union ColorCombiner + { + struct //abc=8bit,d=10bit + { + unsigned d : 4; // TEVSELCC_X + unsigned c : 4; // TEVSELCC_X + unsigned b : 4; // TEVSELCC_X + unsigned a : 4; // TEVSELCC_X + + unsigned bias : 2; + unsigned op : 1; + unsigned clamp : 1; + + unsigned shift : 2; + unsigned dest : 2; //1,2,3 + + }; + u32 hex; + }; + union AlphaCombiner + { + struct + { + unsigned rswap : 2; + unsigned tswap : 2; + unsigned d : 3; // TEVSELCA_ + unsigned c : 3; // TEVSELCA_ + unsigned b : 3; // TEVSELCA_ + unsigned a : 3; // TEVSELCA_ + + unsigned bias : 2; //GXTevBias + unsigned op : 1; + unsigned clamp : 1; + + unsigned shift : 2; + unsigned dest : 2; //1,2,3 + }; + u32 hex; + }; + + ColorCombiner colorC; + AlphaCombiner alphaC; +}; + +#define ITF_8 0 +#define ITF_5 1 +#define ITF_4 2 +#define ITF_3 3 + +#define ITB_NONE 0 +#define ITB_S 1 +#define ITB_T 2 +#define ITB_ST 3 +#define ITB_U 4 +#define ITB_SU 5 +#define ITB_TU 6 +#define ITB_STU 7 + +#define ITBA_OFF 0 +#define ITBA_S 1 +#define ITBA_T 2 +#define ITBA_U 3 + +#define ITW_OFF 0 +#define ITW_256 1 +#define ITW_128 2 +#define ITW_64 3 +#define ITW_32 4 +#define ITW_16 5 +#define ITW_0 6 + +// several discoveries: +// GXSetTevIndBumpST(tevstage, indstage, matrixind) +// if( matrix == 2 ) realmat = 6; // 10 +// else if( matrix == 3 ) realmat = 7; // 11 +// else if( matrix == 1 ) realmat = 5; // 9 +// GXSetTevIndirect(tevstage, indstage, 0, 3, realmat, 6, 6, 0, 0, 0) +// GXSetTevIndirect(tevstage+1, indstage, 0, 3, realmat+4, 6, 6, 1, 0, 0) +// GXSetTevIndirect(tevstage+2, indstage, 0, 0, 0, 0, 0, 1, 0, 0) + +union TevStageIndirect +{ + // if mid, sw, tw, and addprev are 0, then no indirect stage is used, mask = 0x17fe00 + struct + { + unsigned bt : 2; // indirect tex stage ID + unsigned fmt : 2; // format: ITF_X + unsigned bias : 3; // ITB_X + unsigned bs : 2; // ITBA_X, indicates which coordinate will become the 'bump alpha' + unsigned mid : 4; // matrix id to multiply offsets with + unsigned sw : 3; // ITW_X, wrapping factor for S of regular coord + unsigned tw : 3; // ITW_X, wrapping factor for T of regular coord + unsigned lb_utclod : 1; // use modified or unmodified texture coordinates for LOD computation + unsigned fb_addprev : 1; // 1 if the texture coordinate results from the previous TEV stage should be added + unsigned pad0 : 3; + unsigned rid : 8; + }; + struct + { + u32 hex : 21; + u32 unused : 11; + }; + + bool IsActive() { return (hex&0x17fe00)!=0; } +}; + +union TwoTevStageOrders +{ + struct + { + unsigned texmap0 : 3; // indirect tex stage texmap + unsigned texcoord0 : 3; + unsigned enable0 : 1; // 1 if should read from texture + unsigned colorchan0 : 3; // RAS1_CC_X + + unsigned pad0 : 2; + + unsigned texmap1 : 3; + unsigned texcoord1 : 3; + unsigned enable1 : 1; // 1 if should read from texture + unsigned colorchan1 : 3; // RAS1_CC_X + + unsigned pad1 : 2; + unsigned rid : 8; + }; + 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;} +}; + +union TEXSCALE +{ + struct + { + unsigned ss0 : 4; // indirect tex stage 0, 2^(-ss0) + unsigned ts0 : 4; // indirect tex stage 0 + unsigned ss1 : 4; // indirect tex stage 1 + unsigned ts1 : 4; // indirect tex stage 1 + unsigned pad : 8; + unsigned rid : 8; + }; + u32 hex; + + float getScaleS(int i){return 1.0f/(float)(1<<(i?ss1:ss0));} + float getScaleT(int i){return 1.0f/(float)(1<<(i?ts1:ts0));} +}; + +union RAS1_IREF +{ + struct + { + unsigned bi0 : 3; // indirect tex stage 0 ntexmap + unsigned bc0 : 3; // indirect tex stage 0 ntexcoord + unsigned bi1 : 3; + unsigned bc1 : 3; + unsigned bi2 : 3; + unsigned bc3 : 3; + unsigned bi4 : 3; + unsigned bc4 : 3; + unsigned rid : 8; + }; + u32 hex; + + u32 getTexCoord(int i) { return (hex>>(6*i+3))&3; } + u32 getTexMap(int i) { return (hex>>(6*i))&3; } +}; + +////////////////////////////////////////////////////////////////////////// +// 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 : 10; + 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 (was 20 for GC) + }; + 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; // TEV_Z_TYPE_X + unsigned op : 2; // GXZTexOp + }; + u32 hex; +}; + +// Z-texture types (formats) +#define TEV_ZTEX_TYPE_U8 0 +#define TEV_ZTEX_TYPE_U16 1 +#define TEV_ZTEX_TYPE_U24 2 + +#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; // in 1/6th pixels + unsigned pointsize : 8; // in 1/6th pixels + 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; + }; + + float GetA() { + union { u32 i; float f; } dummy; + dummy.i = ((u32)sign<<31)|((u32)exponent<<23)|((u32)mantissa<<12); + return dummy.f; + } + + u32 hex; +}; + +union FogParam3 +{ + struct + { + unsigned c_mant : 11; + unsigned c_exp : 8; + unsigned c_sign : 1; + unsigned proj : 1; // 0 - perspective, 1 - orthographic + unsigned fsel : 3; // 0 - off, 2 - linear, 4 - exp, 5 - exp2, 6 - backward exp, 7 - backward exp2 + }; + + // amount to subtract from eyespacez after range adjustment + float GetC() { + union { u32 i; float f; } dummy; + dummy.i = ((u32)c_sign << 31) | ((u32)c_exp << 23) | ((u32)c_mant << 12); + return dummy.f; + } + + u32 hex; +}; + +// final eq: ze = A/(B_MAG - (Zs>>B_SHF)); +struct FogParams +{ + FogParam0 a; + u32 b_magnitude; + u32 b_shift; // b's exp + 1? + FogParam3 c_proj_fsel; + + union FogColor + { + struct + { + unsigned b : 8; + unsigned g : 8; + unsigned r : 8; + }; + u32 hex; + }; + + FogColor 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; +}; + +#define PIXELFMT_RGB8_Z24 0 +#define PIXELFMT_RGBA6_Z24 1 +#define PIXELFMT_RGB565_Z16 2 +#define PIXELFMT_Z24 3 +#define PIXELFMT_Y8 4 +#define PIXELFMT_U8 5 +#define PIXELFMT_V8 6 +#define PIXELFMT_YUV420 7 + +union PE_CONTROL +{ + struct + { + unsigned pixel_format : 3; // PIXELFMT_X + unsigned zformat : 3; // 0 - linear, 1 - near, 2 - mid, 3 - far + unsigned zcomploc : 1; // 1: before tex stage + unsigned unused : 17; + unsigned rid : 8; + }; + 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; +}; + + +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 : 1; + unsigned target_pixel_format : 4; // realformat is (fmt/2)+((fmt&1)*8).... for some reason the msb is the lsb + unsigned gamma : 2; + unsigned half_scale : 1; // real size should be 2x smaller (run a gauss filter?) + unsigned scale_something : 1; + unsigned clear : 1; + unsigned frame_to_field : 2; + unsigned copy_to_xfb : 1; + unsigned intensity_fmt : 1; // if set, is an intensity format (I4,I8,IA4,IA8) + unsigned : 16; // seems to set everything to 1s when target pixel format is invalid + }; +}; + +////////////////////////////////////////////////////////////////////////// +// All of SU memory +////////////////////////////////////////////////////////////////////////// + +// ByPass Command +struct BPCommand +{ + int address; + int changes; + int newvalue; +}; + +struct SUMemory +{ + GenMode genMode; + u32 display_copy_filter[4]; // 01-04 + u32 unknown; // 05 + // indirect matrices (set by GXSetIndTexMtx, selected by TevStageIndirect::mid) + // abc form a 2x3 offset matrix, there's 3 such matrices + // the 3 offset matrices can either be indirect type, S-type, or T-type + // 6bit scale factor s is distributed across IND_MTXA/B/C. + // before using matrices scale by 2^-(s-17) + IND_MTX indmtx[3];//06-0e GXSetIndTexMtx, 2x3 matrices + IND_IMASK imask;//0f + TevStageIndirect tevind[16];//10 GXSetTevIndirect + X12Y12 scissorTL; //20 + X12Y12 scissorBR; //21 + LPSize lineptwidth; //22 line and point width + u32 sucounter; //23 + u32 rascounter; //24 + TEXSCALE texscale[2]; //25-26 GXSetIndTexCoordScale + RAS1_IREF tevindref; //27 GXSetIndTexOrder + 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 + PE_CONTROL zcontrol; //43 GXSetZCompLoc, GXPixModeSync + u32 fieldmask; //44 + u32 drawdone; //45, bit1=1 if end of list + u32 unknown5; //46 clock? + u32 petoken; //47 + u32 petokenint; // 48 + X10Y10 copyTexSrcXY; // 49 + X10Y10 copyTexSrcWH; // 4a + u32 copyTexDest; //4b// 4b == CopyAddress (GXDispCopy and GXTexCopy use it) + u32 unknown6; //4c + u32 copyMipMapStrideChannels; // 4d usually set to 4 when dest is single channel, 8 when dest is 2 channel, 16 when dest is RGBA + // also, doubles whenever mipmap box filter option is set (excent on RGBA). Probably to do with number of bytes to look at when smoothing + 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), 0x60-0x63 have to do with preloaded textures? + u32 tlutXferSrc; //64 + u32 tlutXferDest; //65 + u32 texinvalidate;//66 + u32 metric; //67 + u32 fieldmode;//68 + u32 unknown10[7];//69-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[3]; //0xe9,0xea,0xeb - fog related + u32 tev_range_adj_c; //0xec - screenx center for range adjustment, range adjustment enable + u32 tev_range_adj_k; //0xed - specifies range adjustment function = sqrt(x*x+k*k)/k + 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 suMask; //0xFE + u32 unknown18; //ff +}; + +#pragma pack() + +extern SUMemory sumem; + +void LoadSUReg(u32 value0); + +#endif diff --git a/Source/Core/VideoCommon/Src/SUStructs.cpp b/Source/Core/VideoCommon/Src/SUStructs.cpp new file mode 100644 index 0000000000..ff26f4e592 --- /dev/null +++ b/Source/Core/VideoCommon/Src/SUStructs.cpp @@ -0,0 +1,595 @@ +// Copyright (C) 2003-2009 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include + +#include "Profiler.h" +#include "Statistics.h" +#include "VideoCommon.h" +#include "PixelShaderManager.h" +#include "SUFunctions.h" +#include "SUStructs.h" +#include "TextureDecoder.h" +#include "OpcodeDecoding.h" +#include "VertexLoader.h" +#include "VertexShaderManager.h" + +using namespace SUFunctions; + +void SUInit() +{ + memset(&sumem, 0, sizeof(sumem)); + sumem.suMask = 0xFFFFFF; +} + +// ---------------------------------------------------------------------------------------------------------- +// Write the bypass command to the Setup/Rasterization Memory +/* ------------------ + Called: + At the end of every: OpcodeDecoding.cpp ExecuteDisplayList > Decode() > LoadSUReg + TODO: + Turn into function table. The (future) DisplayList (DL) jit can then call the functions directly, + getting rid of dynamic dispatch. Unfortunately, few games use DLs properly - most\ + just stuff geometry in them and don't put state changes there. */ +// ---------------------------------------------------------------------------------------------------------- +void SUWritten(const BPCommand& bp) +{ + // -------------------------------------------------------------------------------------------------------- + // First the pipeline is flushed then update the sumem with the new value. + // Some of the BP cases have to call certain functions while others just update the sumem. + // some bp cases check the changes variable, because they might not have to be updated all the time + // NOTE: it seems not all su cases like checking changes, so calling if (bp.changes == 0 ? false : true) + // had to be ditched and the games seem to work fine with out it. + // -------------------------------------------------------------------------------------------------------- + + // Debugging only, this lets you skip a bp update + //static int times = 0; + //static bool enable = false; + + //switch (bp.address) + //{ + //case SUMEM_CONSTANTALPHA: + // { + // if (times-- == 0 && enable) + // return; + // else + // break; + // } + //default: break; + //} + + FlushPipeline(); + ((u32*)&sumem)[bp.address] = bp.newvalue; + + switch (bp.address) + { + case SUMEM_GENMODE: // Set the Generation Mode + { + PRIM_LOG("genmode: texgen=%d, col=%d, ms_en=%d, tev=%d, culmode=%d, ind=%d, zfeeze=%d", + sumem.genMode.numtexgens, sumem.genMode.numcolchans, + sumem.genMode.ms_en, sumem.genMode.numtevstages+1, sumem.genMode.cullmode, + sumem.genMode.numindstages, sumem.genMode.zfreeze); + SetGenerationMode(bp); + break; + } + case SUMEM_IND_MTXA: // Index Matrix Changed + case SUMEM_IND_MTXB: + case SUMEM_IND_MTXC: + case SUMEM_IND_MTXA+3: + case SUMEM_IND_MTXB+3: + case SUMEM_IND_MTXC+3: + case SUMEM_IND_MTXA+6: + case SUMEM_IND_MTXB+6: + case SUMEM_IND_MTXC+6: + PixelShaderManager::SetIndMatrixChanged((bp.address - SUMEM_IND_MTXA) / 3); + break; + case SUMEM_RAS1_SS0: // Index Texture Coordinate Scale 0 + PixelShaderManager::SetIndTexScaleChanged(0x03); + case SUMEM_RAS1_SS1: // Index Texture Coordinate Scale 1 + PixelShaderManager::SetIndTexScaleChanged(0x0c); + break; + case SUMEM_SCISSORTL: // Scissor Rectable Top, Left + case SUMEM_SCISSORBR: // Scissor Rectable Bottom, Right + case SUMEM_SCISSOROFFSET: // Scissor Offset + SetScissor(bp); + break; + case SUMEM_LINEPTWIDTH: // Line Width + SetLineWidth(bp); + break; + case SUMEM_ZMODE: // Depth Control + PRIM_LOG("zmode: test=%d, func=%d, upd=%d", sumem.zmode.testenable, sumem.zmode.func, + sumem.zmode.updateenable); + SetDepthMode(bp); + break; + case SUMEM_BLENDMODE: // Blending Control + { + if (bp.changes & 0xFFFF) + { + PRIM_LOG("blendmode: en=%d, open=%d, colupd=%d, alphaupd=%d, dst=%d, src=%d, sub=%d, mode=%d", + sumem.blendmode.blendenable, sumem.blendmode.logicopenable, sumem.blendmode.colorupdate, sumem.blendmode.alphaupdate, + sumem.blendmode.dstfactor, sumem.blendmode.srcfactor, sumem.blendmode.subtract, sumem.blendmode.logicmode); + // Set LogicOp Blending Mode + if (bp.changes & 2) + { + SETSTAT(stats.logicOpMode, sumem.blendmode.logicopenable != 0 ? sumem.blendmode.logicmode : stats.logicOpMode); + SetLogicOpMode(bp); + } + // Set Dithering Mode + if (bp.changes & 4) + { + SETSTAT(stats.dither, sumem.blendmode.dither); + SetDitherMode(bp); + } + // Set Blending Mode + if (bp.changes & 0xFE1) + { + SETSTAT(stats.srcFactor, sumem.blendmode.srcfactor); + SETSTAT(stats.dstFactor, sumem.blendmode.dstfactor); + SetBlendMode(bp); + } + // Set Color Mask + if (bp.changes & 0x18) + { + SETSTAT(stats.alphaUpdate, sumem.blendmode.alphaupdate); + SETSTAT(stats.colorUpdate, sumem.blendmode.colorupdate); + SetColorMask(bp); + } + } + break; + } + case SUMEM_CONSTANTALPHA: // Set Destination Alpha + { + PRIM_LOG("constalpha: alp=%d, en=%d", sumem.dstalpha.alpha, sumem.dstalpha.enable); + SETSTAT(stats.dstAlphaEnable, sumem.dstalpha.enable); + SETSTAT_UINT(stats.dstAlpha, sumem.dstalpha.alpha); + PixelShaderManager::SetDestAlpha(sumem.dstalpha); + break; + } + // This is called when the game is done drawing the new frame (eg: like in DX: Begin(); Draw(); End();) + case SUMEM_SETDRAWDONE: + switch (bp.newvalue & 0xFF) + { + case 0x02: + g_VideoInitialize.pSetPEFinish(); // may generate interrupt + DEBUG_LOG(VIDEO, "GXSetDrawDone SetPEFinish (value: 0x%02X)", (bp.newvalue & 0xFFFF)); + break; + + default: + WARN_LOG(VIDEO, "GXSetDrawDone ??? (value 0x%02X)", (bp.newvalue & 0xFFFF)); + break; + } + break; + case SUMEM_PE_TOKEN_ID: // Pixel Engine Token ID + g_VideoInitialize.pSetPEToken(static_cast(bp.newvalue & 0xFFFF), FALSE); + DEBUG_LOG(VIDEO, "SetPEToken 0x%04x", (bp.newvalue & 0xFFFF)); + break; + case SUMEM_PE_TOKEN_INT_ID: // Pixel Engine Interrupt Token ID + g_VideoInitialize.pSetPEToken(static_cast(bp.newvalue & 0xFFFF), TRUE); + DEBUG_LOG(VIDEO, "SetPEToken + INT 0x%04x", (bp.newvalue & 0xFFFF)); + break; + // ------------------------ + // EFB copy command. This copies a rectangle from the EFB to either RAM in a texture format or to XFB as YUYV. + // It can also optionally clear the EFB while copying from it. To emulate this, we of course copy first and clear afterwards. + case SUMEM_TRIGGER_EFB_COPY: // Copy EFB Region or Render to the XFB or Clear the screen. + { + DVSTARTSUBPROFILE("LoadSUReg:swap"); + // The bottom right is within the rectangle + // The values in sumem.copyTexSrcXY and sumem.copyTexSrcWH are updated in case 0x49 and 0x4a in this function + TRectangle rc = { + (int)(sumem.copyTexSrcXY.x), + (int)(sumem.copyTexSrcXY.y), + (int)((sumem.copyTexSrcXY.x + sumem.copyTexSrcWH.x + 1)), + (int)((sumem.copyTexSrcXY.y + sumem.copyTexSrcWH.y + 1)) + }; + + float MValueX = GetRendererTargetScaleX(); + float MValueY = GetRendererTargetScaleY(); + + // Need another rc here to get it to scale. + // Here the bottom right is the out of the rectangle. + TRectangle multirc = { + (int)(sumem.copyTexSrcXY.x * MValueX), + (int)(sumem.copyTexSrcXY.y * MValueY), + (int)((sumem.copyTexSrcXY.x * MValueX + (sumem.copyTexSrcWH.x + 1) * MValueX)), + (int)((sumem.copyTexSrcXY.y * MValueY + (sumem.copyTexSrcWH.y + 1) * MValueY)) + }; + UPE_Copy PE_copy; + PE_copy.Hex = sumem.triggerEFBCopy; + + // Check if we are to copy from the EFB or draw to the XFB + if (PE_copy.copy_to_xfb == 0) + { + if (GetConfig(CONFIG_SHOWEFBREGIONS)) + stats.efb_regions.push_back(rc); + + CopyEFB(bp, rc, sumem.copyTexDest << 5, + sumem.zcontrol.pixel_format == PIXELFMT_Z24, + PE_copy.intensity_fmt > 0, + ((PE_copy.target_pixel_format / 2) + ((PE_copy.target_pixel_format & 1) * 8)), + PE_copy.half_scale > 0); + } + else + { + // the number of lines copied is determined by the y scale * source efb height + const float yScale = sumem.dispcopyyscale / 256.0f; + const float xfbLines = ((sumem.copyTexSrcWH.y + 1.0f) * yScale); + RenderToXFB(bp, multirc, yScale, xfbLines, + Memory_GetPtr(sumem.copyTexDest << 5), + sumem.copyMipMapStrideChannels << 4, + (u32)ceil(xfbLines)); + } + + // Clear the picture after it's done and submitted, to prepare for the next picture + if (PE_copy.clear) + ClearScreen(bp, multirc); + + RestoreRenderState(bp); + + break; + } + case SUMEM_LOADTLUT0: // Load a Texture Look Up Table + case SUMEM_LOADTLUT1: + { + DVSTARTSUBPROFILE("LoadSUReg:GXLoadTlut"); + + u32 tlutTMemAddr = (bp.newvalue & 0x3FF) << 9; + u32 tlutXferCount = (bp.newvalue & 0x1FFC00) >> 5; + + u8 *ptr = 0; + + // TODO - figure out a cleaner way. + if (GetConfig(CONFIG_ISWII)) + ptr = GetPointer(sumem.tlutXferSrc << 5); + else + ptr = GetPointer((sumem.tlutXferSrc & 0xFFFFF) << 5); + + if (ptr) + memcpy_gc(texMem + tlutTMemAddr, ptr, tlutXferCount); + else + PanicAlert("Invalid palette pointer %08x %08x %08x", sumem.tlutXferSrc, sumem.tlutXferSrc << 5, (sumem.tlutXferSrc & 0xFFFFF)<< 5); + + // 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; + } + case SUMEM_FOGRANGE: // Fog Settings Control + case SUMEM_FOGPARAM0: + case SUMEM_FOGBMAGNITUDE: + case SUMEM_FOGBEXPONENT: + case SUMEM_FOGPARAM3: + if(!GetConfig(CONFIG_DISABLEFOG)) + PixelShaderManager::SetFogParamChanged(); + break; + case SUMEM_FOGCOLOR: // Fog Color + PixelShaderManager::SetFogColorChanged(); + break; + case SUMEM_ALPHACOMPARE: // Compare Alpha Values + PRIM_LOG("alphacmp: ref0=%d, ref1=%d, comp0=%d, comp1=%d, logic=%d", sumem.alphaFunc.ref0, + sumem.alphaFunc.ref1, sumem.alphaFunc.comp0, sumem.alphaFunc.comp1, sumem.alphaFunc.logic); + PixelShaderManager::SetAlpha(sumem.alphaFunc); + break; + case SUMEM_BIAS: // BIAS + PRIM_LOG("ztex bias=0x%x", sumem.ztex1.bias); + PixelShaderManager::SetZTextureBias(sumem.ztex1.bias); + break; + case SUMEM_ZTEX2: // Z Texture type + { + if (bp.changes & 3) + PixelShaderManager::SetZTextureTypeChanged(); + #if defined(_DEBUG) || defined(DEBUGFAST) + const char* pzop[] = {"DISABLE", "ADD", "REPLACE", "?"}; + const char* pztype[] = {"Z8", "Z16", "Z24", "?"}; + PRIM_LOG("ztex op=%s, type=%s", pzop[sumem.ztex2.op], pztype[sumem.ztex2.type]); + #endif + break; + } + // ---------------------------------- + // Display Copy Filtering Control + // Fields: Destination, Frame2Field, Gamma, Source + // TODO: We might have to implement the gamma one, some games might need this, if they are too dark to see. + // ---------------------------------- + case SUMEM_DISPLAYCOPYFILER: + case SUMEM_DISPLAYCOPYFILER+1: + case SUMEM_DISPLAYCOPYFILER+2: + case SUMEM_DISPLAYCOPYFILER+3: + case SUMEM_COPYFILTER0: //GXSetCopyFilter + case SUMEM_COPYFILTER1: + break; + case SUMEM_FIELDMASK: // Interlacing Control + case SUMEM_FIELDMODE: + SetInterlacingMode(bp); + break; + // --------------------------------------------------- + // Debugging/Profiling info, we don't care about them + // --------------------------------------------------- + case SUMEM_CLOCK0: // Some Clock + case SUMEM_CLOCK1: // Some Clock + case SUMEM_SU_COUNTER: // Pixel or Poly Count + case SUMEM_RAS_COUNTER: // Sound Count of something in the Texture Units + case SUMEM_SETGPMETRIC: // Set the Graphic Processor Metric + break; + // ---------------- + // EFB Copy config + // ---------------- + case SUMEM_EFB_TL: // EFB Source Rect. Top, Left + case SUMEM_EFB_BR: // EFB Source Rect. Bottom, Right (w, h - 1) + case SUMEM_EFB_ADDR: // EFB Target Address + break; + // -------------- + // Clear Config + // -------------- + case SUMEM_CLEAR_AR: // Alpha and Red Components + case SUMEM_CLEAR_GB: // Green and Blue Components + case SUMEM_CLEAR_Z: // Z Components (24-bit Zbuffer) + break; + // ------------------------- + // Culling Occulsion, we don't support this + // let's hope not many games use bboxes.. + // TODO(ector): add something that watches bboxes + // ------------------------- + case SUMEM_CLEARBBOX1: + case SUMEM_CLEARBBOX2: + break; + case SUMEM_ZCOMPARE: // Set the Z-Compare + case SUMEM_TEXINVALIDATE: // Used, if game has manual control the Texture Cache, which we don't allow + case SUMEM_MIPMAP_STRIDE: // MipMap Stride Channel + case SUMEM_COPYYSCALE: // Display Copy Y Scale + case SUMEM_IREF: /* 24 RID + 21 BC3 - Ind. Tex Stage 3 NTexCoord + 18 BI3 - Ind. Tex Stage 3 NTexMap + 15 BC2 - Ind. Tex Stage 2 NTexCoord + 12 BI2 - Ind. Tex Stage 2 NTexMap + 9 BC1 - Ind. Tex Stage 1 NTexCoord + 6 BI1 - Ind. Tex Stage 1 NTexMap + 3 BC0 - Ind. Tex Stage 0 NTexCoord + 0 BI0 - Ind. Tex Stage 0 NTexMap */ + break; + case SUMEM_TEV_KSEL: // Texture Environment Swap Mode Table 0 + case SUMEM_TEV_KSEL+1:// Texture Environment Swap Mode Table 1 + case SUMEM_TEV_KSEL+2:// Texture Environment Swap Mode Table 2 + case SUMEM_TEV_KSEL+3:// Texture Environment Swap Mode Table 3 + case SUMEM_TEV_KSEL+4:// Texture Environment Swap Mode Table 4 + case SUMEM_TEV_KSEL+5:// Texture Environment Swap Mode Table 5 + case SUMEM_TEV_KSEL+6:// Texture Environment Swap Mode Table 6 + case SUMEM_TEV_KSEL+7:// Texture Environment Swap Mode Table 7 + break; + case SUMEM_BP_MASK: // This Register can be used to limit to which bits of BP registers is actually written to. the mask is + // only valid for the next BP command, and will reset itself. + case SUMEM_IND_IMASK: // Index Mask ? + break; + case SUMEM_UNKNOWN: // This is always set to 0xF at boot of any game, so this sounds like a useless reg + if (bp.newvalue != 0x0F) + PanicAlert("Unknown is not 0xF! val = 0x%08x", bp.newvalue); + break; + + // Cases added due to: http://code.google.com/p/dolphin-emu/issues/detail?id=360#c90 + // Are these related to BBox? + case SUMEM_UNKNOWN1: + case SUMEM_UNKNOWN2: + case SUMEM_UNKNOWN3: + case SUMEM_UNKNOWN4: + break; + // ------------------------------------------------ + // On Default, we try to look for other things + // before we give up and say its an unknown opcode + // ------------------------------------------------ + default: + switch (bp.address & 0xFC) // Texture sampler filter + { + // ------------------------- + // Texture Environment Order + // ------------------------- + case SUMEM_TREF: + case SUMEM_TREF+1: + case SUMEM_TREF+2: + case SUMEM_TREF+3: + case SUMEM_TREF+4: + case SUMEM_TREF+5: + case SUMEM_TREF+6: + case SUMEM_TREF+7: + break; + // ---------------------- + // Set wrap size + // ---------------------- + case SUMEM_SU_SSIZE: + case SUMEM_SU_TSIZE: + case SUMEM_SU_SSIZE+2: + case SUMEM_SU_TSIZE+2: + case SUMEM_SU_SSIZE+4: + case SUMEM_SU_TSIZE+4: + case SUMEM_SU_SSIZE+6: + case SUMEM_SU_TSIZE+6: + case SUMEM_SU_SSIZE+8: + case SUMEM_SU_TSIZE+8: + case SUMEM_SU_SSIZE+10: + case SUMEM_SU_TSIZE+10: + case SUMEM_SU_SSIZE+12: + case SUMEM_SU_TSIZE+12: + case SUMEM_SU_SSIZE+14: + case SUMEM_SU_TSIZE+14: + PixelShaderManager::SetTexCoordChanged((bp.address - SUMEM_SU_SSIZE) >> 1); + break; + // ------------------------ + // SUMEM_TX_SETMODE0 - (Texture lookup and filtering mode) LOD/BIAS Clamp, MaxAnsio, LODBIAS, DiagLoad, Min Filter, Mag Filter, Wrap T, S + // SUMEM_TX_SETMODE1 - (LOD Stuff) - Max LOD, Min LOD + // ------------------------ + case SUMEM_TX_SETMODE0: // (0x90 for linear) + case SUMEM_TX_SETMODE0+1: + case SUMEM_TX_SETMODE0+2: + case SUMEM_TX_SETMODE0+3: + case SUMEM_TX_SETMODE1: + case SUMEM_TX_SETMODE1+1: + case SUMEM_TX_SETMODE1+2: + case SUMEM_TX_SETMODE1+3: + case SUMEM_TX_SETMODE0_4: + case SUMEM_TX_SETMODE0_4+1: + case SUMEM_TX_SETMODE0_4+2: + case SUMEM_TX_SETMODE0_4+3: + case SUMEM_TX_SETMODE1_4: + case SUMEM_TX_SETMODE1_4+1: + case SUMEM_TX_SETMODE1_4+2: + case SUMEM_TX_SETMODE1_4+3: + SetSamplerState(bp); + break; + // -------------------------------------------- + // SUMEM_TX_SETIMAGE0 - Texture width, height, format + // SUMEM_TX_SETIMAGE1 - even LOD address in TMEM - Image Type, Cache Height, Cache Width, TMEM Offset + // SUMEM_TX_SETIMAGE2 - odd LOD address in TMEM - Cache Height, Cache Width, TMEM Offset + // SUMEM_TX_SETIMAGE3 - Address of Texture in main memory + // -------------------------------------------- + case SUMEM_TX_SETIMAGE0: + case SUMEM_TX_SETIMAGE0+1: + case SUMEM_TX_SETIMAGE0+2: + case SUMEM_TX_SETIMAGE0+3: + case SUMEM_TX_SETIMAGE0_4: + case SUMEM_TX_SETIMAGE0_4+1: + case SUMEM_TX_SETIMAGE0_4+2: + case SUMEM_TX_SETIMAGE0_4+3: + case SUMEM_TX_SETIMAGE1: + case SUMEM_TX_SETIMAGE1+1: + case SUMEM_TX_SETIMAGE1+2: + case SUMEM_TX_SETIMAGE1+3: + case SUMEM_TX_SETIMAGE1_4: + case SUMEM_TX_SETIMAGE1_4+1: + case SUMEM_TX_SETIMAGE1_4+2: + case SUMEM_TX_SETIMAGE1_4+3: + case SUMEM_TX_SETIMAGE2: + case SUMEM_TX_SETIMAGE2+1: + case SUMEM_TX_SETIMAGE2+2: + case SUMEM_TX_SETIMAGE2+3: + case SUMEM_TX_SETIMAGE2_4: + case SUMEM_TX_SETIMAGE2_4+1: + case SUMEM_TX_SETIMAGE2_4+2: + case SUMEM_TX_SETIMAGE2_4+3: + case SUMEM_TX_SETIMAGE3: + case SUMEM_TX_SETIMAGE3+1: + case SUMEM_TX_SETIMAGE3+2: + case SUMEM_TX_SETIMAGE3+3: + case SUMEM_TX_SETIMAGE3_4: + case SUMEM_TX_SETIMAGE3_4+1: + case SUMEM_TX_SETIMAGE3_4+2: + case SUMEM_TX_SETIMAGE3_4+3: + break; + // ------------------------------- + // Set a TLUT + // SUMEM_TX_SETTLUT - Format, TMEM Offset (offset of TLUT from start of TMEM high bank > > 5) + // ------------------------------- + case SUMEM_TX_SETTLUT: + case SUMEM_TX_SETTLUT+1: + case SUMEM_TX_SETTLUT+2: + case SUMEM_TX_SETTLUT+3: + case SUMEM_TX_SETLUT_4: + case SUMEM_TX_SETLUT_4+1: + case SUMEM_TX_SETLUT_4+2: + case SUMEM_TX_SETLUT_4+3: + break; + // --------------------------------------------------- + // Set the TEV Color + // --------------------------------------------------- + case SUMEM_TEV_REGISTER_L: // Reg 1 + case SUMEM_TEV_REGISTER_H: + case SUMEM_TEV_REGISTER_L+2: // Reg 2 + case SUMEM_TEV_REGISTER_H+2: + case SUMEM_TEV_REGISTER_L+4: // Reg 3 + case SUMEM_TEV_REGISTER_H+4: + case SUMEM_TEV_REGISTER_L+6: // Reg 4 + case SUMEM_TEV_REGISTER_H+6: + { + if (bp.address & 1) + { + // don't compare with changes! + int num = (bp.address >> 1 ) & 0x3; + PixelShaderManager::SetColorChanged(sumem.tevregs[num].high.type, num); + } + break; + } + // ------------------------------------------------ + // On Default, we try to look for other things + // before we give up and say its an unknown opcode + // again ... + // ------------------------------------------------ + default: + switch (bp.address & 0xF0) + { + // -------------- + // Indirect Tev + // -------------- + case SUMEM_IND_CMD: + case SUMEM_IND_CMD+1: + case SUMEM_IND_CMD+2: + case SUMEM_IND_CMD+3: + case SUMEM_IND_CMD+4: + case SUMEM_IND_CMD+5: + case SUMEM_IND_CMD+6: + case SUMEM_IND_CMD+7: + case SUMEM_IND_CMD+8: + case SUMEM_IND_CMD+9: + case SUMEM_IND_CMD+10: + case SUMEM_IND_CMD+11: + case SUMEM_IND_CMD+12: + case SUMEM_IND_CMD+13: + case SUMEM_IND_CMD+14: + case SUMEM_IND_CMD+15: + break; + // -------------------------------------------------- + // Set Color/Alpha of a Tev + // SUMEM_TEV_COLOR_ENV - Dest, Shift, Clamp, Sub, Bias, Sel A, Sel B, Sel C, Sel D + // SUMEM_TEV_ALPHA_ENV - Dest, Shift, Clamp, Sub, Bias, Sel A, Sel B, Sel C, Sel D, T Swap, R Swap + // -------------------------------------------------- + case SUMEM_TEV_COLOR_ENV: // Texture Environment 1 + case SUMEM_TEV_ALPHA_ENV: + case SUMEM_TEV_COLOR_ENV+2: // Texture Environment 2 + case SUMEM_TEV_ALPHA_ENV+2: + case SUMEM_TEV_COLOR_ENV+4: // Texture Environment 3 + case SUMEM_TEV_ALPHA_ENV+4: + case SUMEM_TEV_COLOR_ENV+8: // Texture Environment 4 + case SUMEM_TEV_ALPHA_ENV+8: + case SUMEM_TEV_COLOR_ENV+10: // Texture Environment 5 + case SUMEM_TEV_ALPHA_ENV+10: + case SUMEM_TEV_COLOR_ENV+12: // Texture Environment 6 + case SUMEM_TEV_ALPHA_ENV+12: + case SUMEM_TEV_COLOR_ENV+14: // Texture Environment 7 + case SUMEM_TEV_ALPHA_ENV+14: + case SUMEM_TEV_COLOR_ENV+16: // Texture Environment 8 + case SUMEM_TEV_ALPHA_ENV+16: + case SUMEM_TEV_COLOR_ENV+18: // Texture Environment 9 + case SUMEM_TEV_ALPHA_ENV+18: + case SUMEM_TEV_COLOR_ENV+20: // Texture Environment 10 + case SUMEM_TEV_ALPHA_ENV+20: + case SUMEM_TEV_COLOR_ENV+22: // Texture Environment 11 + case SUMEM_TEV_ALPHA_ENV+22: + case SUMEM_TEV_COLOR_ENV+24: // Texture Environment 12 + case SUMEM_TEV_ALPHA_ENV+24: + case SUMEM_TEV_COLOR_ENV+26: // Texture Environment 13 + case SUMEM_TEV_ALPHA_ENV+26: + case SUMEM_TEV_COLOR_ENV+28: // Texture Environment 14 + case SUMEM_TEV_ALPHA_ENV+28: + case SUMEM_TEV_COLOR_ENV+30: // Texture Environment 15 + case SUMEM_TEV_ALPHA_ENV+30: + case SUMEM_TEV_COLOR_ENV+32: // Texture Environment 16 + case SUMEM_TEV_ALPHA_ENV+32: + break; + default: + WARN_LOG(VIDEO, "Unknown Bypass opcode: address = 0x%08x value = 0x%08x", bp.address, bp.newvalue); + break; + } + + } + + } +} + diff --git a/Source/Core/VideoCommon/Src/SUStructs.h b/Source/Core/VideoCommon/Src/SUStructs.h new file mode 100644 index 0000000000..f9ac7a21e5 --- /dev/null +++ b/Source/Core/VideoCommon/Src/SUStructs.h @@ -0,0 +1,27 @@ +// Copyright (C) 2003-2009 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _SUSTRUCTS_H_ +#define _SUSTRUCTS_H_ + +#include "SUMemory.h" + +void SUInit(); +void LoadSUReg(u32 value0); +void SUReload(); + +#endif // _SUSTRUCTS_H_ diff --git a/Source/Plugins/Plugin_VideoDX9/Src/SUFunctions.cpp b/Source/Plugins/Plugin_VideoDX9/Src/SUFunctions.cpp new file mode 100644 index 0000000000..f827edb918 --- /dev/null +++ b/Source/Plugins/Plugin_VideoDX9/Src/SUFunctions.cpp @@ -0,0 +1,336 @@ +// Copyright (C) 2003-2009 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "SUFunctions.h" +#include "D3DBase.h" +#include "Config.h" +#include "Common.h" +#include "TextureCache.h" +#include "VertexManager.h" +#include "VertexShaderManager.h" +#include "Utils.h" + + +bool textureChanged[8]; + +const bool renderFog = false; + +using namespace D3D; + +// State translation lookup tables +static const D3DBLEND d3dSrcFactors[8] = +{ + D3DBLEND_ZERO, + D3DBLEND_ONE, + D3DBLEND_DESTCOLOR, + D3DBLEND_INVDESTCOLOR, + D3DBLEND_SRCALPHA, + D3DBLEND_INVSRCALPHA, + D3DBLEND_DESTALPHA, + D3DBLEND_INVDESTALPHA +}; + +static const D3DBLEND d3dDestFactors[8] = +{ + D3DBLEND_ZERO, + D3DBLEND_ONE, + D3DBLEND_SRCCOLOR, + D3DBLEND_INVSRCCOLOR, + D3DBLEND_SRCALPHA, + D3DBLEND_INVSRCALPHA, + D3DBLEND_DESTALPHA, + D3DBLEND_INVDESTALPHA +}; + +static const D3DCULL d3dCullModes[4] = +{ + D3DCULL_NONE, + D3DCULL_CCW, + D3DCULL_CW, + D3DCULL_CCW +}; + +static const D3DCMPFUNC d3dCmpFuncs[8] = +{ + D3DCMP_NEVER, + D3DCMP_LESS, + D3DCMP_EQUAL, + D3DCMP_LESSEQUAL, + D3DCMP_GREATER, + D3DCMP_NOTEQUAL, + D3DCMP_GREATEREQUAL, + D3DCMP_ALWAYS +}; + +static const D3DTEXTUREFILTERTYPE d3dMipFilters[4] = +{ + D3DTEXF_NONE, + D3DTEXF_POINT, + D3DTEXF_ANISOTROPIC, + D3DTEXF_LINEAR, //reserved +}; + +static const D3DTEXTUREADDRESS d3dClamps[4] = +{ + D3DTADDRESS_CLAMP, + D3DTADDRESS_WRAP, + D3DTADDRESS_MIRROR, + D3DTADDRESS_WRAP //reserved +}; + +namespace SUFunctions +{ + +void FlushPipeline() +{ + VertexManager::Flush(); +} + +void SetGenerationMode(const BPCommand &bp) +{ + // dev->SetRenderState(D3DRS_CULLMODE, d3dCullModes[sumem.genMode.cullmode]); + Renderer::SetRenderState(D3DRS_CULLMODE, d3dCullModes[sumem.genMode.cullmode]); + + if (sumem.genMode.cullmode == 3) + { + // dev->SetRenderState(D3DRS_COLORWRITEENABLE, 0); + Renderer::SetRenderState(D3DRS_COLORWRITEENABLE, 0); + } + else + { + DWORD write = 0; + if (sumem.blendmode.alphaupdate) + write = D3DCOLORWRITEENABLE_ALPHA; + if (sumem.blendmode.colorupdate) + write |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE; + + // dev->SetRenderState(D3DRS_COLORWRITEENABLE, write); + Renderer::SetRenderState(D3DRS_COLORWRITEENABLE, write); + } +} + +void SetScissor(const BPCommand &bp) +{ + Renderer::SetScissorRect(); +} +void SetLineWidth(const BPCommand &bp) +{ + // We can't change line width in D3D unless we use ID3DXLine + float psize = float(sumem.lineptwidth.pointsize) * 6.0f; + Renderer::SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&psize)); +} +void SetDepthMode(const BPCommand &bp) +{ + if (sumem.zmode.testenable) + { + // dev->SetRenderState(D3DRS_ZENABLE, TRUE); + // dev->SetRenderState(D3DRS_ZWRITEENABLE, sumem.zmode.updateenable); + // dev->SetRenderState(D3DRS_ZFUNC,d3dCmpFuncs[sumem.zmode.func]); + + Renderer::SetRenderState(D3DRS_ZENABLE, TRUE); + Renderer::SetRenderState(D3DRS_ZWRITEENABLE, sumem.zmode.updateenable); + Renderer::SetRenderState(D3DRS_ZFUNC, d3dCmpFuncs[sumem.zmode.func]); + } + else + { + // if the test is disabled write is disabled too + // dev->SetRenderState(D3DRS_ZENABLE, FALSE); + // dev->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); + + Renderer::SetRenderState(D3DRS_ZENABLE, FALSE); + Renderer::SetRenderState(D3DRS_ZWRITEENABLE, FALSE); + } + + //if (!sumem.zmode.updateenable) + // Renderer::SetRenderMode(Renderer::RM_Normal); + +} +void SetBlendMode(const BPCommand &bp) +{ + if (bp.changes & 1) + Renderer::SetRenderState(D3DRS_ALPHABLENDENABLE, sumem.blendmode.blendenable); + + D3DBLEND src = d3dSrcFactors[sumem.blendmode.srcfactor]; + D3DBLEND dst = d3dDestFactors[sumem.blendmode.dstfactor]; + + if (bp.changes & 0x700) + Renderer::SetRenderState(D3DRS_SRCBLEND, src); + + if (bp.changes & 0xE0) { + if (!sumem.blendmode.subtract) + { + Renderer::SetRenderState(D3DRS_DESTBLEND, dst); + } + else + { + Renderer::SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + } + } + if (bp.changes & 0x800) + { + if (sumem.blendmode.subtract) + { + Renderer::SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); + Renderer::SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + } + else + { + Renderer::SetRenderState(D3DRS_SRCBLEND, src); + Renderer::SetRenderState(D3DRS_DESTBLEND, dst); + } + + Renderer::SetRenderState(D3DRS_BLENDOP, sumem.blendmode.subtract ? D3DBLENDOP_SUBTRACT : D3DBLENDOP_ADD); + } +} +void SetDitherMode(const BPCommand &bp) +{ + Renderer::SetRenderState(D3DRS_DITHERENABLE,sumem.blendmode.dither); +} +void SetLogicOpMode(const BPCommand &bp) +{ + // Logic op blending. D3D can't do this but can fake some modes. +} +void SetColorMask(const BPCommand &bp) +{ + DWORD write = 0; + if (sumem.blendmode.alphaupdate) + write = D3DCOLORWRITEENABLE_ALPHA; + if (sumem.blendmode.colorupdate) + write |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE; + + Renderer::SetRenderState(D3DRS_COLORWRITEENABLE, write); +} +float GetRendererTargetScaleX() +{ + return Renderer::GetXScale(); +} +float GetRendererTargetScaleY() +{ + return Renderer::GetYScale(); +} +void CopyEFB(const BPCommand &bp, const TRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 ©fmt, const bool &scaleByHalf) +{ + RECT rec = { rc.left, rc.top, rc.right, rc.bottom }; + TextureCache::CopyEFBToRenderTarget(sumem.copyTexDest<<5, &rec); +} + +void RenderToXFB(const BPCommand &bp, const TRectangle &multirc, const float &yScale, const float &xfbLines, u8* pXFB, const u32 &dstWidth, const u32 &dstHeight) +{ + Renderer::SwapBuffers(); + PRIM_LOG("Renderer::SwapBuffers()"); + g_VideoInitialize.pCopiedToXFB(); +} +void ClearScreen(const BPCommand &bp, const TRectangle &multirc) +{ + // 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 + + VertexShaderManager::SetViewportChanged(); + + // Since clear operations use the source rectangle, we have to do + // regular renders + DWORD clearflags = 0; + D3DCOLOR col = 0; + float clearZ = 0; + + if (sumem.blendmode.colorupdate || sumem.blendmode.alphaupdate) + { + if (sumem.blendmode.colorupdate || sumem.blendmode.alphaupdate) + col = (sumem.clearcolorAR << 16) | sumem.clearcolorGB; + // clearflags |= D3DCLEAR_TARGET; set to break animal crossing :p + } + + // clear z-buffer + if (sumem.zmode.updateenable) + { + clearZ = (float)(sumem.clearZValue & 0xFFFFFF) / float(0xFFFFFF); + if (clearZ > 1.0f) clearZ = 1.0f; + if (clearZ < 0.0f) clearZ = 0.0f; + clearflags |= D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL; + } + + D3D::dev->Clear(0, NULL, clearflags, col, clearZ, 0); +} + +void RestoreRenderState(const BPCommand &bp) +{ + //Renderer::SetRenderMode(Renderer::RM_Normal); +} + +bool GetConfig(const int &type) +{ + switch (type) + { + case CONFIG_ISWII: + return g_VideoInitialize.bWii; + case CONFIG_DISABLEFOG: + return false; + case CONFIG_SHOWEFBREGIONS: + return false; + default: + PanicAlert("GetConfig Error: Unknown Config Type!"); + return false; + } +} +u8 *GetPointer(const u32 &address) +{ + return g_VideoInitialize.pGetMemoryPointer(address); +} +void SetSamplerState(const BPCommand &bp) +{ + FourTexUnits &tex = sumem.tex[(bp.address & 0xE0) == 0xA0]; + int stage = (bp.address & 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 ((bp.address & 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); +} +void SetInterlacingMode(const BPCommand &bp) +{ + // TODO +} +}; \ No newline at end of file diff --git a/Source/Plugins/Plugin_VideoOGL/Src/SUFunctions.cpp b/Source/Plugins/Plugin_VideoOGL/Src/SUFunctions.cpp new file mode 100644 index 0000000000..b9e52ff521 --- /dev/null +++ b/Source/Plugins/Plugin_VideoOGL/Src/SUFunctions.cpp @@ -0,0 +1,226 @@ +// Copyright (C) 2003-2009 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "SUFunctions.h" +#include "Globals.h" +#include "Profiler.h" +#include "Config.h" +#include "VertexManager.h" +#include "Render.h" +#include "TextureMngr.h" +#include "TextureConverter.h" +#include "VertexShaderManager.h" +#include "XFB.h" +#include "main.h" + +namespace SUFunctions +{ +// ---------------------------------------------- +// State translation lookup tables +// Reference: Yet Another Gamecube Documentation +// ---------------------------------------------- + +static const GLenum glCmpFuncs[8] = { + GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS +}; + +static const GLenum glLogicOpCodes[16] = { + GL_CLEAR, GL_AND, GL_AND_REVERSE, GL_COPY, GL_AND_INVERTED, GL_NOOP, GL_XOR, + GL_OR, GL_NOR, GL_EQUIV, GL_INVERT, GL_OR_REVERSE, GL_COPY_INVERTED, GL_OR_INVERTED, GL_NAND, GL_SET +}; + +void FlushPipeline() +{ + VertexManager::Flush(); +} +void SetGenerationMode(const BPCommand &bp) +{ + // none, ccw, cw, ccw + if (sumem.genMode.cullmode > 0) + { + glEnable(GL_CULL_FACE); + glFrontFace(sumem.genMode.cullmode == 2 ? GL_CCW : GL_CW); + } + else + glDisable(GL_CULL_FACE); +} + + +void SetScissor(const BPCommand &bp) +{ + if (!Renderer::SetScissorRect()) + if (bp.address == SUMEM_SCISSORBR) + ERROR_LOG(VIDEO, "bad scissor!"); +} +void SetLineWidth(const BPCommand &bp) +{ + float fratio = xfregs.rawViewport[0] != 0 ? ((float)Renderer::GetTargetWidth() / EFB_WIDTH) : 1.0f; + if (sumem.lineptwidth.linesize > 0) + glLineWidth((float)sumem.lineptwidth.linesize * fratio / 6.0f); // scale by ratio of widths + if (sumem.lineptwidth.pointsize > 0) + glPointSize((float)sumem.lineptwidth.pointsize * fratio / 6.0f); +} +void SetDepthMode(const BPCommand &bp) +{ + if (sumem.zmode.testenable) + { + glEnable(GL_DEPTH_TEST); + glDepthMask(sumem.zmode.updateenable ? GL_TRUE : GL_FALSE); + glDepthFunc(glCmpFuncs[sumem.zmode.func]); + } + else + { + // if the test is disabled write is disabled too + glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + } +} +void SetBlendMode(const BPCommand &bp) +{ + Renderer::SetBlendMode(false); +} +void SetDitherMode(const BPCommand &bp) +{ + if (sumem.blendmode.dither) + glEnable(GL_DITHER); + else + glDisable(GL_DITHER); +} +void SetLogicOpMode(const BPCommand &bp) +{ + if (sumem.blendmode.logicopenable) + { + glEnable(GL_COLOR_LOGIC_OP); + glLogicOp(glLogicOpCodes[sumem.blendmode.logicmode]); + } + else + glDisable(GL_COLOR_LOGIC_OP); +} +void SetColorMask(const BPCommand &bp) +{ + Renderer::SetColorMask(); +} +float GetRendererTargetScaleX() +{ + return Renderer::GetTargetScaleX(); +} +float GetRendererTargetScaleY() +{ + return Renderer::GetTargetScaleY(); +} +void CopyEFB(const BPCommand &bp, const TRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 ©fmt, const bool &scaleByHalf) +{ + // sumem.zcontrol.pixel_format to PIXELFMT_Z24 is when the game wants to copy from ZBuffer (Zbuffer uses 24-bit Format) + if (!g_Config.bEFBCopyDisable) + if (g_Config.bCopyEFBToRAM) // To RAM + TextureConverter::EncodeToRam(address, fromZBuffer, isIntensityFmt, copyfmt, scaleByHalf, rc); + else // To OGL Texture + TextureMngr::CopyRenderTargetToTexture(address, fromZBuffer, isIntensityFmt, copyfmt, scaleByHalf, rc); +} + +void RenderToXFB(const BPCommand &bp, const TRectangle &multirc, const float &yScale, const float &xfbLines, u8* pXFB, const u32 &dstWidth, const u32 &dstHeight) +{ + // EFB to XFB + if (g_Config.bUseXFB) + { + + XFB_Write(pXFB, multirc, dstWidth, dstHeight); + // FIXME: we draw XFB from here in DC mode. + // Bad hack since we can have multiple EFB to XFB copy before a draw. + // Plus we should use width and height from VI regs (see VI->Update()). + // Dixit donkopunchstania for the info. + //DebugLog("(EFB to XFB->XFB_Draw): ptr: %08x | %ix%i", (u32)pXFB, dstWidth, dstHeight); + if (g_VideoInitialize.bUseDualCore) + XFB_Draw(pXFB, dstWidth, dstHeight, 0); + } + else + { + // Hm, we need to compensate for the fact that the copy may be bigger than what is displayed. + // Seen in Spartan Warrior. Not sure how to deal with it yet. + Renderer::Swap(multirc); + } + g_VideoInitialize.pCopiedToXFB(); +} +void ClearScreen(const BPCommand &bp, const TRectangle &multirc) +{ + // Update the view port for clearing the picture + glViewport(0, 0, Renderer::GetTargetWidth(), Renderer::GetTargetHeight()); + + // Always set the scissor in case it was set by the game and has not been reset + glScissor(multirc.left, (Renderer::GetTargetHeight() - multirc.bottom), + (multirc.right - multirc.left), (multirc.bottom - multirc.top)); + // --------------------------- + + VertexShaderManager::SetViewportChanged(); + + // Since clear operations use the source rectangle, we have to do + // regular renders (glClear clears the entire buffer) + if (sumem.blendmode.colorupdate || sumem.blendmode.alphaupdate || sumem.zmode.updateenable) + { + GLbitfield bits = 0; + if (sumem.blendmode.colorupdate || sumem.blendmode.alphaupdate) + { + u32 clearColor = (sumem.clearcolorAR << 16) | sumem.clearcolorGB; + glClearColor(((clearColor>>16) & 0xff)*(1/255.0f), + ((clearColor>>8 ) & 0xff)*(1/255.0f), + ((clearColor>>0 ) & 0xff)*(1/255.0f), + ((clearColor>>24) & 0xff)*(1/255.0f)); + bits |= GL_COLOR_BUFFER_BIT; + } + if (sumem.zmode.updateenable) + { + glClearDepth((float)(sumem.clearZValue & 0xFFFFFF) / float(0xFFFFFF)); + bits |= GL_DEPTH_BUFFER_BIT; + } + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + glClear(bits); + } +} + +void RestoreRenderState(const BPCommand &bp) +{ + Renderer::RestoreGLState(); +} + +bool GetConfig(const int &type) +{ + switch (type) + { + case CONFIG_ISWII: + return g_VideoInitialize.bWii; + case CONFIG_DISABLEFOG: + return g_Config.bDisableFog; + case CONFIG_SHOWEFBREGIONS: + return g_Config.bShowEFBCopyRegions; + default: + PanicAlert("GetConfig Error: Unknown Config Type!"); + return false; + } +} +u8 *GetPointer(const u32 &address) +{ + return g_VideoInitialize.pGetMemoryPointer(address); +} +void SetSamplerState(const BPCommand &bp) +{ + // TODO +} +void SetInterlacingMode(const BPCommand &bp) +{ + // TODO +} +};