mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge branch 'master' of https://github.com/hrydgard/ppsspp
This commit is contained in:
commit
fb919a392b
25 changed files with 322 additions and 141 deletions
|
@ -38,6 +38,7 @@ option(BLACKBERRY "Set to ON if targeting a Blackberry device" ${BLACKBERRY})
|
|||
option(IOS "Set to ON if targeting an iOS device" ${IOS})
|
||||
option(USING_GLES2 "Set to ON if target device uses OpenGL ES 2.0" ${USING_GLES2})
|
||||
option(HEADLESS "Set to OFF to not generate the PPSSPPHeadless target" ${HEADLESS})
|
||||
option(DEBUG "Set to ON to enable full debug logging" ${DEBUG})
|
||||
|
||||
if(ANDROID)
|
||||
if(NOT ANDROID_ABI)
|
||||
|
@ -101,12 +102,16 @@ if (USING_GLES2)
|
|||
add_definitions(-DUSING_GLES2)
|
||||
endif()
|
||||
|
||||
if(DEBUG)
|
||||
add_definitions(-D_DEBUG)
|
||||
endif()
|
||||
|
||||
if(NOT MSVC)
|
||||
# Disable some warnings
|
||||
add_definitions(-Wno-psabi)
|
||||
add_definitions(-Wno-multichar)
|
||||
add_definitions(-fno-strict-aliasing)
|
||||
if(NOT APPLE)
|
||||
add_definitions(-Wno-psabi)
|
||||
add_definitions(-D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED -D__BSD_VISIBLE=1)
|
||||
add_definitions(-D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64)
|
||||
endif()
|
||||
|
|
|
@ -48,7 +48,7 @@ void CConfig::Load(const char *iniFileName)
|
|||
general->Get("ConfirmOnQuit", &bConfirmOnQuit, false);
|
||||
general->Get("IgnoreBadMemAccess", &bIgnoreBadMemAccess, true);
|
||||
general->Get("CurrentDirectory", ¤tDirectory, "");
|
||||
|
||||
general->Get("ShowDebuggerOnLoad", &bShowDebuggerOnLoad, false);
|
||||
IniFile::Section *cpu = iniFile.GetOrCreateSection("CPU");
|
||||
cpu->Get("Core", &iCpuCore, 0);
|
||||
|
||||
|
@ -63,6 +63,7 @@ void CConfig::Load(const char *iniFileName)
|
|||
|
||||
IniFile::Section *control = iniFile.GetOrCreateSection("Control");
|
||||
control->Get("ShowStick", &bShowAnalogStick, false);
|
||||
control->Get("ShowTouchControls", &bShowTouchControls, true);
|
||||
}
|
||||
|
||||
void CConfig::Save()
|
||||
|
@ -79,7 +80,7 @@ void CConfig::Save()
|
|||
general->Set("ConfirmOnQuit", bConfirmOnQuit);
|
||||
general->Set("IgnoreBadMemAccess", bIgnoreBadMemAccess);
|
||||
general->Set("CurrentDirectory", currentDirectory);
|
||||
|
||||
general->Set("ShowDebuggerOnLoad", bShowDebuggerOnLoad);
|
||||
IniFile::Section *cpu = iniFile.GetOrCreateSection("CPU");
|
||||
cpu->Set("Core", iCpuCore);
|
||||
|
||||
|
@ -94,6 +95,7 @@ void CConfig::Save()
|
|||
|
||||
IniFile::Section *control = iniFile.GetOrCreateSection("Control");
|
||||
control->Set("ShowStick", bShowAnalogStick);
|
||||
control->Set("ShowTouchControls", bShowTouchControls);
|
||||
|
||||
iniFile.Save(iniFilename_.c_str());
|
||||
NOTICE_LOG(LOADER, "Config saved: %s", iniFilename_.c_str());
|
||||
|
|
|
@ -44,6 +44,8 @@ public:
|
|||
bool bDisplayFramebuffer;
|
||||
bool bBufferedRendering;
|
||||
|
||||
bool bShowTouchControls;
|
||||
bool bShowDebuggerOnLoad;
|
||||
bool bShowAnalogStick;
|
||||
bool bShowFPSCounter;
|
||||
bool bShowDebugStats;
|
||||
|
@ -58,6 +60,5 @@ private:
|
|||
std::string iniFilename_;
|
||||
};
|
||||
|
||||
|
||||
extern SState g_State;
|
||||
extern CConfig g_Config;
|
||||
|
|
|
@ -323,7 +323,7 @@ u32 sceAudioOutput2Reserve(u32 sampleCount)
|
|||
|
||||
void sceAudioOutput2OutputBlocking(u32 vol, u32 dataPtr)
|
||||
{
|
||||
WARN_LOG(HLE,"FAKE sceAudioOutput2OutputBlocking(%i, %08x)", vol, dataPtr);
|
||||
DEBUG_LOG(HLE,"FAKE sceAudioOutput2OutputBlocking(%i, %08x)", vol, dataPtr);
|
||||
chans[0].leftVolume = vol;
|
||||
chans[0].rightVolume = vol;
|
||||
chans[0].sampleAddress = dataPtr;
|
||||
|
|
|
@ -618,18 +618,30 @@ int sceRtcTickAddMonths(u32 destTickPtr, u32 srcTickPtr, int numMonths)
|
|||
{
|
||||
if (Memory::IsValidAddress(destTickPtr) && Memory::IsValidAddress(srcTickPtr))
|
||||
{
|
||||
s64 srcTick = (s64)Memory::Read_U64(srcTickPtr);
|
||||
u64 srcTick = Memory::Read_U64(srcTickPtr);
|
||||
|
||||
// slightly bodgy but we need to add months to a pt and then convert to ticks (untested and broken)
|
||||
// slightly bodgy but we need to add months to a pt and then convert to ticks
|
||||
ScePspDateTime pt;
|
||||
|
||||
int years = numMonths /12;
|
||||
int realmonths = numMonths % 12;
|
||||
memset(&pt, 0, sizeof(pt));
|
||||
pt.year = years;
|
||||
pt.month = realmonths;
|
||||
srcTick +=__RtcPspTimeToTicks(pt);
|
||||
|
||||
if (numMonths < 0)
|
||||
{
|
||||
numMonths = (numMonths^0xFFFFFFFF)+1;
|
||||
int years = numMonths /12;
|
||||
int realmonths = numMonths % 12;
|
||||
|
||||
pt.year = years;
|
||||
pt.month = realmonths;
|
||||
srcTick -=__RtcPspTimeToTicks(pt);
|
||||
}
|
||||
else
|
||||
{
|
||||
int years = numMonths /12;
|
||||
int realmonths = numMonths % 12;
|
||||
|
||||
pt.year = years;
|
||||
pt.month = realmonths;
|
||||
srcTick +=__RtcPspTimeToTicks(pt);
|
||||
}
|
||||
Memory::Write_U64(srcTick, destTickPtr);
|
||||
}
|
||||
|
||||
|
|
|
@ -361,6 +361,19 @@ void sceSasRevParam()
|
|||
RETURN(0);
|
||||
}
|
||||
|
||||
u32 sceSasGetPauseFlag()
|
||||
{
|
||||
u32 PauseFlag = 0;
|
||||
for (int i = 0; i < sas.maxVoices; i++) {
|
||||
if (!sas.voices[i].playing)
|
||||
PauseFlag |= 1 << i;
|
||||
}
|
||||
DEBUG_LOG(HLE,"%08x=sceSasGetPauseFlag()", PauseFlag);
|
||||
return PauseFlag;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void sceSasRevEVOL()
|
||||
{
|
||||
u32 core = PARAM(0);
|
||||
|
@ -410,7 +423,7 @@ const HLEFunction sceSasCore[] =
|
|||
{0xd5a229c9, sceSasRevEVOL, "__sceSasRevEVOL"}, // (int sasCore, int leftVol, int rightVol) // effect volume
|
||||
{0x33d4ab37, sceSasRevType, "__sceSasRevType"}, // (int sasCore, int type)
|
||||
{0x267a6dd2, sceSasRevParam, "__sceSasRevParam"}, // (int sasCore, int delay, int feedback)
|
||||
{0x2c8e6ab3, 0, "__sceSasGetPauseFlag"}, // int sasCore
|
||||
{0x2c8e6ab3, WrapU_V<sceSasGetPauseFlag>, "__sceSasGetPauseFlag"}, // int sasCore
|
||||
{0x787d04d5, 0, "__sceSasSetPause"},
|
||||
{0xa232cbe6, 0, "__sceSasSetTriangularWave"}, // (int sasCore, int voice, int unknown)
|
||||
{0xd5ebbbcd, 0, "__sceSasSetSteepWave"}, // (int sasCore, int voice, int unknown) // square wave?
|
||||
|
|
|
@ -175,7 +175,7 @@ void GLES_GPU::SetRenderFrameBuffer()
|
|||
int drawing_height = ((gstate.region2 >> 10) & 0x3FF) + 1;
|
||||
|
||||
int fmt = gstate.framebufpixformat & 3;
|
||||
|
||||
|
||||
// Find a matching framebuffer
|
||||
VirtualFramebuffer *vfb = 0;
|
||||
for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ++iter)
|
||||
|
@ -189,7 +189,7 @@ void GLES_GPU::SetRenderFrameBuffer()
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// None found? Create one.
|
||||
if (!vfb) {
|
||||
vfb = new VirtualFramebuffer;
|
||||
|
@ -442,7 +442,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff)
|
|||
case GE_CMD_RET:
|
||||
//TODO : debug!
|
||||
{
|
||||
u32 target = dcontext.pc & 0xF0000000 | (stack[--stackptr] & 0x0FFFFFFF);
|
||||
u32 target = (dcontext.pc & 0xF0000000) | (stack[--stackptr] & 0x0FFFFFFF);
|
||||
DEBUG_LOG(G3D,"DL CMD RET - from %08x to %08x", dcontext.pc, target);
|
||||
dcontext.pc = target - 4;
|
||||
}
|
||||
|
@ -571,38 +571,38 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff)
|
|||
break;
|
||||
|
||||
case GE_CMD_FOGENABLE:
|
||||
DEBUG_LOG(G3D, "DL Fog Enable: %i", gstate.fogEnable);
|
||||
DEBUG_LOG(G3D, "DL Fog Enable: %i", data);
|
||||
break;
|
||||
|
||||
case GE_CMD_DITHERENABLE:
|
||||
DEBUG_LOG(G3D, "DL Dither Enable: %i", gstate.ditherEnable);
|
||||
DEBUG_LOG(G3D, "DL Dither Enable: %i", data);
|
||||
break;
|
||||
|
||||
case GE_CMD_OFFSETX:
|
||||
DEBUG_LOG(G3D, "DL Offset X: %i", gstate.offsetx);
|
||||
DEBUG_LOG(G3D, "DL Offset X: %i", data);
|
||||
break;
|
||||
|
||||
case GE_CMD_OFFSETY:
|
||||
DEBUG_LOG(G3D, "DL Offset Y: %i", gstate.offsety);
|
||||
DEBUG_LOG(G3D, "DL Offset Y: %i", data);
|
||||
break;
|
||||
|
||||
case GE_CMD_TEXSCALEU:
|
||||
gstate_c.uScale = getFloat24(data);
|
||||
case GE_CMD_TEXSCALEU:
|
||||
gstate_c.uScale = getFloat24(data);
|
||||
DEBUG_LOG(G3D, "DL Texture U Scale: %f", gstate_c.uScale);
|
||||
break;
|
||||
|
||||
case GE_CMD_TEXSCALEV:
|
||||
gstate_c.vScale = getFloat24(data);
|
||||
case GE_CMD_TEXSCALEV:
|
||||
gstate_c.vScale = getFloat24(data);
|
||||
DEBUG_LOG(G3D, "DL Texture V Scale: %f", gstate_c.vScale);
|
||||
break;
|
||||
|
||||
case GE_CMD_TEXOFFSETU:
|
||||
gstate_c.uOff = getFloat24(data);
|
||||
case GE_CMD_TEXOFFSETU:
|
||||
gstate_c.uOff = getFloat24(data);
|
||||
DEBUG_LOG(G3D, "DL Texture U Offset: %f", gstate_c.uOff);
|
||||
break;
|
||||
|
||||
case GE_CMD_TEXOFFSETV:
|
||||
gstate_c.vOff = getFloat24(data);
|
||||
case GE_CMD_TEXOFFSETV:
|
||||
gstate_c.vOff = getFloat24(data);
|
||||
DEBUG_LOG(G3D, "DL Texture V Offset: %f", gstate_c.vOff);
|
||||
break;
|
||||
|
||||
|
@ -998,7 +998,9 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff)
|
|||
DEBUG_LOG(G3D,"DL TexFilter min: %i mag: %i", min, mag);
|
||||
}
|
||||
break;
|
||||
|
||||
case GE_CMD_TEXENVCOLOR:
|
||||
DEBUG_LOG(G3D,"DL TexEnvColor %06x", data);
|
||||
break;
|
||||
case GE_CMD_TEXMODE:
|
||||
DEBUG_LOG(G3D,"DL TexMode %08x", data);
|
||||
break;
|
||||
|
@ -1044,7 +1046,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff)
|
|||
gstate_c.morphWeights[index] = weight;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case GE_CMD_DITH0:
|
||||
case GE_CMD_DITH1:
|
||||
case GE_CMD_DITH2:
|
||||
|
@ -1053,12 +1055,12 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff)
|
|||
break;
|
||||
|
||||
case GE_CMD_WORLDMATRIXNUMBER:
|
||||
DEBUG_LOG(G3D,"DL World matrix # %i", data & 0xF);
|
||||
DEBUG_LOG(G3D,"DL World # %i", data & 0xF);
|
||||
gstate.worldmtxnum &= 0xFF00000F;
|
||||
break;
|
||||
|
||||
case GE_CMD_WORLDMATRIXDATA:
|
||||
DEBUG_LOG(G3D,"DL World matrix data # %f", getFloat24(data));
|
||||
DEBUG_LOG(G3D,"DL World data # %f", getFloat24(data));
|
||||
{
|
||||
int num = gstate.worldmtxnum & 0xF;
|
||||
if (num < 12)
|
||||
|
@ -1068,12 +1070,12 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff)
|
|||
break;
|
||||
|
||||
case GE_CMD_VIEWMATRIXNUMBER:
|
||||
DEBUG_LOG(G3D,"DL VIEW matrix # %i", data & 0xF);
|
||||
DEBUG_LOG(G3D,"DL VIEW # %i", data & 0xF);
|
||||
gstate.viewmtxnum &= 0xFF00000F;
|
||||
break;
|
||||
|
||||
case GE_CMD_VIEWMATRIXDATA:
|
||||
DEBUG_LOG(G3D,"DL VIEW matrix data # %f", getFloat24(data));
|
||||
DEBUG_LOG(G3D,"DL VIEW data # %f", getFloat24(data));
|
||||
{
|
||||
int num = gstate.viewmtxnum & 0xF;
|
||||
if (num < 12)
|
||||
|
@ -1083,14 +1085,14 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff)
|
|||
break;
|
||||
|
||||
case GE_CMD_PROJMATRIXNUMBER:
|
||||
DEBUG_LOG(G3D,"DL PROJECTION matrix # %i", data & 0xF);
|
||||
DEBUG_LOG(G3D,"DL PROJECTION # %i", data & 0xF);
|
||||
gstate.projmtxnum &= 0xFF00000F;
|
||||
break;
|
||||
|
||||
case GE_CMD_PROJMATRIXDATA:
|
||||
DEBUG_LOG(G3D,"DL PROJECTION matrix data # %f", getFloat24(data));
|
||||
{
|
||||
int num = gstate.projmtxnum & 0xF;
|
||||
int num = gstate.projmtxnum & 0xF;
|
||||
gstate.projMatrix[num++] = getFloat24(data);
|
||||
gstate.projmtxnum = (gstate.projmtxnum & 0xFF000000) | (num & 0xF);
|
||||
}
|
||||
|
@ -1098,12 +1100,12 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff)
|
|||
break;
|
||||
|
||||
case GE_CMD_TGENMATRIXNUMBER:
|
||||
DEBUG_LOG(G3D,"DL TGEN matrix # %i", data & 0xF);
|
||||
DEBUG_LOG(G3D,"DL TGEN # %i", data & 0xF);
|
||||
gstate.texmtxnum &= 0xFF00000F;
|
||||
break;
|
||||
|
||||
case GE_CMD_TGENMATRIXDATA:
|
||||
DEBUG_LOG(G3D,"DL TGEN matrix data # %f", getFloat24(data));
|
||||
DEBUG_LOG(G3D,"DL TGEN data # %f", getFloat24(data));
|
||||
{
|
||||
int num = gstate.texmtxnum & 0xF;
|
||||
if (num < 12)
|
||||
|
@ -1113,12 +1115,12 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff)
|
|||
break;
|
||||
|
||||
case GE_CMD_BONEMATRIXNUMBER:
|
||||
DEBUG_LOG(G3D,"DL BONE matrix #%i", data);
|
||||
DEBUG_LOG(G3D,"DL BONE #%i", data);
|
||||
gstate.boneMatrixNumber &= 0xFF00007F;
|
||||
break;
|
||||
|
||||
case GE_CMD_BONEMATRIXDATA:
|
||||
DEBUG_LOG(G3D,"DL BONE matrix data #%i %f", gstate.boneMatrixNumber & 0x7f, getFloat24(data));
|
||||
DEBUG_LOG(G3D,"DL BONE data #%i %f", gstate.boneMatrixNumber & 0x7f, getFloat24(data));
|
||||
{
|
||||
int num = gstate.boneMatrixNumber & 0x7F;
|
||||
if (num < 96) {
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#include "FragmentShaderGenerator.h"
|
||||
#include "../ge_constants.h"
|
||||
#include "../GPUState.h"
|
||||
|
@ -76,7 +75,9 @@ char *GenerateFragmentShader()
|
|||
|
||||
int lmode = gstate.lmode & 1;
|
||||
|
||||
if (gstate.textureMapEnable & 1)
|
||||
int doTexture = (gstate.textureMapEnable & 1) && !(gstate.clearmode & 1);
|
||||
|
||||
if (doTexture)
|
||||
WRITE(p, "uniform sampler2D tex;\n");
|
||||
if (gstate.alphaTestEnable & 1)
|
||||
WRITE(p, "uniform vec4 u_alpharef;\n");
|
||||
|
@ -88,7 +89,8 @@ char *GenerateFragmentShader()
|
|||
WRITE(p, "varying vec4 v_color0;\n");
|
||||
if (lmode)
|
||||
WRITE(p, "varying vec4 v_color1;\n");
|
||||
WRITE(p, "varying vec2 v_texcoord;\n");
|
||||
if (doTexture)
|
||||
WRITE(p, "varying vec2 v_texcoord;\n");
|
||||
if (gstate.isFogEnabled())
|
||||
WRITE(p, "varying float v_depth;\n");
|
||||
|
||||
|
@ -97,6 +99,7 @@ char *GenerateFragmentShader()
|
|||
|
||||
if (gstate.clearmode & 1)
|
||||
{
|
||||
// Clear mode does not allow any fancy shading.
|
||||
WRITE(p, " v = v_color0;\n");
|
||||
}
|
||||
else
|
||||
|
@ -155,7 +158,7 @@ char *GenerateFragmentShader()
|
|||
if (gstate.texfunc & 0x10000) {
|
||||
WRITE(p, " v = v * vec4(2.0, 2.0, 2.0, 1.0);");
|
||||
}
|
||||
|
||||
|
||||
if (gstate.alphaTestEnable & 1) {
|
||||
int alphaTestFunc = gstate.alphatest & 7;
|
||||
const char *alphaTestFuncs[] = { "#", "#", " == ", " != ", " < ", " <= ", " > ", " >= " }; // never/always don't make sense
|
||||
|
@ -168,7 +171,6 @@ char *GenerateFragmentShader()
|
|||
// WRITE(p, " v = mix(v, u_fogcolor, u_fogcoef.x + u_fogcoef.y * v_depth;\n");
|
||||
// WRITE(p, " v.x = v_depth;\n");
|
||||
}
|
||||
// Fogging should be added here - and disabled during clear mode
|
||||
}
|
||||
|
||||
WRITE(p, " gl_FragColor = v;\n");
|
||||
|
|
|
@ -25,9 +25,7 @@
|
|||
#include "TransformPipeline.h"
|
||||
|
||||
Shader::Shader(const char *code, uint32_t shaderType) {
|
||||
#ifdef _DEBUG
|
||||
source_ = code;
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
// OutputDebugString(code);
|
||||
#endif
|
||||
|
@ -46,7 +44,7 @@ Shader::Shader(const char *code, uint32_t shaderType) {
|
|||
ERROR_LOG(G3D, "Info log: %s\n", infoLog);
|
||||
ERROR_LOG(G3D, "Shader source:\n%s\n", (const char *)code);
|
||||
} else {
|
||||
//NOTICE_LOG(G3D, "Compiled shader:\n%s\n", (const char *)code);
|
||||
DEBUG_LOG(G3D, "Compiled shader:\n%s\n", (const char *)code);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,33 +64,33 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs)
|
|||
char* buf = new char[bufLength];
|
||||
glGetProgramInfoLog(program, bufLength, NULL, buf);
|
||||
ERROR_LOG(G3D, "Could not link program:\n %s", buf);
|
||||
ERROR_LOG(G3D, "VS:\n%s", vs->source().c_str());
|
||||
ERROR_LOG(G3D, "FS:\n%s", fs->source().c_str());
|
||||
delete [] buf; // we're dead!
|
||||
|
||||
//_dbg_assert_msg_(HLE,0,"Could not link program");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NOTICE_LOG(G3D, "Linked shader!");
|
||||
INFO_LOG(G3D, "Linked shader: vs %i fs %i", (int)vs->shader, (int)fs->shader);
|
||||
|
||||
u_tex = glGetUniformLocation(program, "tex");
|
||||
u_proj = glGetUniformLocation(program, "u_proj");
|
||||
u_tex = glGetUniformLocation(program, "tex");
|
||||
u_proj = glGetUniformLocation(program, "u_proj");
|
||||
u_proj_through = glGetUniformLocation(program, "u_proj_through");
|
||||
u_texenv = glGetUniformLocation(program, "u_texenv");
|
||||
u_fogcolor = glGetUniformLocation(program, "u_fogcolor");
|
||||
u_fogcoef = glGetUniformLocation(program, "u_fogcoef");
|
||||
u_alpharef = glGetUniformLocation(program, "u_alpharef");
|
||||
|
||||
a_position = glGetAttribLocation(program, "a_position");
|
||||
a_color0 = glGetAttribLocation(program, "a_color0");
|
||||
a_color1 = glGetAttribLocation(program, "a_color1");
|
||||
a_texcoord = glGetAttribLocation(program, "a_texcoord");
|
||||
a_position = glGetAttribLocation(program, "a_position");
|
||||
a_color0 = glGetAttribLocation(program, "a_color0");
|
||||
a_color1 = glGetAttribLocation(program, "a_color1");
|
||||
a_texcoord = glGetAttribLocation(program, "a_texcoord");
|
||||
|
||||
glUseProgram(program);
|
||||
// Default uniform values
|
||||
glUniform1i(u_tex, 0);
|
||||
// The rest, use the "dirty" mechanism.
|
||||
dirtyUniforms = DIRTY_PROJMATRIX | DIRTY_TEXENV | DIRTY_ALPHAREF;
|
||||
dirtyUniforms = DIRTY_PROJMATRIX | DIRTY_PROJTHROUGHMATRIX | DIRTY_TEXENV | DIRTY_ALPHAREF;
|
||||
}
|
||||
|
||||
LinkedShader::~LinkedShader() {
|
||||
|
@ -100,7 +98,7 @@ LinkedShader::~LinkedShader() {
|
|||
}
|
||||
|
||||
void LinkedShader::use() {
|
||||
glUseProgram(program);
|
||||
glUseProgram(program);
|
||||
glUniform1i(u_tex, 0);
|
||||
// Update any dirty uniforms before we draw
|
||||
if (u_proj != -1 && (dirtyUniforms & DIRTY_PROJMATRIX)) {
|
||||
|
@ -175,7 +173,7 @@ void ShaderManager::DirtyShader()
|
|||
}
|
||||
|
||||
|
||||
LinkedShader *ShaderManager::ApplyShader()
|
||||
LinkedShader *ShaderManager::ApplyShader(int prim)
|
||||
{
|
||||
if (globalDirty) {
|
||||
// Deferred dirtying! Let's see if we can make this even more clever later.
|
||||
|
@ -187,7 +185,7 @@ LinkedShader *ShaderManager::ApplyShader()
|
|||
|
||||
VertexShaderID VSID;
|
||||
FragmentShaderID FSID;
|
||||
ComputeVertexShaderID(&VSID);
|
||||
ComputeVertexShaderID(&VSID, prim);
|
||||
ComputeFragmentShaderID(&FSID);
|
||||
|
||||
// Bail quickly in the no-op case. TODO: why does it cause trouble?
|
||||
|
@ -206,7 +204,7 @@ LinkedShader *ShaderManager::ApplyShader()
|
|||
} else {
|
||||
vs = vsIter->second;
|
||||
}
|
||||
|
||||
|
||||
FSCache::iterator fsIter = fsCache.find(FSID);
|
||||
Shader *fs;
|
||||
if (fsIter == fsCache.end()) {
|
||||
|
|
|
@ -33,7 +33,6 @@ struct LinkedShader
|
|||
void use();
|
||||
|
||||
uint32_t program;
|
||||
|
||||
u32 dirtyUniforms;
|
||||
|
||||
// Pre-fetched attrs and uniforms
|
||||
|
@ -53,8 +52,13 @@ struct LinkedShader
|
|||
int u_alpharef;
|
||||
int u_fogcolor;
|
||||
int u_fogcoef;
|
||||
|
||||
// Lighting
|
||||
int u_ambientcolor;
|
||||
int u_light[4]; // each light consist of vec4[3]
|
||||
};
|
||||
|
||||
// Will reach 32 bits soon :P
|
||||
enum
|
||||
{
|
||||
DIRTY_PROJMATRIX = (1 << 0),
|
||||
|
@ -63,8 +67,29 @@ enum
|
|||
DIRTY_FOGCOEF = (1 << 3),
|
||||
DIRTY_TEXENV = (1 << 4),
|
||||
DIRTY_ALPHAREF = (1 << 5),
|
||||
DIRTY_COLORREF = (1 << 6),
|
||||
|
||||
DIRTY_ALL = (1 << 6) - 1
|
||||
DIRTY_LIGHT0 = (1 << 12),
|
||||
DIRTY_LIGHT1 = (1 << 13),
|
||||
DIRTY_LIGHT2 = (1 << 14),
|
||||
DIRTY_LIGHT3 = (1 << 15),
|
||||
|
||||
DIRTY_GLOBALAMBIENT = (1 << 16),
|
||||
DIRTY_MATERIAL = (1 << 17), // let's set all 4 together (emissive ambient diffuse specular). We hide specular coef in specular.a
|
||||
DIRTY_UVSCALEOFFSET = (1 << 18), // this will be dirtied ALL THE TIME... maybe we'll need to do "last value with this shader compares"
|
||||
|
||||
DIRTY_VIEWMATRIX = (1 << 22), // Maybe we'll fold this into projmatrix eventually
|
||||
DIRTY_TEXMATRIX = (1 << 23),
|
||||
DIRTY_BONEMATRIX0 = (1 << 24),
|
||||
DIRTY_BONEMATRIX1 = (1 << 25),
|
||||
DIRTY_BONEMATRIX2 = (1 << 26),
|
||||
DIRTY_BONEMATRIX3 = (1 << 27),
|
||||
DIRTY_BONEMATRIX4 = (1 << 28),
|
||||
DIRTY_BONEMATRIX5 = (1 << 29),
|
||||
DIRTY_BONEMATRIX6 = (1 << 30),
|
||||
DIRTY_BONEMATRIX7 = (1 << 31),
|
||||
|
||||
DIRTY_ALL = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
// Real public interface
|
||||
|
@ -73,6 +98,7 @@ struct Shader
|
|||
{
|
||||
Shader(const char *code, uint32_t shaderType);
|
||||
uint32_t shader;
|
||||
const std::string &source() const { return source_; }
|
||||
private:
|
||||
std::string source_;
|
||||
};
|
||||
|
@ -84,7 +110,7 @@ public:
|
|||
ShaderManager() : globalDirty(0xFFFFFFFF) {}
|
||||
|
||||
void ClearCache(bool deleteThem); // TODO: deleteThem currently not respected
|
||||
LinkedShader *ApplyShader();
|
||||
LinkedShader *ApplyShader(int prim);
|
||||
void DirtyShader();
|
||||
void DirtyUniform(u32 what);
|
||||
|
||||
|
|
|
@ -119,9 +119,9 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[
|
|||
specular = ∈
|
||||
else
|
||||
specular = &materialSpecular;
|
||||
|
||||
|
||||
Color4 lightSum0 = globalAmbient * *ambient + materialEmissive;
|
||||
Color4 lightSum1(0,0,0,0);
|
||||
Color4 lightSum1(0, 0, 0, 0);
|
||||
|
||||
// Try lights.elf - there's something wrong with the lighting
|
||||
|
||||
|
@ -131,8 +131,8 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[
|
|||
if ((gstate.lightEnable[l] & 1) == 0 && !doShadeMapping_)
|
||||
continue;
|
||||
|
||||
GELightComputation comp = (GELightComputation)(gstate.ltype[l]&3);
|
||||
GELightType type = (GELightType)((gstate.ltype[l]>>8)&3);
|
||||
GELightComputation comp = (GELightComputation)(gstate.ltype[l] & 3);
|
||||
GELightType type = (GELightType)((gstate.ltype[l] >> 8) & 3);
|
||||
Vec3 toLight;
|
||||
|
||||
if (type == GE_LIGHTTYPE_DIRECTIONAL)
|
||||
|
@ -146,7 +146,7 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[
|
|||
float lightScale = 1.0f;
|
||||
if (type != GE_LIGHTTYPE_DIRECTIONAL)
|
||||
{
|
||||
float distance = toLight.Normalize();
|
||||
float distance = toLight.Normalize();
|
||||
lightScale = 1.0f / (gstate_c.lightatt[l][0] + gstate_c.lightatt[l][1]*distance + gstate_c.lightatt[l][2]*distance*distance);
|
||||
if (lightScale > 1.0f) lightScale = 1.0f;
|
||||
}
|
||||
|
@ -159,12 +159,12 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[
|
|||
if (poweredDiffuse)
|
||||
dot = powf(dot, specCoef_);
|
||||
|
||||
Color4 diff = (gstate_c.lightColor[1][l] * *diffuse) * (dot * lightScale);
|
||||
Color4 diff = (gstate_c.lightColor[1][l] * *diffuse) * (dot * lightScale);
|
||||
|
||||
// Real PSP specular
|
||||
Vec3 toViewer(0,0,1);
|
||||
// Better specular
|
||||
//Vec3 toViewer = (viewer - pos).Normalized();
|
||||
// Vec3 toViewer = (viewer - pos).Normalized();
|
||||
|
||||
if (doSpecular)
|
||||
{
|
||||
|
@ -176,7 +176,7 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[
|
|||
if (dot >= 0)
|
||||
{
|
||||
lightSum1 += (gstate_c.lightColor[2][l] * *specular * (powf(dot, specCoef_)*lightScale));
|
||||
}
|
||||
}
|
||||
}
|
||||
dots[l] = dot;
|
||||
if (gstate.lightEnable[l] & 1)
|
||||
|
@ -203,7 +203,11 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte
|
|||
VertexDecoder dec;
|
||||
dec.SetVertexType(gstate.vertType);
|
||||
dec.DecodeVerts(decoded, verts, inds, prim, vertexCount, &indexLowerBound, &indexUpperBound);
|
||||
|
||||
#if 0
|
||||
for (int i = indexLowerBound; i <= indexUpperBound; i++) {
|
||||
PrintDecodedVertex(decoded[i], gstate.vertType);
|
||||
}
|
||||
#endif
|
||||
bool useTexCoord = false;
|
||||
|
||||
// Check if anything needs updating
|
||||
|
@ -217,14 +221,14 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte
|
|||
}
|
||||
gpuStats.numDrawCalls++;
|
||||
gpuStats.numVertsTransformed += vertexCount;
|
||||
|
||||
|
||||
if (bytesRead)
|
||||
*bytesRead = vertexCount * dec.VertexSize();
|
||||
|
||||
bool throughmode = (gstate.vertType & GE_VTYPE_THROUGH_MASK) != 0;
|
||||
// Then, transform and draw in one big swoop (urgh!)
|
||||
// need to move this to the shader.
|
||||
|
||||
|
||||
// We're gonna have to keep software transforming RECTANGLES, unless we use a geom shader which we can't on OpenGL ES 2.0.
|
||||
// Usually, though, these primitives don't use lighting etc so it's no biggie performance wise, but it would be nice to get rid of
|
||||
// this code.
|
||||
|
@ -322,7 +326,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte
|
|||
float litColor0[4];
|
||||
float litColor1[4];
|
||||
lighter.Light(litColor0, litColor1, unlitColor, out, norm, dots);
|
||||
|
||||
|
||||
if (gstate.lightingEnable & 1)
|
||||
{
|
||||
// TODO: don't ignore gstate.lmode - we should send two colors in that case
|
||||
|
@ -459,7 +463,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte
|
|||
if (indexType == GE_VTYPE_IDX_8BIT)
|
||||
{
|
||||
index = ((u8*)inds)[i];
|
||||
}
|
||||
}
|
||||
else if (indexType == GE_VTYPE_IDX_16BIT)
|
||||
{
|
||||
index = ((u16*)inds)[i];
|
||||
|
@ -480,7 +484,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte
|
|||
// We have to turn the rectangle into two triangles, so 6 points. Sigh.
|
||||
|
||||
// TODO: there's supposed to be extra magic here to rotate the UV coordinates depending on if upside down etc.
|
||||
|
||||
|
||||
// bottom right
|
||||
*trans = transVtx;
|
||||
trans++;
|
||||
|
@ -606,17 +610,19 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte
|
|||
glstate.depthTest.set(wantDepthTest);
|
||||
if(wantDepthTest) {
|
||||
// Force GL_ALWAYS if mode clear
|
||||
u8 depthTestFunc = gstate.isModeClear() ? 1 : gstate.getDepthTestFunc();
|
||||
int depthTestFunc = gstate.isModeClear() ? 1 : gstate.getDepthTestFunc();
|
||||
glstate.depthFunc.set(ztests[depthTestFunc]);
|
||||
}
|
||||
|
||||
bool wantDepthWrite = gstate.isModeClear() || gstate.isDepthWriteEnabled();
|
||||
glstate.depthWrite.set(wantDepthWrite ? GL_TRUE : GL_FALSE);
|
||||
|
||||
glstate.depthRange.set(gstate_c.zOff - gstate_c.zScale, gstate_c.zOff + gstate_c.zScale);
|
||||
float depthRangeMin = gstate_c.zOff - gstate_c.zScale;
|
||||
float depthRangeMax = gstate_c.zOff + gstate_c.zScale;
|
||||
glstate.depthRange.set(depthRangeMin, depthRangeMax);
|
||||
|
||||
UpdateViewportAndProjection();
|
||||
LinkedShader *program = shaderManager_->ApplyShader();
|
||||
LinkedShader *program = shaderManager_->ApplyShader(prim);
|
||||
|
||||
// TODO: Make a cache for glEnableVertexAttribArray and glVertexAttribPtr states, these spam the gDebugger log.
|
||||
glEnableVertexAttribArray(program->a_position);
|
||||
|
@ -625,7 +631,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte
|
|||
if (program->a_color1 != -1) glEnableVertexAttribArray(program->a_color1);
|
||||
const int vertexSize = sizeof(transformed[0]);
|
||||
glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, drawBuffer);
|
||||
if (useTexCoord && program->a_texcoord != -1) glVertexAttribPointer(program->a_texcoord, 2, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 3 * 4);
|
||||
if (useTexCoord && program->a_texcoord != -1) glVertexAttribPointer(program->a_texcoord, 2, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 3 * 4);
|
||||
if (program->a_color0 != -1) glVertexAttribPointer(program->a_color0, 4, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 5 * 4);
|
||||
if (program->a_color1 != -1) glVertexAttribPointer(program->a_color1, 4, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 9 * 4);
|
||||
// NOTICE_LOG(G3D,"DrawPrimitive: %i", numTrans);
|
||||
|
@ -643,7 +649,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte
|
|||
void GLES_GPU::UpdateViewportAndProjection()
|
||||
{
|
||||
bool throughmode = (gstate.vertType & GE_VTYPE_THROUGH_MASK) != 0;
|
||||
|
||||
|
||||
// We can probably use these to simply set scissors? Maybe we need to offset by regionX1/Y1
|
||||
int regionX1 = gstate.region1 & 0x3FF;
|
||||
int regionY1 = (gstate.region1 >> 10) & 0x3FF;
|
||||
|
@ -654,8 +660,8 @@ void GLES_GPU::UpdateViewportAndProjection()
|
|||
float offsetY = (float)(gstate.offsety & 0xFFFF) / 16.0f;
|
||||
|
||||
if (throughmode) {
|
||||
return;
|
||||
// No viewport transform here. Let's experiment with using region.
|
||||
return;
|
||||
glViewport((0 + regionX1) * renderWidthFactor_, (0 - regionY1) * renderHeightFactor_, (regionX2 - regionX1) * renderWidthFactor_, (regionY2 - regionY1) * renderHeightFactor_);
|
||||
} else {
|
||||
// These we can turn into a glViewport call, offset by offsetX and offsetY. Math after.
|
||||
|
@ -693,8 +699,8 @@ void GLES_GPU::UpdateViewportAndProjection()
|
|||
|
||||
// Flip vpY0 to match the OpenGL coordinate system.
|
||||
vpY0 = renderHeight_ - (vpY0 + vpHeight);
|
||||
glViewport(vpX0, vpY0, vpWidth, vpHeight);
|
||||
glViewport(vpX0, vpY0, vpWidth, vpHeight);
|
||||
// Sadly, as glViewport takes integers, we will not be able to support sub pixel offsets this way. But meh.
|
||||
shaderManager_->DirtyUniform(DIRTY_PROJMATRIX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,15 @@
|
|||
|
||||
#include "VertexDecoder.h"
|
||||
|
||||
void PrintDecodedVertex(const DecodedVertex &vtx, u32 vtype)
|
||||
{
|
||||
if (vtype & GE_VTYPE_NRM_MASK) printf("N: %f %f %f\n", vtx.normal[0], vtx.normal[1], vtx.normal[2]);
|
||||
if (vtype & GE_VTYPE_TC_MASK) printf("TC: %f %f\n", vtx.uv[0], vtx.uv[1]);
|
||||
if (vtype & GE_VTYPE_COL_MASK) printf("C: %02x %02x %02x %02x\n", vtx.color[0], vtx.color[1], vtx.color[2], vtx.color[3]);
|
||||
if (vtype & GE_VTYPE_WEIGHT_MASK) printf("W: TODO\n");
|
||||
printf("P: %f %f %f\n", vtx.pos[0], vtx.pos[1], vtx.pos[2]);
|
||||
}
|
||||
|
||||
const int tcsize[4] = {0,2,4,8}, tcalign[4] = {0,1,2,4};
|
||||
const int colsize[8] = {0,0,0,0,2,2,2,4}, colalign[8] = {0,0,0,0,2,2,2,4};
|
||||
const int nrmsize[4] = {0,3,6,12}, nrmalign[4] = {0,1,2,4};
|
||||
|
@ -30,7 +39,7 @@ const int wtsize[4] = {0,1,2,4}, wtalign[4] = {0,1,2,4};
|
|||
|
||||
inline int align(int n, int align)
|
||||
{
|
||||
return (n+(align-1)) & ~(align-1);
|
||||
return (n + (align - 1)) & ~(align - 1);
|
||||
}
|
||||
|
||||
void VertexDecoder::SetVertexType(u32 fmt)
|
||||
|
@ -40,7 +49,7 @@ void VertexDecoder::SetVertexType(u32 fmt)
|
|||
|
||||
int biggest = 0;
|
||||
size = 0;
|
||||
|
||||
|
||||
tc = fmt & 0x3;
|
||||
col = (fmt >> 2) & 0x7;
|
||||
nrm = (fmt >> 5) & 0x3;
|
||||
|
@ -51,7 +60,7 @@ void VertexDecoder::SetVertexType(u32 fmt)
|
|||
nweights = ((fmt >> 14) & 0x7)+1;
|
||||
|
||||
DEBUG_LOG(G3D,"VTYPE: THRU=%i TC=%i COL=%i POS=%i NRM=%i WT=%i NW=%i IDX=%i MC=%i", (int)throughmode, tc,col,pos,nrm,weighttype,nweights,idx,morphcount);
|
||||
|
||||
|
||||
if (weighttype)
|
||||
{
|
||||
//size = align(size, wtalign[weighttype]); unnecessary
|
||||
|
|
|
@ -40,26 +40,27 @@ struct TransformedVertex
|
|||
|
||||
|
||||
|
||||
// Right now
|
||||
// Right now
|
||||
// - only contains computed information
|
||||
// - does decoding in nasty branchfilled loops
|
||||
// Future TODO
|
||||
// - will compile into lighting fast specialized x86
|
||||
// Future TODO
|
||||
// - will compile into lighting fast specialized x86 and ARM
|
||||
// - will not bother translating components that can be read directly
|
||||
// by OpenGL ES. Will still have to translate 565 colors, and things
|
||||
// like that. DecodedVertex will not be a fixed struct. Will have to
|
||||
// do morphing here.
|
||||
//
|
||||
// We want 100% perf on 1Ghz even in vertex complex games!
|
||||
class VertexDecoder
|
||||
class VertexDecoder
|
||||
{
|
||||
public:
|
||||
VertexDecoder() : coloff(0), nrmoff(0), posoff(0) {}
|
||||
~VertexDecoder() {}
|
||||
void SetVertexType(u32 fmt);
|
||||
void SetVertexType(u32 vtype);
|
||||
void DecodeVerts(DecodedVertex *decoded, const void *verts, const void *inds, int prim, int count, int *indexLowerBound, int *indexUpperBound) const;
|
||||
bool hasColor() const { return col != 0; }
|
||||
int VertexSize() const { return size; }
|
||||
|
||||
private:
|
||||
u32 fmt;
|
||||
bool throughmode;
|
||||
|
@ -81,5 +82,8 @@ private:
|
|||
int idx;
|
||||
int morphcount;
|
||||
int nweights;
|
||||
|
||||
};
|
||||
|
||||
// Debugging utilities
|
||||
void PrintDecodedVertex(const DecodedVertex &vtx, u32 vtype);
|
||||
|
||||
|
|
|
@ -38,12 +38,24 @@ static char buffer[16384];
|
|||
|
||||
#define WRITE(x, ...) p+=sprintf(p, x "\n" __VA_ARGS__)
|
||||
|
||||
void ComputeVertexShaderID(VertexShaderID *id)
|
||||
// prim so we can special case for RECTANGLES :(
|
||||
void ComputeVertexShaderID(VertexShaderID *id, int prim)
|
||||
{
|
||||
int doTexture = (gstate.textureMapEnable & 1) && !(gstate.clearmode & 1);
|
||||
|
||||
memset(id->d, 0, sizeof(id->d));
|
||||
id->d[0] = gstate.lmode & 1;
|
||||
id->d[0] |= ((int)gstate.isModeThrough()) << 1;
|
||||
id->d[0] |= ((int)gstate.isFogEnabled()) << 2;
|
||||
id->d[0] |= doTexture << 3;
|
||||
|
||||
// Bits that we will need:
|
||||
// lightenable * 4
|
||||
// lighttype * 4
|
||||
// lightcomp * 4
|
||||
// uv gen:
|
||||
// mapping type
|
||||
// texshade light choices (ONLY IF uv mapping type is shade)
|
||||
}
|
||||
|
||||
void WriteLight(char *p, int l) {
|
||||
|
@ -61,8 +73,11 @@ char *GenerateVertexShader()
|
|||
|
||||
int lmode = gstate.lmode & 1;
|
||||
|
||||
WRITE("attribute vec4 a_position;");
|
||||
WRITE("attribute vec2 a_texcoord;");
|
||||
int doTexture = (gstate.textureMapEnable & 1) && !(gstate.clearmode & 1);
|
||||
|
||||
WRITE("attribute vec3 a_position;");
|
||||
if (doTexture)
|
||||
WRITE("attribute vec2 a_texcoord;");
|
||||
WRITE("attribute vec4 a_color0;");
|
||||
if (lmode)
|
||||
WRITE("attribute vec4 a_color1;");
|
||||
|
@ -77,18 +92,20 @@ char *GenerateVertexShader()
|
|||
WRITE("varying vec4 v_color0;");
|
||||
if (lmode)
|
||||
WRITE("varying vec4 v_color1;");
|
||||
WRITE("varying vec2 v_texcoord;");
|
||||
if (doTexture)
|
||||
WRITE("varying vec2 v_texcoord;");
|
||||
if (gstate.isFogEnabled())
|
||||
WRITE("varying float v_depth;");
|
||||
WRITE("void main() {");
|
||||
WRITE(" v_color0 = a_color0;");
|
||||
if (lmode)
|
||||
WRITE(" v_color1 = a_color1;");
|
||||
WRITE(" v_texcoord = a_texcoord;");
|
||||
if (doTexture)
|
||||
WRITE(" v_texcoord = a_texcoord;");
|
||||
if (gstate.isModeThrough()) {
|
||||
WRITE(" gl_Position = u_proj_through * a_position;");
|
||||
WRITE(" gl_Position = u_proj_through * vec4(a_position, 1.0);");
|
||||
} else {
|
||||
WRITE(" gl_Position = u_proj * a_position;");
|
||||
WRITE(" gl_Position = u_proj * vec4(a_position, 1.0);");
|
||||
}
|
||||
if (gstate.isFogEnabled()) {
|
||||
WRITE(" v_depth = gl_Position.z;");
|
||||
|
|
|
@ -46,7 +46,7 @@ struct VertexShaderID
|
|||
}
|
||||
};
|
||||
|
||||
void ComputeVertexShaderID(VertexShaderID *id);
|
||||
void ComputeVertexShaderID(VertexShaderID *id, int prim);
|
||||
|
||||
// The return value is only valid until the function is called again.
|
||||
char *GenerateVertexShader();
|
||||
|
|
|
@ -79,8 +79,8 @@ struct GPUgstate
|
|||
u32 cmdmem[256];
|
||||
struct
|
||||
{
|
||||
int nop;
|
||||
u32 vaddr,
|
||||
u32 nop,
|
||||
vaddr,
|
||||
iaddr,
|
||||
pad00,
|
||||
prim,
|
||||
|
@ -226,11 +226,9 @@ struct GPUgstate
|
|||
transferstart,
|
||||
transfersrcpos,
|
||||
transferdstpos,
|
||||
transfersize
|
||||
;
|
||||
transfersize;
|
||||
|
||||
u32 pad05[0x63-0x40];
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -40,7 +40,28 @@ void WindowsHost::SetWindowTitle(const char *message)
|
|||
// Really need a better way to deal with versions.
|
||||
std::string title = "PPSSPP v0.4 - ";
|
||||
title += message;
|
||||
SetWindowText(mainWindow_, title.c_str());
|
||||
|
||||
int size = MultiByteToWideChar(CP_UTF8, 0, message, title.size(), NULL, 0);
|
||||
if (size > 0)
|
||||
{
|
||||
wchar_t *utf16_title = new wchar_t[size + 1];
|
||||
if (utf16_title)
|
||||
size = MultiByteToWideChar(CP_UTF8, 0, message, title.size(), utf16_title, size);
|
||||
else
|
||||
size = 0;
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
utf16_title[size] = 0;
|
||||
// Don't use SetWindowTextW because it will internally use DefWindowProcA.
|
||||
DefWindowProcW(mainWindow_, WM_SETTEXT, 0, (LPARAM) utf16_title);
|
||||
delete[] utf16_title;
|
||||
}
|
||||
}
|
||||
|
||||
// Something went wrong, fall back to using the local codepage.
|
||||
if (size <= 0)
|
||||
SetWindowTextA(mainWindow_, title.c_str());
|
||||
}
|
||||
|
||||
void WindowsHost::InitSound(PMixer *mixer)
|
||||
|
|
|
@ -35,6 +35,9 @@
|
|||
#include "XPTheme.h"
|
||||
#endif
|
||||
|
||||
BOOL g_bFullScreen = FALSE;
|
||||
RECT rc = {0};
|
||||
|
||||
namespace MainWindow
|
||||
{
|
||||
HWND hwndMain;
|
||||
|
@ -81,7 +84,7 @@ namespace MainWindow
|
|||
wcex.hInstance = hInstance;
|
||||
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_PPSSPP);
|
||||
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wcex.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
|
||||
wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||||
wcex.lpszMenuName = (LPCSTR)IDR_MENU1;
|
||||
wcex.lpszClassName = szWindowClass;
|
||||
wcex.hIconSm = (HICON)LoadImage(hInstance, (LPCTSTR)IDI_PPSSPP, IMAGE_ICON, 16,16,LR_SHARED);
|
||||
|
@ -465,8 +468,12 @@ namespace MainWindow
|
|||
g_Config.bIgnoreBadMemAccess = !g_Config.bIgnoreBadMemAccess;
|
||||
UpdateMenus();
|
||||
break;
|
||||
//case ID_OPTIONS_FULLSCREEN:
|
||||
// break;
|
||||
case ID_OPTIONS_FULLSCREEN:
|
||||
if(g_bFullScreen)
|
||||
_ViewNormal(hWnd);
|
||||
else
|
||||
_ViewFullScreen(hWnd);
|
||||
break;
|
||||
|
||||
case ID_OPTIONS_DISPLAYRAWFRAMEBUFFER:
|
||||
g_Config.bDisplayFramebuffer = !g_Config.bDisplayFramebuffer;
|
||||
|
@ -580,7 +587,7 @@ namespace MainWindow
|
|||
case WM_USER+1:
|
||||
disasmWindow[0] = new CDisasm(MainWindow::GetHInstance(), MainWindow::GetHWND(), currentDebugMIPS);
|
||||
DialogManager::AddDlg(disasmWindow[0]);
|
||||
disasmWindow[0]->Show(TRUE);
|
||||
disasmWindow[0]->Show(g_Config.bShowDebuggerOnLoad);
|
||||
memoryWindow[0] = new CMemoryDlg(MainWindow::GetHInstance(), MainWindow::GetHWND(), currentDebugMIPS);
|
||||
DialogManager::AddDlg(memoryWindow[0]);
|
||||
if (disasmWindow[0])
|
||||
|
@ -670,6 +677,53 @@ namespace MainWindow
|
|||
{
|
||||
InvalidateRect(hwndDisplay,0,0);
|
||||
}
|
||||
void _ViewNormal(HWND hWnd)
|
||||
{
|
||||
// put caption and border styles back
|
||||
DWORD dwOldStyle = ::GetWindowLong(hWnd, GWL_STYLE);
|
||||
DWORD dwNewStyle = dwOldStyle | WS_CAPTION | WS_THICKFRAME;
|
||||
::SetWindowLong(hWnd, GWL_STYLE, dwNewStyle);
|
||||
|
||||
// put back the menu bar
|
||||
::SetMenu(hWnd, menu);
|
||||
|
||||
// resize to normal view
|
||||
// NOTE: use SWP_FRAMECHANGED to force redraw non-client
|
||||
const int x = rc.left;
|
||||
const int y = rc.top;
|
||||
const int cx = rc.right - rc.left;
|
||||
const int cy = rc.bottom - rc.top;
|
||||
::SetWindowPos(hWnd, HWND_NOTOPMOST, x, y, cx, cy, SWP_FRAMECHANGED);
|
||||
|
||||
// reset full screen indicator
|
||||
g_bFullScreen = FALSE;
|
||||
}
|
||||
|
||||
void _ViewFullScreen(HWND hWnd)
|
||||
{
|
||||
// keep in mind normal window rectangle
|
||||
::GetWindowRect(hWnd, &rc);
|
||||
|
||||
// remove caption and border styles
|
||||
DWORD dwOldStyle = ::GetWindowLong(hWnd, GWL_STYLE);
|
||||
DWORD dwNewStyle = dwOldStyle & ~(WS_CAPTION | WS_THICKFRAME);
|
||||
::SetWindowLong(hWnd, GWL_STYLE, dwNewStyle);
|
||||
|
||||
// remove the menu bar
|
||||
::SetMenu(hWnd, NULL);
|
||||
|
||||
// resize to full screen view
|
||||
// NOTE: use SWP_FRAMECHANGED to force redraw non-client
|
||||
const int x = 0;
|
||||
const int y = 0;
|
||||
const int cx = ::GetSystemMetrics(SM_CXSCREEN);
|
||||
const int cy = ::GetSystemMetrics(SM_CYSCREEN);
|
||||
::SetWindowPos(hWnd, HWND_TOPMOST, x, y, cx, cy, SWP_FRAMECHANGED);
|
||||
|
||||
// set full screen indicator
|
||||
g_bFullScreen = TRUE;
|
||||
}
|
||||
|
||||
|
||||
void SetPlaying(const char *text)
|
||||
{
|
||||
|
|
|
@ -14,4 +14,6 @@ namespace MainWindow
|
|||
HINSTANCE GetHInstance();
|
||||
HWND GetDisplayHWND();
|
||||
void SetPlaying(const char*text);
|
||||
void _ViewFullScreen(HWND hWnd);
|
||||
void _ViewNormal(HWND hWnd);
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ BEGIN
|
|||
DEFPUSHBUTTON "OK",IDOK,243,141,50,14
|
||||
ICON IDI_PPSSPP,IDC_STATIC,10,9,20,20
|
||||
LTEXT "PPSSPP",IDC_STATIC,40,8,127,9
|
||||
LTEXT "Copyright (c) by Henrik Rydgård 2012",IDC_STATIC,40,33,253,8
|
||||
LTEXT "Copyright (c) by Henrik Rydg<EFBFBD>rd 2012",IDC_STATIC,40,33,253,8
|
||||
LTEXT "All trademarks are property of their respective owners.\nThe emulator is for educational and development purposes only and it may not be used to play games you do not legally own.",IDC_STATIC,40,102,253,24
|
||||
LTEXT "PSP emulator and debugger",IDC_STATIC,40,19,253,8
|
||||
LTEXT "CISO decompression code by BOOSTER",IDC_STATIC,48,73,240,8
|
||||
|
@ -211,7 +211,7 @@ BEGIN
|
|||
END
|
||||
POPUP "&Options"
|
||||
BEGIN
|
||||
MENUITEM "&Toggle Full Screen\tAlt+Enter", ID_OPTIONS_FULLSCREEN, GRAYED
|
||||
MENUITEM "&Toggle Full Screen\tF12", ID_OPTIONS_FULLSCREEN
|
||||
MENUITEM "&Display raw framebuffer", ID_OPTIONS_DISPLAYRAWFRAMEBUFFER
|
||||
MENUITEM "&Buffered rendering", ID_OPTIONS_BUFFEREDRENDERING
|
||||
MENUITEM "&Show debug statistics", ID_OPTIONS_SHOWDEBUGSTATISTICS
|
||||
|
@ -317,7 +317,7 @@ BEGIN
|
|||
VK_F5, ID_FILE_REFRESHGAMELIST, VIRTKEY, NOINVERT
|
||||
VK_F2, ID_FILE_SAVESTATE, VIRTKEY, NOINVERT
|
||||
"W", ID_FILE_UNLOAD, VIRTKEY, CONTROL, NOINVERT
|
||||
VK_RETURN, ID_OPTIONS_FULLSCREEN, VIRTKEY, ALT, NOINVERT
|
||||
VK_F12, ID_OPTIONS_FULLSCREEN, VIRTKEY, NOINVERT
|
||||
END
|
||||
|
||||
|
||||
|
@ -344,11 +344,11 @@ BEGIN
|
|||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "PPSSPP PSP emulator"
|
||||
VALUE "CompanyName", "Henrik Rydgård Inc."
|
||||
VALUE "CompanyName", "Henrik Rydg<EFBFBD>rd Inc."
|
||||
VALUE "FileDescription", "PPSSPP"
|
||||
VALUE "FileVersion", "1, 0, 0, 0"
|
||||
VALUE "InternalName", "s"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2006-2012 by Henrik Rydgård"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2006-2012 by Henrik Rydg<EFBFBD>rd"
|
||||
VALUE "LegalTrademarks", "All product names are trademarks of their respective owners."
|
||||
VALUE "OriginalFilename", "PPSSPP.exe"
|
||||
VALUE "ProductName", "PPSSPP"
|
||||
|
|
0
android/ab.sh
Normal file → Executable file
0
android/ab.sh
Normal file → Executable file
|
@ -16,6 +16,7 @@
|
|||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "gfx_es2/glsl_program.h"
|
||||
#include "gfx_es2/gl_state.h"
|
||||
#include "gfx_es2/fbo.h"
|
||||
|
||||
#include "input/input_state.h"
|
||||
|
@ -153,14 +154,7 @@ void EmuScreen::render()
|
|||
// Reapply the graphics state of the PSP
|
||||
ReapplyGfxState();
|
||||
|
||||
// First attempt at an Android-friendly execution loop.
|
||||
// We simply run the CPU for 1/60th of a second each frame. If a swap doesn't happen, not sure what the best thing to do is :P
|
||||
// Also if we happen to get half a frame or something, things will be screwed up so this doesn't actually really work.
|
||||
//
|
||||
// I think we need to allocate FBOs per framebuffer and just blit the displayed one here at the end of the frame.
|
||||
// Also - we should add another option to the core that lets us run it until a vblank event happens or the N cycles have passed
|
||||
// - then the synchronization would at least not be able to drift off.
|
||||
|
||||
// We just run the CPU until we get to vblank. This will quickly sync up pretty nicely.
|
||||
// The actual number of cycles doesn't matter so much here as we will break due to CORE_NEXTFRAME, most of the time hopefully...
|
||||
int blockTicks = usToCycles(1000000 / 2);
|
||||
|
||||
|
@ -186,8 +180,8 @@ void EmuScreen::render()
|
|||
ui_draw2d.Begin(DBMODE_NORMAL);
|
||||
|
||||
// Make this configurable.
|
||||
// if (coreParam.useTouchControls)
|
||||
DrawGamepad(ui_draw2d);
|
||||
if (g_Config.bShowTouchControls)
|
||||
DrawGamepad(ui_draw2d);
|
||||
|
||||
DrawWatermark();
|
||||
|
||||
|
|
|
@ -240,19 +240,22 @@ void SettingsScreen::render() {
|
|||
int x = 30;
|
||||
int y = 50;
|
||||
UICheckBox(GEN_ID, x, y += 50, "Enable Sound Emulation", ALIGN_TOPLEFT, &g_Config.bEnableSound);
|
||||
UICheckBox(GEN_ID, x, y += 50, "Show Analog Stick", ALIGN_TOPLEFT, &g_Config.bShowAnalogStick);
|
||||
UICheckBox(GEN_ID, x, y += 50, "Buffered Rendering (may fix flicker)", ALIGN_TOPLEFT, &g_Config.bBufferedRendering);
|
||||
|
||||
|
||||
bool useFastInt = g_Config.iCpuCore == CPU_FASTINTERPRETER;
|
||||
UICheckBox(GEN_ID, x, y += 50, "Slightly faster interpreter (may crash)", ALIGN_TOPLEFT, &useFastInt);
|
||||
ui_draw2d.DrawText(UBUNTU48, "much faster JIT coming later", x += 50, 0xcFFFFFFF, ALIGN_LEFT);
|
||||
// ui_draw2d.DrawText(UBUNTU48, "much faster JIT coming later", x, y+=50, 0xcFFFFFFF, ALIGN_LEFT);
|
||||
UICheckBox(GEN_ID, x, y += 50, "On-screen Touch Controls", ALIGN_TOPLEFT, &g_Config.bShowTouchControls);
|
||||
if (g_Config.bShowTouchControls)
|
||||
UICheckBox(GEN_ID, x + 50, y += 50, "Show Analog Stick", ALIGN_TOPLEFT, &g_Config.bShowAnalogStick);
|
||||
g_Config.iCpuCore = useFastInt ? CPU_FASTINTERPRETER : CPU_INTERPRETER;
|
||||
// UICheckBox(GEN_ID, x, y += 50, "Draw raw framebuffer (for some homebrew)", ALIGN_TOPLEFT, &g_Config.bDisplayFramebuffer);
|
||||
|
||||
if (UIButton(GEN_ID, Pos(dp_xres - 10, dp_yres-10), LARGE_BUTTON_WIDTH, "Back", ALIGN_RIGHT | ALIGN_BOTTOM)) {
|
||||
screenManager()->switchScreen(new MenuScreen());
|
||||
}
|
||||
|
||||
|
||||
UIEnd();
|
||||
|
||||
glsl_bind(UIShader_Get());
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "base/NativeApp.h"
|
||||
#include "file/vfs.h"
|
||||
#include "file/zip_read.h"
|
||||
#include "gfx_es2/gl_state.h"
|
||||
#include "gfx/gl_lost_manager.h"
|
||||
#include "gfx/texture.h"
|
||||
#include "input/input_state.h"
|
||||
|
@ -168,6 +169,7 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co
|
|||
LogManager *logman = LogManager::GetInstance();
|
||||
ILOG("Logman: %p", logman);
|
||||
|
||||
bool gfxLog = false;
|
||||
// Parse command line
|
||||
LogTypes::LOG_LEVELS logLevel = LogTypes::LINFO;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
|
@ -177,12 +179,20 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co
|
|||
// Enable debug logging
|
||||
logLevel = LogTypes::LDEBUG;
|
||||
break;
|
||||
case 'g':
|
||||
gfxLog = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
boot_filename = argv[i];
|
||||
if (!File::Exists(boot_filename))
|
||||
{
|
||||
fprintf(stdout, "File not found: %s\n", boot_filename.c_str());
|
||||
if (boot_filename.empty()) {
|
||||
boot_filename = argv[i];
|
||||
if (!File::Exists(boot_filename))
|
||||
{
|
||||
fprintf(stderr, "File not found: %s\n", boot_filename.c_str());
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Can only boot one file");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -204,13 +214,14 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co
|
|||
{
|
||||
LogTypes::LOG_TYPE type = (LogTypes::LOG_TYPE)i;
|
||||
logman->SetEnable(type, true);
|
||||
logman->SetLogLevel(type, logLevel);
|
||||
logman->SetLogLevel(type, gfxLog && i == LogTypes::G3D ? LogTypes::LDEBUG : logLevel);
|
||||
#ifdef ANDROID
|
||||
logman->AddListener(type, logger);
|
||||
#endif
|
||||
}
|
||||
// Special hack for G3D as it's very spammy. Need to make a flag for this.
|
||||
logman->SetLogLevel(LogTypes::G3D, LogTypes::LERROR);
|
||||
if (!gfxLog)
|
||||
logman->SetLogLevel(LogTypes::G3D, LogTypes::LERROR);
|
||||
INFO_LOG(BOOT, "Logger inited.");
|
||||
}
|
||||
|
||||
|
@ -257,6 +268,7 @@ void NativeInitGraphics()
|
|||
|
||||
void NativeRender()
|
||||
{
|
||||
glstate.Restore();
|
||||
glViewport(0, 0, pixel_xres, pixel_yres);
|
||||
Matrix4x4 ortho;
|
||||
ortho.setOrtho(0.0f, dp_xres, dp_yres, 0.0f, -1.0f, 1.0f);
|
||||
|
|
2
native
2
native
|
@ -1 +1 @@
|
|||
Subproject commit 92bd22ffe5fd90b1441660b9136fc6dc230399ec
|
||||
Subproject commit 7ed5811db38f3547f8eec3d3b577dae38405b1e0
|
Loading…
Add table
Reference in a new issue