Merge pull request #6950 from unknownbrackets/gpu-minor

d3d9: Show an error when default shaders fail to compile
This commit is contained in:
Henrik Rydgård 2014-09-27 18:38:42 +02:00
commit 80a28e5ac7
12 changed files with 1243 additions and 1171 deletions

14
.gitattributes vendored Normal file
View File

@ -0,0 +1,14 @@
*.cpp text diff=cpp
*.h text diff=cpp
*.mm text diff=objc
*.m text diff=objc
*.java text diff=java
*.sh text eol=lf
*.vcproj text eol=crlf
*.vcproj.filters text eol=crlf
*.sln text eol=crlf
*.properties text
*.xml text
# To avoid mucking up the utf-8 characters.
Core/Dialog/PSPOskDialog.cpp binary

View File

@ -98,5 +98,6 @@ extern "C" {
// Call directly after the command or use the error num.
// This function might change the error code.
// Defined in Misc.cpp.
const char* GetLastErrorMsg();
const char *GetLastErrorMsg();
const char *GetStringErrorMsg(int errCode);

View File

@ -15,6 +15,7 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "util/text/utf8.h"
#include "Common.h"
#include <string.h>
@ -30,25 +31,40 @@
// Generic function to get last error message.
// Call directly after the command or use the error num.
// This function might change the error code.
const char* GetLastErrorMsg()
const char *GetLastErrorMsg()
{
static const size_t buff_size = 255;
#ifndef _XBOX
#ifdef _WIN32
static __declspec(thread) char err_str[buff_size] = {};
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
err_str, buff_size, NULL);
return GetStringErrorMsg(GetLastError());
#else
static __thread char err_str[buff_size] = {};
// Thread safe (XSI-compliant)
strerror_r(errno, err_str, buff_size);
return GetStringErrorMsg(errno);
#endif
return err_str;
#else
return "GetLastErrorMsg";
#endif
}
const char *GetStringErrorMsg(int errCode) {
static const size_t buff_size = 1023;
#ifndef _XBOX
#ifdef _WIN32
static __declspec(thread) wchar_t err_strw[buff_size] = {};
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
err_strw, buff_size, NULL);
static __declspec(thread) char err_str[buff_size] = {};
snprintf(err_str, buff_size, ConvertWStringToUTF8(err_strw).c_str());
#else
static __thread char err_str[buff_size] = {};
// Thread safe (XSI-compliant)
strerror_r(errCode, err_str, buff_size);
#endif
return err_str;
#else
return "GetStringErrorMsg";
#endif
}

View File

@ -1,212 +1,212 @@
// Copyright (c) 2012- PPSSPP 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 or later versions.
// 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 git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "Core/HLE/HLE.h"
#include "Core/HLE/FunctionWrappers.h"
#include "Core/HLE/sceAudiocodec.h"
#include "Core/MemMap.h"
#include "Core/Reporting.h"
#include "Core/HW/SimpleAudioDec.h"
#include "Common/ChunkFile.h"
// Following kaien_fr's sample code https://github.com/hrydgard/ppsspp/issues/5620#issuecomment-37086024
// Should probably store the EDRAM get/release status somewhere within here, etc.
struct AudioCodecContext {
u32_le unknown[6];
u32_le inDataPtr; // 6
u32_le inDataSize; // 7
u32_le outDataPtr; // 8
u32_le audioSamplesPerFrame; // 9
u32_le inDataSizeAgain; // 10 ??
};
// audioList is to store current playing audios.
static std::map<u32, SimpleAudio *> audioList;
static bool oldStateLoaded = false;
// find the audio decoder for corresponding ctxPtr in audioList
static SimpleAudio *findDecoder(u32 ctxPtr) {
auto it = audioList.find(ctxPtr);
if (it != audioList.end()) {
return it->second;
}
return NULL;
}
// remove decoder from audioList
static bool removeDecoder(u32 ctxPtr) {
auto it = audioList.find(ctxPtr);
if (it != audioList.end()) {
delete it->second;
audioList.erase(it);
return true;
}
return false;
}
static void clearDecoders() {
for (auto it = audioList.begin(), end = audioList.end(); it != end; it++) {
delete it->second;
}
audioList.clear();
}
void __AudioCodecInit() {
oldStateLoaded = false;
}
void __AudioCodecShutdown() {
// We need to kill off any still opened codecs to not leak memory.
clearDecoders();
}
int sceAudiocodecInit(u32 ctxPtr, int codec) {
if (IsValidCodec(codec)) {
// Create audio decoder for given audio codec and push it into AudioList
if (removeDecoder(ctxPtr)) {
WARN_LOG_REPORT(HLE, "sceAudiocodecInit(%08x, %d): replacing existing context", ctxPtr, codec);
}
auto decoder = new SimpleAudio(codec);
decoder->SetCtxPtr(ctxPtr);
audioList[ctxPtr] = decoder;
INFO_LOG(ME, "sceAudiocodecInit(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));
DEBUG_LOG(ME, "Number of playing sceAudioCodec audios : %d", (int)audioList.size());
return 0;
}
ERROR_LOG_REPORT(ME, "sceAudiocodecInit(%08x, %i (%s)): Unknown audio codec %i", ctxPtr, codec, GetCodecName(codec), codec);
return 0;
}
int sceAudiocodecDecode(u32 ctxPtr, int codec) {
if (!ctxPtr){
ERROR_LOG_REPORT(ME, "sceAudiocodecDecode(%08x, %i (%s)) got NULL pointer", ctxPtr, codec, GetCodecName(codec));
return -1;
}
if (IsValidCodec(codec)){
// Use SimpleAudioDec to decode audio
auto ctx = PSPPointer<AudioCodecContext>::Create(ctxPtr); // On stack, no need to allocate.
int outbytes = 0;
// find a decoder in audioList
auto decoder = findDecoder(ctxPtr);
if (!decoder && oldStateLoaded) {
// We must have loaded an old state that did not have sceAudiocodec information.
// Fake it by creating the desired context.
decoder = new SimpleAudio(codec);
decoder->SetCtxPtr(ctxPtr);
audioList[ctxPtr] = decoder;
}
if (decoder != NULL) {
// Decode audio
decoder->Decode(Memory::GetPointer(ctx->inDataPtr), ctx->inDataSize, Memory::GetPointer(ctx->outDataPtr), &outbytes);
}
DEBUG_LOG(ME, "sceAudiocodecDec(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));
return 0;
}
ERROR_LOG_REPORT(ME, "UNIMPL sceAudiocodecDecode(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));
return 0;
}
int sceAudiocodecGetInfo(u32 ctxPtr, int codec) {
ERROR_LOG_REPORT(ME, "UNIMPL sceAudiocodecGetInfo(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));
return 0;
}
int sceAudiocodecCheckNeedMem(u32 ctxPtr, int codec) {
WARN_LOG(ME, "UNIMPL sceAudiocodecCheckNeedMem(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));
return 0;
}
int sceAudiocodecGetEDRAM(u32 ctxPtr, int codec) {
WARN_LOG(ME, "UNIMPL sceAudiocodecGetEDRAM(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));
return 0;
}
int sceAudiocodecReleaseEDRAM(u32 ctxPtr, int id) {
if (removeDecoder(ctxPtr)){
INFO_LOG(ME, "sceAudiocodecReleaseEDRAM(%08x, %i)", ctxPtr, id);
return 0;
}
WARN_LOG(ME, "UNIMPL sceAudiocodecReleaseEDRAM(%08x, %i)", ctxPtr, id);
return 0;
}
const HLEFunction sceAudiocodec[] = {
{ 0x70A703F8, WrapI_UI<sceAudiocodecDecode>, "sceAudiocodecDecode" },
{ 0x5B37EB1D, WrapI_UI<sceAudiocodecInit>, "sceAudiocodecInit" },
{ 0x8ACA11D5, WrapI_UI<sceAudiocodecGetInfo>, "sceAudiocodecGetInfo" },
{ 0x3A20A200, WrapI_UI<sceAudiocodecGetEDRAM>, "sceAudiocodecGetEDRAM" },
{ 0x29681260, WrapI_UI<sceAudiocodecReleaseEDRAM>, "sceAudiocodecReleaseEDRAM" },
{ 0x9D3F790C, WrapI_UI<sceAudiocodecCheckNeedMem>, "sceAudiocodecCheckNeedMem" },
{ 0x59176a0f, 0, "sceAudiocodec_59176A0F" },
};
void Register_sceAudiocodec()
{
RegisterModule("sceAudiocodec", ARRAY_SIZE(sceAudiocodec), sceAudiocodec);
}
void __sceAudiocodecDoState(PointerWrap &p){
auto s = p.Section("AudioList", 0, 2);
if (!s) {
oldStateLoaded = true;
return;
}
int count = (int)audioList.size();
p.Do(count);
if (count > 0) {
if (p.mode == PointerWrap::MODE_READ) {
clearDecoders();
// loadstate if audioList is nonempty
auto codec_ = new int[count];
auto ctxPtr_ = new u32[count];
p.DoArray(codec_, s >= 2 ? count : (int)ARRAY_SIZE(codec_));
p.DoArray(ctxPtr_, s >= 2 ? count : (int)ARRAY_SIZE(ctxPtr_));
for (int i = 0; i < count; i++) {
auto decoder = new SimpleAudio(codec_[i]);
decoder->SetCtxPtr(ctxPtr_[i]);
audioList[ctxPtr_[i]] = decoder;
}
delete[] codec_;
delete[] ctxPtr_;
}
else
{
// savestate if audioList is nonempty
// Some of this is only necessary in Write but won't really hurt Measure.
auto codec_ = new int[count];
auto ctxPtr_ = new u32[count];
int i = 0;
for (auto it = audioList.begin(), end = audioList.end(); it != end; it++) {
const SimpleAudio *decoder = it->second;
codec_[i] = decoder->GetAudioType();
ctxPtr_[i] = decoder->GetCtxPtr();
i++;
}
p.DoArray(codec_, count);
p.DoArray(ctxPtr_, count);
delete[] codec_;
delete[] ctxPtr_;
}
}
}
// Copyright (c) 2012- PPSSPP 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 or later versions.
// 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 git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "Core/HLE/HLE.h"
#include "Core/HLE/FunctionWrappers.h"
#include "Core/HLE/sceAudiocodec.h"
#include "Core/MemMap.h"
#include "Core/Reporting.h"
#include "Core/HW/SimpleAudioDec.h"
#include "Common/ChunkFile.h"
// Following kaien_fr's sample code https://github.com/hrydgard/ppsspp/issues/5620#issuecomment-37086024
// Should probably store the EDRAM get/release status somewhere within here, etc.
struct AudioCodecContext {
u32_le unknown[6];
u32_le inDataPtr; // 6
u32_le inDataSize; // 7
u32_le outDataPtr; // 8
u32_le audioSamplesPerFrame; // 9
u32_le inDataSizeAgain; // 10 ??
};
// audioList is to store current playing audios.
static std::map<u32, SimpleAudio *> audioList;
static bool oldStateLoaded = false;
// find the audio decoder for corresponding ctxPtr in audioList
static SimpleAudio *findDecoder(u32 ctxPtr) {
auto it = audioList.find(ctxPtr);
if (it != audioList.end()) {
return it->second;
}
return NULL;
}
// remove decoder from audioList
static bool removeDecoder(u32 ctxPtr) {
auto it = audioList.find(ctxPtr);
if (it != audioList.end()) {
delete it->second;
audioList.erase(it);
return true;
}
return false;
}
static void clearDecoders() {
for (auto it = audioList.begin(), end = audioList.end(); it != end; it++) {
delete it->second;
}
audioList.clear();
}
void __AudioCodecInit() {
oldStateLoaded = false;
}
void __AudioCodecShutdown() {
// We need to kill off any still opened codecs to not leak memory.
clearDecoders();
}
int sceAudiocodecInit(u32 ctxPtr, int codec) {
if (IsValidCodec(codec)) {
// Create audio decoder for given audio codec and push it into AudioList
if (removeDecoder(ctxPtr)) {
WARN_LOG_REPORT(HLE, "sceAudiocodecInit(%08x, %d): replacing existing context", ctxPtr, codec);
}
auto decoder = new SimpleAudio(codec);
decoder->SetCtxPtr(ctxPtr);
audioList[ctxPtr] = decoder;
INFO_LOG(ME, "sceAudiocodecInit(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));
DEBUG_LOG(ME, "Number of playing sceAudioCodec audios : %d", (int)audioList.size());
return 0;
}
ERROR_LOG_REPORT(ME, "sceAudiocodecInit(%08x, %i (%s)): Unknown audio codec %i", ctxPtr, codec, GetCodecName(codec), codec);
return 0;
}
int sceAudiocodecDecode(u32 ctxPtr, int codec) {
if (!ctxPtr){
ERROR_LOG_REPORT(ME, "sceAudiocodecDecode(%08x, %i (%s)) got NULL pointer", ctxPtr, codec, GetCodecName(codec));
return -1;
}
if (IsValidCodec(codec)){
// Use SimpleAudioDec to decode audio
auto ctx = PSPPointer<AudioCodecContext>::Create(ctxPtr); // On stack, no need to allocate.
int outbytes = 0;
// find a decoder in audioList
auto decoder = findDecoder(ctxPtr);
if (!decoder && oldStateLoaded) {
// We must have loaded an old state that did not have sceAudiocodec information.
// Fake it by creating the desired context.
decoder = new SimpleAudio(codec);
decoder->SetCtxPtr(ctxPtr);
audioList[ctxPtr] = decoder;
}
if (decoder != NULL) {
// Decode audio
decoder->Decode(Memory::GetPointer(ctx->inDataPtr), ctx->inDataSize, Memory::GetPointer(ctx->outDataPtr), &outbytes);
}
DEBUG_LOG(ME, "sceAudiocodecDec(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));
return 0;
}
ERROR_LOG_REPORT(ME, "UNIMPL sceAudiocodecDecode(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));
return 0;
}
int sceAudiocodecGetInfo(u32 ctxPtr, int codec) {
ERROR_LOG_REPORT(ME, "UNIMPL sceAudiocodecGetInfo(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));
return 0;
}
int sceAudiocodecCheckNeedMem(u32 ctxPtr, int codec) {
WARN_LOG(ME, "UNIMPL sceAudiocodecCheckNeedMem(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));
return 0;
}
int sceAudiocodecGetEDRAM(u32 ctxPtr, int codec) {
WARN_LOG(ME, "UNIMPL sceAudiocodecGetEDRAM(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));
return 0;
}
int sceAudiocodecReleaseEDRAM(u32 ctxPtr, int id) {
if (removeDecoder(ctxPtr)){
INFO_LOG(ME, "sceAudiocodecReleaseEDRAM(%08x, %i)", ctxPtr, id);
return 0;
}
WARN_LOG(ME, "UNIMPL sceAudiocodecReleaseEDRAM(%08x, %i)", ctxPtr, id);
return 0;
}
const HLEFunction sceAudiocodec[] = {
{ 0x70A703F8, WrapI_UI<sceAudiocodecDecode>, "sceAudiocodecDecode" },
{ 0x5B37EB1D, WrapI_UI<sceAudiocodecInit>, "sceAudiocodecInit" },
{ 0x8ACA11D5, WrapI_UI<sceAudiocodecGetInfo>, "sceAudiocodecGetInfo" },
{ 0x3A20A200, WrapI_UI<sceAudiocodecGetEDRAM>, "sceAudiocodecGetEDRAM" },
{ 0x29681260, WrapI_UI<sceAudiocodecReleaseEDRAM>, "sceAudiocodecReleaseEDRAM" },
{ 0x9D3F790C, WrapI_UI<sceAudiocodecCheckNeedMem>, "sceAudiocodecCheckNeedMem" },
{ 0x59176a0f, 0, "sceAudiocodec_59176A0F" },
};
void Register_sceAudiocodec()
{
RegisterModule("sceAudiocodec", ARRAY_SIZE(sceAudiocodec), sceAudiocodec);
}
void __sceAudiocodecDoState(PointerWrap &p){
auto s = p.Section("AudioList", 0, 2);
if (!s) {
oldStateLoaded = true;
return;
}
int count = (int)audioList.size();
p.Do(count);
if (count > 0) {
if (p.mode == PointerWrap::MODE_READ) {
clearDecoders();
// loadstate if audioList is nonempty
auto codec_ = new int[count];
auto ctxPtr_ = new u32[count];
p.DoArray(codec_, s >= 2 ? count : (int)ARRAY_SIZE(codec_));
p.DoArray(ctxPtr_, s >= 2 ? count : (int)ARRAY_SIZE(ctxPtr_));
for (int i = 0; i < count; i++) {
auto decoder = new SimpleAudio(codec_[i]);
decoder->SetCtxPtr(ctxPtr_[i]);
audioList[ctxPtr_[i]] = decoder;
}
delete[] codec_;
delete[] ctxPtr_;
}
else
{
// savestate if audioList is nonempty
// Some of this is only necessary in Write but won't really hurt Measure.
auto codec_ = new int[count];
auto ctxPtr_ = new u32[count];
int i = 0;
for (auto it = audioList.begin(), end = audioList.end(); it != end; it++) {
const SimpleAudio *decoder = it->second;
codec_[i] = decoder->GetAudioType();
ctxPtr_[i] = decoder->GetCtxPtr();
i++;
}
p.DoArray(codec_, count);
p.DoArray(ctxPtr_, count);
delete[] codec_;
delete[] ctxPtr_;
}
}
}

View File

@ -1,343 +1,343 @@
// Copyright (c) 2013- PPSSPP 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 or later versions.
// 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 git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "GPU/Common/DrawEngineCommon.h"
#include "GPU/Common/SplineCommon.h"
#include "GPU/Common/VertexDecoderCommon.h"
#include "GPU/ge_constants.h"
#include "GPU/GPUState.h"
#include "Core/Config.h"
#include <algorithm>
DrawEngineCommon::~DrawEngineCommon() { }
struct Plane {
float x, y, z, w;
void Set(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; }
float Test(float f[3]) const { return x * f[0] + y * f[1] + z * f[2] + w; }
};
static void PlanesFromMatrix(float mtx[16], Plane planes[6]) {
planes[0].Set(mtx[3]-mtx[0], mtx[7]-mtx[4], mtx[11]-mtx[8], mtx[15]-mtx[12]); // Right
planes[1].Set(mtx[3]+mtx[0], mtx[7]+mtx[4], mtx[11]+mtx[8], mtx[15]+mtx[12]); // Left
planes[2].Set(mtx[3]+mtx[1], mtx[7]+mtx[5], mtx[11]+mtx[9], mtx[15]+mtx[13]); // Bottom
planes[3].Set(mtx[3]-mtx[1], mtx[7]-mtx[5], mtx[11]-mtx[9], mtx[15]-mtx[13]); // Top
planes[4].Set(mtx[3]+mtx[2], mtx[7]+mtx[6], mtx[11]+mtx[10], mtx[15]+mtx[14]); // Near
planes[5].Set(mtx[3]-mtx[2], mtx[7]-mtx[6], mtx[11]-mtx[10], mtx[15]-mtx[14]); // Far
}
static Vec3f ClipToScreen(const Vec4f& coords) {
// TODO: Check for invalid parameters (x2 < x1, etc)
float vpx1 = getFloat24(gstate.viewportx1);
float vpx2 = getFloat24(gstate.viewportx2);
float vpy1 = getFloat24(gstate.viewporty1);
float vpy2 = getFloat24(gstate.viewporty2);
float vpz1 = getFloat24(gstate.viewportz1);
float vpz2 = getFloat24(gstate.viewportz2);
float retx = coords.x * vpx1 / coords.w + vpx2;
float rety = coords.y * vpy1 / coords.w + vpy2;
float retz = coords.z * vpz1 / coords.w + vpz2;
// 16 = 0xFFFF / 4095.9375
return Vec3f(retx * 16, rety * 16, retz);
}
static Vec3f ScreenToDrawing(const Vec3f& coords) {
Vec3f ret;
ret.x = (coords.x - gstate.getOffsetX16()) * (1.0f / 16.0f);
ret.y = (coords.y - gstate.getOffsetY16()) * (1.0f / 16.0f);
ret.z = coords.z;
return ret;
}
// This code is HIGHLY unoptimized!
//
// It does the simplest and safest test possible: If all points of a bbox is outside a single of
// our clipping planes, we reject the box. Tighter bounds would be desirable but would take more calculations.
bool DrawEngineCommon::TestBoundingBox(void* control_points, int vertexCount, u32 vertType) {
SimpleVertex *corners = (SimpleVertex *)(decoded + 65536 * 12);
float *verts = (float *)(decoded + 65536 * 18);
// Try to skip NormalizeVertices if it's pure positions. No need to bother with a vertex decoder
// and a large vertex format.
if ((vertType & 0xFFFFFF) == GE_VTYPE_POS_FLOAT) {
// memcpy(verts, control_points, 12 * vertexCount);
verts = (float *)control_points;
} else if ((vertType & 0xFFFFFF) == GE_VTYPE_POS_8BIT) {
const s8 *vtx = (const s8 *)control_points;
for (int i = 0; i < vertexCount * 3; i++) {
verts[i] = vtx[i] * (1.0f / 128.0f);
}
} else if ((vertType & 0xFFFFFF) == GE_VTYPE_POS_16BIT) {
const s16 *vtx = (const s16*)control_points;
for (int i = 0; i < vertexCount * 3; i++) {
verts[i] = vtx[i] * (1.0f / 32768.0f);
}
} else {
// Simplify away bones and morph before proceeding
u8 *temp_buffer = decoded + 65536 * 24;
NormalizeVertices((u8 *)corners, temp_buffer, (u8 *)control_points, 0, vertexCount, vertType);
// Special case for float positions only.
const float *ctrl = (const float *)control_points;
for (int i = 0; i < vertexCount; i++) {
verts[i * 3] = corners[i].pos.x;
verts[i * 3 + 1] = corners[i].pos.y;
verts[i * 3 + 2] = corners[i].pos.z;
}
}
Plane planes[6];
float world[16];
float view[16];
float worldview[16];
float worldviewproj[16];
ConvertMatrix4x3To4x4(world, gstate.worldMatrix);
ConvertMatrix4x3To4x4(view, gstate.viewMatrix);
Matrix4ByMatrix4(worldview, world, view);
Matrix4ByMatrix4(worldviewproj, worldview, gstate.projMatrix);
PlanesFromMatrix(worldviewproj, planes);
for (int plane = 0; plane < 6; plane++) {
int inside = 0;
int out = 0;
for (int i = 0; i < vertexCount; i++) {
// Here we can test against the frustum planes!
float value = planes[plane].Test(verts + i * 3);
if (value < 0)
out++;
else
inside++;
}
if (inside == 0) {
// All out
return false;
}
// Any out. For testing that the planes are in the right locations.
// if (out != 0) return false;
}
return true;
}
// TODO: This probably is not the best interface.
bool DrawEngineCommon::GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices) {
// This is always for the current vertices.
u16 indexLowerBound = 0;
u16 indexUpperBound = count - 1;
bool savedVertexFullAlpha = gstate_c.vertexFullAlpha;
if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) {
const u8 *inds = Memory::GetPointer(gstate_c.indexAddr);
const u16 *inds16 = (const u16 *)inds;
if (inds) {
GetIndexBounds(inds, count, gstate.vertType, &indexLowerBound, &indexUpperBound);
indices.resize(count);
switch (gstate.vertType & GE_VTYPE_IDX_MASK) {
case GE_VTYPE_IDX_16BIT:
for (int i = 0; i < count; ++i) {
indices[i] = inds16[i];
}
break;
case GE_VTYPE_IDX_8BIT:
for (int i = 0; i < count; ++i) {
indices[i] = inds[i];
}
break;
default:
return false;
}
} else {
indices.clear();
}
} else {
indices.clear();
}
static std::vector<u32> temp_buffer;
static std::vector<SimpleVertex> simpleVertices;
temp_buffer.resize(std::max((int)indexUpperBound, 8192) * 128 / sizeof(u32));
simpleVertices.resize(indexUpperBound + 1);
NormalizeVertices((u8 *)(&simpleVertices[0]), (u8 *)(&temp_buffer[0]), Memory::GetPointer(gstate_c.vertexAddr), indexLowerBound, indexUpperBound, gstate.vertType);
float world[16];
float view[16];
float worldview[16];
float worldviewproj[16];
ConvertMatrix4x3To4x4(world, gstate.worldMatrix);
ConvertMatrix4x3To4x4(view, gstate.viewMatrix);
Matrix4ByMatrix4(worldview, world, view);
Matrix4ByMatrix4(worldviewproj, worldview, gstate.projMatrix);
vertices.resize(indexUpperBound + 1);
for (int i = indexLowerBound; i <= indexUpperBound; ++i) {
const SimpleVertex &vert = simpleVertices[i];
if (gstate.isModeThrough()) {
if (gstate.vertType & GE_VTYPE_TC_MASK) {
vertices[i].u = vert.uv[0];
vertices[i].v = vert.uv[1];
} else {
vertices[i].u = 0.0f;
vertices[i].v = 0.0f;
}
vertices[i].x = vert.pos.x;
vertices[i].y = vert.pos.y;
vertices[i].z = vert.pos.z;
if (gstate.vertType & GE_VTYPE_COL_MASK) {
memcpy(vertices[i].c, vert.color, sizeof(vertices[i].c));
} else {
memset(vertices[i].c, 0, sizeof(vertices[i].c));
}
} else {
float clipPos[4];
Vec3ByMatrix44(clipPos, vert.pos.AsArray(), worldviewproj);
Vec3f screenPos = ClipToScreen(clipPos);
Vec3f drawPos = ScreenToDrawing(screenPos);
if (gstate.vertType & GE_VTYPE_TC_MASK) {
vertices[i].u = vert.uv[0];
vertices[i].v = vert.uv[1];
} else {
vertices[i].u = 0.0f;
vertices[i].v = 0.0f;
}
vertices[i].x = drawPos.x;
vertices[i].y = drawPos.y;
vertices[i].z = drawPos.z;
if (gstate.vertType & GE_VTYPE_COL_MASK) {
memcpy(vertices[i].c, vert.color, sizeof(vertices[i].c));
} else {
memset(vertices[i].c, 0, sizeof(vertices[i].c));
}
}
}
gstate_c.vertexFullAlpha = savedVertexFullAlpha;
return true;
}
// This normalizes a set of vertices in any format to SimpleVertex format, by processing away morphing AND skinning.
// The rest of the transform pipeline like lighting will go as normal, either hardware or software.
// The implementation is initially a bit inefficient but shouldn't be a big deal.
// An intermediate buffer of not-easy-to-predict size is stored at bufPtr.
u32 DrawEngineCommon::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, VertexDecoder *dec, int lowerBound, int upperBound, u32 vertType) {
// First, decode the vertices into a GPU compatible format. This step can be eliminated but will need a separate
// implementation of the vertex decoder.
dec->DecodeVerts(bufPtr, inPtr, lowerBound, upperBound);
// OK, morphing eliminated but bones still remain to be taken care of.
// Let's do a partial software transform where we only do skinning.
VertexReader reader(bufPtr, dec->GetDecVtxFmt(), vertType);
SimpleVertex *sverts = (SimpleVertex *)outPtr;
const u8 defaultColor[4] = {
(u8)gstate.getMaterialAmbientR(),
(u8)gstate.getMaterialAmbientG(),
(u8)gstate.getMaterialAmbientB(),
(u8)gstate.getMaterialAmbientA(),
};
// Let's have two separate loops, one for non skinning and one for skinning.
if (!g_Config.bSoftwareSkinning && (vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE) {
int numBoneWeights = vertTypeGetNumBoneWeights(vertType);
for (int i = lowerBound; i <= upperBound; i++) {
reader.Goto(i);
SimpleVertex &sv = sverts[i];
if (vertType & GE_VTYPE_TC_MASK) {
reader.ReadUV(sv.uv);
}
if (vertType & GE_VTYPE_COL_MASK) {
reader.ReadColor0_8888(sv.color);
} else {
memcpy(sv.color, defaultColor, 4);
}
float nrm[3], pos[3];
float bnrm[3], bpos[3];
if (vertType & GE_VTYPE_NRM_MASK) {
// Normals are generated during tesselation anyway, not sure if any need to supply
reader.ReadNrm(nrm);
} else {
nrm[0] = 0;
nrm[1] = 0;
nrm[2] = 1.0f;
}
reader.ReadPos(pos);
// Apply skinning transform directly
float weights[8];
reader.ReadWeights(weights);
// Skinning
Vec3Packedf psum(0, 0, 0);
Vec3Packedf nsum(0, 0, 0);
for (int w = 0; w < numBoneWeights; w++) {
if (weights[w] != 0.0f) {
Vec3ByMatrix43(bpos, pos, gstate.boneMatrix + w * 12);
Vec3Packedf tpos(bpos);
psum += tpos * weights[w];
Norm3ByMatrix43(bnrm, nrm, gstate.boneMatrix + w * 12);
Vec3Packedf tnorm(bnrm);
nsum += tnorm * weights[w];
}
}
sv.pos = psum;
sv.nrm = nsum;
}
} else {
for (int i = lowerBound; i <= upperBound; i++) {
reader.Goto(i);
SimpleVertex &sv = sverts[i];
if (vertType & GE_VTYPE_TC_MASK) {
reader.ReadUV(sv.uv);
} else {
sv.uv[0] = 0; // This will get filled in during tesselation
sv.uv[1] = 0;
}
if (vertType & GE_VTYPE_COL_MASK) {
reader.ReadColor0_8888(sv.color);
} else {
memcpy(sv.color, defaultColor, 4);
}
if (vertType & GE_VTYPE_NRM_MASK) {
// Normals are generated during tesselation anyway, not sure if any need to supply
reader.ReadNrm((float *)&sv.nrm);
} else {
sv.nrm.x = 0;
sv.nrm.y = 0;
sv.nrm.z = 1.0f;
}
reader.ReadPos((float *)&sv.pos);
}
}
// Okay, there we are! Return the new type (but keep the index bits)
return GE_VTYPE_TC_FLOAT | GE_VTYPE_COL_8888 | GE_VTYPE_NRM_FLOAT | GE_VTYPE_POS_FLOAT | (vertType & (GE_VTYPE_IDX_MASK | GE_VTYPE_THROUGH));
}
// Copyright (c) 2013- PPSSPP 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 or later versions.
// 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 git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "GPU/Common/DrawEngineCommon.h"
#include "GPU/Common/SplineCommon.h"
#include "GPU/Common/VertexDecoderCommon.h"
#include "GPU/ge_constants.h"
#include "GPU/GPUState.h"
#include "Core/Config.h"
#include <algorithm>
DrawEngineCommon::~DrawEngineCommon() { }
struct Plane {
float x, y, z, w;
void Set(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; }
float Test(float f[3]) const { return x * f[0] + y * f[1] + z * f[2] + w; }
};
static void PlanesFromMatrix(float mtx[16], Plane planes[6]) {
planes[0].Set(mtx[3]-mtx[0], mtx[7]-mtx[4], mtx[11]-mtx[8], mtx[15]-mtx[12]); // Right
planes[1].Set(mtx[3]+mtx[0], mtx[7]+mtx[4], mtx[11]+mtx[8], mtx[15]+mtx[12]); // Left
planes[2].Set(mtx[3]+mtx[1], mtx[7]+mtx[5], mtx[11]+mtx[9], mtx[15]+mtx[13]); // Bottom
planes[3].Set(mtx[3]-mtx[1], mtx[7]-mtx[5], mtx[11]-mtx[9], mtx[15]-mtx[13]); // Top
planes[4].Set(mtx[3]+mtx[2], mtx[7]+mtx[6], mtx[11]+mtx[10], mtx[15]+mtx[14]); // Near
planes[5].Set(mtx[3]-mtx[2], mtx[7]-mtx[6], mtx[11]-mtx[10], mtx[15]-mtx[14]); // Far
}
static Vec3f ClipToScreen(const Vec4f& coords) {
// TODO: Check for invalid parameters (x2 < x1, etc)
float vpx1 = getFloat24(gstate.viewportx1);
float vpx2 = getFloat24(gstate.viewportx2);
float vpy1 = getFloat24(gstate.viewporty1);
float vpy2 = getFloat24(gstate.viewporty2);
float vpz1 = getFloat24(gstate.viewportz1);
float vpz2 = getFloat24(gstate.viewportz2);
float retx = coords.x * vpx1 / coords.w + vpx2;
float rety = coords.y * vpy1 / coords.w + vpy2;
float retz = coords.z * vpz1 / coords.w + vpz2;
// 16 = 0xFFFF / 4095.9375
return Vec3f(retx * 16, rety * 16, retz);
}
static Vec3f ScreenToDrawing(const Vec3f& coords) {
Vec3f ret;
ret.x = (coords.x - gstate.getOffsetX16()) * (1.0f / 16.0f);
ret.y = (coords.y - gstate.getOffsetY16()) * (1.0f / 16.0f);
ret.z = coords.z;
return ret;
}
// This code is HIGHLY unoptimized!
//
// It does the simplest and safest test possible: If all points of a bbox is outside a single of
// our clipping planes, we reject the box. Tighter bounds would be desirable but would take more calculations.
bool DrawEngineCommon::TestBoundingBox(void* control_points, int vertexCount, u32 vertType) {
SimpleVertex *corners = (SimpleVertex *)(decoded + 65536 * 12);
float *verts = (float *)(decoded + 65536 * 18);
// Try to skip NormalizeVertices if it's pure positions. No need to bother with a vertex decoder
// and a large vertex format.
if ((vertType & 0xFFFFFF) == GE_VTYPE_POS_FLOAT) {
// memcpy(verts, control_points, 12 * vertexCount);
verts = (float *)control_points;
} else if ((vertType & 0xFFFFFF) == GE_VTYPE_POS_8BIT) {
const s8 *vtx = (const s8 *)control_points;
for (int i = 0; i < vertexCount * 3; i++) {
verts[i] = vtx[i] * (1.0f / 128.0f);
}
} else if ((vertType & 0xFFFFFF) == GE_VTYPE_POS_16BIT) {
const s16 *vtx = (const s16*)control_points;
for (int i = 0; i < vertexCount * 3; i++) {
verts[i] = vtx[i] * (1.0f / 32768.0f);
}
} else {
// Simplify away bones and morph before proceeding
u8 *temp_buffer = decoded + 65536 * 24;
NormalizeVertices((u8 *)corners, temp_buffer, (u8 *)control_points, 0, vertexCount, vertType);
// Special case for float positions only.
const float *ctrl = (const float *)control_points;
for (int i = 0; i < vertexCount; i++) {
verts[i * 3] = corners[i].pos.x;
verts[i * 3 + 1] = corners[i].pos.y;
verts[i * 3 + 2] = corners[i].pos.z;
}
}
Plane planes[6];
float world[16];
float view[16];
float worldview[16];
float worldviewproj[16];
ConvertMatrix4x3To4x4(world, gstate.worldMatrix);
ConvertMatrix4x3To4x4(view, gstate.viewMatrix);
Matrix4ByMatrix4(worldview, world, view);
Matrix4ByMatrix4(worldviewproj, worldview, gstate.projMatrix);
PlanesFromMatrix(worldviewproj, planes);
for (int plane = 0; plane < 6; plane++) {
int inside = 0;
int out = 0;
for (int i = 0; i < vertexCount; i++) {
// Here we can test against the frustum planes!
float value = planes[plane].Test(verts + i * 3);
if (value < 0)
out++;
else
inside++;
}
if (inside == 0) {
// All out
return false;
}
// Any out. For testing that the planes are in the right locations.
// if (out != 0) return false;
}
return true;
}
// TODO: This probably is not the best interface.
bool DrawEngineCommon::GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices) {
// This is always for the current vertices.
u16 indexLowerBound = 0;
u16 indexUpperBound = count - 1;
bool savedVertexFullAlpha = gstate_c.vertexFullAlpha;
if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) {
const u8 *inds = Memory::GetPointer(gstate_c.indexAddr);
const u16 *inds16 = (const u16 *)inds;
if (inds) {
GetIndexBounds(inds, count, gstate.vertType, &indexLowerBound, &indexUpperBound);
indices.resize(count);
switch (gstate.vertType & GE_VTYPE_IDX_MASK) {
case GE_VTYPE_IDX_16BIT:
for (int i = 0; i < count; ++i) {
indices[i] = inds16[i];
}
break;
case GE_VTYPE_IDX_8BIT:
for (int i = 0; i < count; ++i) {
indices[i] = inds[i];
}
break;
default:
return false;
}
} else {
indices.clear();
}
} else {
indices.clear();
}
static std::vector<u32> temp_buffer;
static std::vector<SimpleVertex> simpleVertices;
temp_buffer.resize(std::max((int)indexUpperBound, 8192) * 128 / sizeof(u32));
simpleVertices.resize(indexUpperBound + 1);
NormalizeVertices((u8 *)(&simpleVertices[0]), (u8 *)(&temp_buffer[0]), Memory::GetPointer(gstate_c.vertexAddr), indexLowerBound, indexUpperBound, gstate.vertType);
float world[16];
float view[16];
float worldview[16];
float worldviewproj[16];
ConvertMatrix4x3To4x4(world, gstate.worldMatrix);
ConvertMatrix4x3To4x4(view, gstate.viewMatrix);
Matrix4ByMatrix4(worldview, world, view);
Matrix4ByMatrix4(worldviewproj, worldview, gstate.projMatrix);
vertices.resize(indexUpperBound + 1);
for (int i = indexLowerBound; i <= indexUpperBound; ++i) {
const SimpleVertex &vert = simpleVertices[i];
if (gstate.isModeThrough()) {
if (gstate.vertType & GE_VTYPE_TC_MASK) {
vertices[i].u = vert.uv[0];
vertices[i].v = vert.uv[1];
} else {
vertices[i].u = 0.0f;
vertices[i].v = 0.0f;
}
vertices[i].x = vert.pos.x;
vertices[i].y = vert.pos.y;
vertices[i].z = vert.pos.z;
if (gstate.vertType & GE_VTYPE_COL_MASK) {
memcpy(vertices[i].c, vert.color, sizeof(vertices[i].c));
} else {
memset(vertices[i].c, 0, sizeof(vertices[i].c));
}
} else {
float clipPos[4];
Vec3ByMatrix44(clipPos, vert.pos.AsArray(), worldviewproj);
Vec3f screenPos = ClipToScreen(clipPos);
Vec3f drawPos = ScreenToDrawing(screenPos);
if (gstate.vertType & GE_VTYPE_TC_MASK) {
vertices[i].u = vert.uv[0];
vertices[i].v = vert.uv[1];
} else {
vertices[i].u = 0.0f;
vertices[i].v = 0.0f;
}
vertices[i].x = drawPos.x;
vertices[i].y = drawPos.y;
vertices[i].z = drawPos.z;
if (gstate.vertType & GE_VTYPE_COL_MASK) {
memcpy(vertices[i].c, vert.color, sizeof(vertices[i].c));
} else {
memset(vertices[i].c, 0, sizeof(vertices[i].c));
}
}
}
gstate_c.vertexFullAlpha = savedVertexFullAlpha;
return true;
}
// This normalizes a set of vertices in any format to SimpleVertex format, by processing away morphing AND skinning.
// The rest of the transform pipeline like lighting will go as normal, either hardware or software.
// The implementation is initially a bit inefficient but shouldn't be a big deal.
// An intermediate buffer of not-easy-to-predict size is stored at bufPtr.
u32 DrawEngineCommon::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, VertexDecoder *dec, int lowerBound, int upperBound, u32 vertType) {
// First, decode the vertices into a GPU compatible format. This step can be eliminated but will need a separate
// implementation of the vertex decoder.
dec->DecodeVerts(bufPtr, inPtr, lowerBound, upperBound);
// OK, morphing eliminated but bones still remain to be taken care of.
// Let's do a partial software transform where we only do skinning.
VertexReader reader(bufPtr, dec->GetDecVtxFmt(), vertType);
SimpleVertex *sverts = (SimpleVertex *)outPtr;
const u8 defaultColor[4] = {
(u8)gstate.getMaterialAmbientR(),
(u8)gstate.getMaterialAmbientG(),
(u8)gstate.getMaterialAmbientB(),
(u8)gstate.getMaterialAmbientA(),
};
// Let's have two separate loops, one for non skinning and one for skinning.
if (!g_Config.bSoftwareSkinning && (vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE) {
int numBoneWeights = vertTypeGetNumBoneWeights(vertType);
for (int i = lowerBound; i <= upperBound; i++) {
reader.Goto(i);
SimpleVertex &sv = sverts[i];
if (vertType & GE_VTYPE_TC_MASK) {
reader.ReadUV(sv.uv);
}
if (vertType & GE_VTYPE_COL_MASK) {
reader.ReadColor0_8888(sv.color);
} else {
memcpy(sv.color, defaultColor, 4);
}
float nrm[3], pos[3];
float bnrm[3], bpos[3];
if (vertType & GE_VTYPE_NRM_MASK) {
// Normals are generated during tesselation anyway, not sure if any need to supply
reader.ReadNrm(nrm);
} else {
nrm[0] = 0;
nrm[1] = 0;
nrm[2] = 1.0f;
}
reader.ReadPos(pos);
// Apply skinning transform directly
float weights[8];
reader.ReadWeights(weights);
// Skinning
Vec3Packedf psum(0, 0, 0);
Vec3Packedf nsum(0, 0, 0);
for (int w = 0; w < numBoneWeights; w++) {
if (weights[w] != 0.0f) {
Vec3ByMatrix43(bpos, pos, gstate.boneMatrix + w * 12);
Vec3Packedf tpos(bpos);
psum += tpos * weights[w];
Norm3ByMatrix43(bnrm, nrm, gstate.boneMatrix + w * 12);
Vec3Packedf tnorm(bnrm);
nsum += tnorm * weights[w];
}
}
sv.pos = psum;
sv.nrm = nsum;
}
} else {
for (int i = lowerBound; i <= upperBound; i++) {
reader.Goto(i);
SimpleVertex &sv = sverts[i];
if (vertType & GE_VTYPE_TC_MASK) {
reader.ReadUV(sv.uv);
} else {
sv.uv[0] = 0; // This will get filled in during tesselation
sv.uv[1] = 0;
}
if (vertType & GE_VTYPE_COL_MASK) {
reader.ReadColor0_8888(sv.color);
} else {
memcpy(sv.color, defaultColor, 4);
}
if (vertType & GE_VTYPE_NRM_MASK) {
// Normals are generated during tesselation anyway, not sure if any need to supply
reader.ReadNrm((float *)&sv.nrm);
} else {
sv.nrm.x = 0;
sv.nrm.y = 0;
sv.nrm.z = 1.0f;
}
reader.ReadPos((float *)&sv.pos);
}
}
// Okay, there we are! Return the new type (but keep the index bits)
return GE_VTYPE_TC_FLOAT | GE_VTYPE_COL_8888 | GE_VTYPE_NRM_FLOAT | GE_VTYPE_POS_FLOAT | (vertType & (GE_VTYPE_IDX_MASK | GE_VTYPE_THROUGH));
}

View File

@ -1,45 +1,45 @@
// Copyright (c) 2013- PPSSPP 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 or later versions.
// 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 git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#pragma once
#include <vector>
#include "Common/CommonTypes.h"
#include "GPU/Common/GPUDebugInterface.h"
class VertexDecoder;
class DrawEngineCommon {
public:
virtual ~DrawEngineCommon();
bool TestBoundingBox(void* control_points, int vertexCount, u32 vertType);
// TODO: This can be shared once the decoder cache / etc. are.
virtual u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType) = 0;
bool GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices);
static u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, VertexDecoder *dec, int lowerBound, int upperBound, u32 vertType);
protected:
// Vertex collector buffers
u8 *decoded;
u16 *decIndex;
// Copyright (c) 2013- PPSSPP 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 or later versions.
// 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 git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#pragma once
#include <vector>
#include "Common/CommonTypes.h"
#include "GPU/Common/GPUDebugInterface.h"
class VertexDecoder;
class DrawEngineCommon {
public:
virtual ~DrawEngineCommon();
bool TestBoundingBox(void* control_points, int vertexCount, u32 vertType);
// TODO: This can be shared once the decoder cache / etc. are.
virtual u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType) = 0;
bool GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices);
static u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, VertexDecoder *dec, int lowerBound, int upperBound, u32 vertType);
protected:
// Vertex collector buffers
u8 *decoded;
u16 *decIndex;
};

View File

@ -1,6 +1,7 @@
#include "global.h"
#include "fbo.h"
#include "thin3d/d3dx9_loader.h"
#include "Common/CommonFuncs.h"
namespace DX9 {
@ -60,16 +61,14 @@ LPDIRECT3DVERTEXSHADER9 pFramebufferVertexShader = NULL; // Vertex Shader
LPDIRECT3DPIXELSHADER9 pFramebufferPixelShader = NULL; // Pixel Shader
bool CompilePixelShader(const char *code, LPDIRECT3DPIXELSHADER9 *pShader, LPD3DXCONSTANTTABLE *pShaderTable, std::string &errorMessage) {
ID3DXBuffer* pShaderCode = NULL;
ID3DXBuffer* pErrorMsg = NULL;
HRESULT hr = E_FAIL;
ID3DXBuffer *pShaderCode = nullptr;
ID3DXBuffer *pErrorMsg = nullptr;
// Compile pixel shader.
hr = dyn_D3DXCompileShader(code,
HRESULT hr = dyn_D3DXCompileShader(code,
(UINT)strlen(code),
NULL,
NULL,
nullptr,
nullptr,
"main",
"ps_2_0",
0,
@ -80,11 +79,13 @@ bool CompilePixelShader(const char *code, LPDIRECT3DPIXELSHADER9 *pShader, LPD3D
if (pErrorMsg) {
errorMessage = (CHAR *)pErrorMsg->GetBufferPointer();
pErrorMsg->Release();
} else if (FAILED(hr)) {
errorMessage = GetStringErrorMsg(hr);
} else {
errorMessage = "";
}
if (FAILED(hr)) {
if (FAILED(hr) || !pShaderCode) {
if (pShaderCode)
pShaderCode->Release();
return false;
@ -100,16 +101,14 @@ bool CompilePixelShader(const char *code, LPDIRECT3DPIXELSHADER9 *pShader, LPD3D
}
bool CompileVertexShader(const char *code, LPDIRECT3DVERTEXSHADER9 *pShader, LPD3DXCONSTANTTABLE *pShaderTable, std::string &errorMessage) {
ID3DXBuffer* pShaderCode = NULL;
ID3DXBuffer* pErrorMsg = NULL;
HRESULT hr = E_FAIL;
ID3DXBuffer *pShaderCode = nullptr;
ID3DXBuffer *pErrorMsg = nullptr;
// Compile pixel shader.
hr = dyn_D3DXCompileShader(code,
HRESULT hr = dyn_D3DXCompileShader(code,
(UINT)strlen(code),
NULL,
NULL,
nullptr,
nullptr,
"main",
"vs_2_0",
0,
@ -120,11 +119,13 @@ bool CompileVertexShader(const char *code, LPDIRECT3DVERTEXSHADER9 *pShader, LPD
if (pErrorMsg) {
errorMessage = (CHAR *)pErrorMsg->GetBufferPointer();
pErrorMsg->Release();
} else if (FAILED(hr)) {
errorMessage = GetStringErrorMsg(hr);
} else {
errorMessage = "";
}
if (FAILED(hr)) {
if (FAILED(hr) || !pShaderCode) {
if (pShaderCode)
pShaderCode->Release();
return false;
@ -139,22 +140,25 @@ bool CompileVertexShader(const char *code, LPDIRECT3DVERTEXSHADER9 *pShader, LPD
return true;
}
void CompileShaders() {
std::string errorMsg;
bool CompileShaders(std::string &errorMsg) {
if (!CompileVertexShader(vscode, &pFramebufferVertexShader, NULL, errorMsg)) {
OutputDebugStringA(errorMsg.c_str());
DebugBreak();
return false;
}
if (!CompilePixelShader(pscode, &pFramebufferPixelShader, NULL, errorMsg)) {
OutputDebugStringA(errorMsg.c_str());
DebugBreak();
if (pFramebufferVertexShader) {
pFramebufferVertexShader->Release();
}
return false;
}
pD3Ddevice->CreateVertexDeclaration(VertexElements, &pFramebufferVertexDecl);
pD3Ddevice->SetVertexDeclaration(pFramebufferVertexDecl);
pD3Ddevice->CreateVertexDeclaration(SoftTransVertexElements, &pSoftVertexDecl);
return true;
}
void DestroyShaders() {
@ -207,7 +211,8 @@ void DirectxInit(HWND window) {
pD3Ddevice->SetRingBufferParameters( &d3dr );
#endif
CompileShaders();
std::string errorMessage;
CompileShaders(errorMessage);
fbo_init(pD3D);
}

View File

@ -25,7 +25,7 @@ extern LPDIRECT3DPIXELSHADER9 pFramebufferPixelShader; // Pixel Shader
extern IDirect3DVertexDeclaration9* pFramebufferVertexDecl;
extern IDirect3DVertexDeclaration9* pSoftVertexDecl;
void CompileShaders();
bool CompileShaders(std::string &errorMessage);
bool CompilePixelShader(const char *code, LPDIRECT3DPIXELSHADER9 *pShader, ID3DXConstantTable **pShaderTable, std::string &errorMessage);
bool CompileVertexShader(const char *code, LPDIRECT3DVERTEXSHADER9 *pShader, ID3DXConstantTable **pShaderTable, std::string &errorMessage);
void DestroyShaders();

View File

@ -1,195 +1,203 @@
#include "Common/CommonWindows.h"
#include <d3d9.h>
#include "GPU/Directx9/helper/global.h"
#include "GPU/Directx9/helper/fbo.h"
#include "base/logging.h"
#include "util/text/utf8.h"
#include "i18n/i18n.h"
#include "Core/Config.h"
#include "Windows/D3D9Base.h"
#include "thin3d/thin3d.h"
#include "thin3d/d3dx9_loader.h"
static bool has9Ex = false;
static LPDIRECT3D9 d3d;
static LPDIRECT3D9EX d3dEx;
static int adapterId;
static LPDIRECT3DDEVICE9 device;
static LPDIRECT3DDEVICE9EX deviceEx;
static HDC hDC; // Private GDI Device Context
static HGLRC hRC; // Permanent Rendering Context
static HWND hWnd; // Holds Our Window Handle
static int xres, yres;
// TODO: Make config?
static bool enableGLDebug = true;
void D3D9_SwapBuffers() {
if (has9Ex) {
deviceEx->EndScene();
deviceEx->PresentEx(NULL, NULL, NULL, NULL, 0);
deviceEx->BeginScene();
} else {
device->EndScene();
device->Present(NULL, NULL, NULL, NULL);
device->BeginScene();
}
}
Thin3DContext *D3D9_CreateThin3DContext() {
return T3DCreateDX9Context(d3d, d3dEx, adapterId, device, deviceEx);
}
typedef HRESULT (*DIRECT3DCREATE9EX)(UINT, IDirect3D9Ex**);
bool IsWin7OrLater() {
DWORD version = GetVersion();
DWORD major = (DWORD)(LOBYTE(LOWORD(version)));
DWORD minor = (DWORD)(HIBYTE(LOWORD(version)));
return (major > 6) || ((major == 6) && (minor >= 1));
}
bool D3D9_Init(HWND hWnd, bool windowed, std::string *error_message) {
DIRECT3DCREATE9EX g_pfnCreate9ex;
HMODULE hD3D9 = LoadLibrary(TEXT("d3d9.dll"));
if (!hD3D9) {
ELOG("Missing d3d9.dll");
*error_message = "D3D9.dll missing";
return false;
}
g_pfnCreate9ex = (DIRECT3DCREATE9EX)GetProcAddress(hD3D9, "Direct3DCreate9Ex");
has9Ex = (g_pfnCreate9ex != NULL);
if (has9Ex) {
HRESULT result = g_pfnCreate9ex(D3D_SDK_VERSION, &d3dEx);
d3d = d3dEx;
if (FAILED(result)) {
*error_message = "D3D9Ex available but context creation failed";
return false;
}
} else {
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if (!d3d) {
*error_message = "Failed to create D3D9 context";
return false;
}
}
FreeLibrary(hD3D9);
D3DCAPS9 d3dCaps;
D3DDISPLAYMODE d3ddm;
if (FAILED(d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm))) {
*error_message = "GetAdapterDisplayMode failed";
d3d->Release();
return false;
}
adapterId = D3DADAPTER_DEFAULT;
if (FAILED(d3d->GetDeviceCaps(adapterId, D3DDEVTYPE_HAL, &d3dCaps))) {
*error_message = "GetDeviceCaps failed (???)";
d3d->Release();
return false;
}
HRESULT hr;
if (FAILED(hr = d3d->CheckDeviceFormat(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
d3ddm.Format,
D3DUSAGE_DEPTHSTENCIL,
D3DRTYPE_SURFACE,
D3DFMT_D24S8))) {
if (hr == D3DERR_NOTAVAILABLE) {
*error_message = "D24S8 depth/stencil not available";
d3d->Release();
return false;
}
}
DWORD dwBehaviorFlags = D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE;
if (d3dCaps.VertexProcessingCaps != 0)
dwBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
else
dwBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
RECT rc;
GetClientRect(hWnd, &rc);
int xres = rc.right - rc.left;
int yres = rc.bottom - rc.top;
D3DPRESENT_PARAMETERS pp;
memset(&pp, 0, sizeof(pp));
pp.BackBufferWidth = xres;
pp.BackBufferHeight = yres;
pp.BackBufferFormat = d3ddm.Format;
pp.MultiSampleType = D3DMULTISAMPLE_NONE;
pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
pp.Windowed = windowed;
pp.hDeviceWindow = hWnd;
pp.EnableAutoDepthStencil = true;
pp.AutoDepthStencilFormat = D3DFMT_D24S8;
pp.PresentationInterval = (g_Config.bVSync) ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
if (has9Ex) {
if (windowed && IsWin7OrLater()) {
// This new flip mode gives higher performance.
// TODO: This makes it slower?
//pp.BackBufferCount = 2;
//pp.SwapEffect = D3DSWAPEFFECT_FLIPEX;
}
hr = d3dEx->CreateDeviceEx(adapterId, D3DDEVTYPE_HAL, hWnd, dwBehaviorFlags, &pp, NULL, &deviceEx);
device = deviceEx;
} else {
hr = d3d->CreateDevice(adapterId, D3DDEVTYPE_HAL, hWnd, dwBehaviorFlags, &pp, &device);
}
if (FAILED(hr)) {
*error_message = "Failed to create D3D device";
if (has9Ex) {
d3dEx->Release();
} else {
d3d->Release();
}
return false;
}
device->BeginScene();
DX9::pD3Ddevice = device;
DX9::pD3DdeviceEx = deviceEx;
LoadD3DX9Dynamic();
DX9::CompileShaders();
DX9::fbo_init(d3d);
if (deviceEx && IsWin7OrLater()) {
// TODO: This makes it slower?
//deviceEx->SetMaximumFrameLatency(1);
}
return true;
}
void D3D9_Resize(HWND window) {
// TODO!
}
void D3D9_Shutdown() {
DX9::DestroyShaders();
DX9::fbo_shutdown();
device->EndScene();
device->Release();
d3d->Release();
DX9::pD3Ddevice = nullptr;
DX9::pD3DdeviceEx = nullptr;
device = nullptr;
hWnd = nullptr;
}
#include "Common/CommonWindows.h"
#include <d3d9.h>
#include "GPU/Directx9/helper/global.h"
#include "GPU/Directx9/helper/fbo.h"
#include "base/logging.h"
#include "util/text/utf8.h"
#include "i18n/i18n.h"
#include "Core/Config.h"
#include "Windows/D3D9Base.h"
#include "thin3d/thin3d.h"
#include "thin3d/d3dx9_loader.h"
static bool has9Ex = false;
static LPDIRECT3D9 d3d;
static LPDIRECT3D9EX d3dEx;
static int adapterId;
static LPDIRECT3DDEVICE9 device;
static LPDIRECT3DDEVICE9EX deviceEx;
static HDC hDC; // Private GDI Device Context
static HGLRC hRC; // Permanent Rendering Context
static HWND hWnd; // Holds Our Window Handle
static int xres, yres;
// TODO: Make config?
static bool enableGLDebug = true;
void D3D9_SwapBuffers() {
if (has9Ex) {
deviceEx->EndScene();
deviceEx->PresentEx(NULL, NULL, NULL, NULL, 0);
deviceEx->BeginScene();
} else {
device->EndScene();
device->Present(NULL, NULL, NULL, NULL);
device->BeginScene();
}
}
Thin3DContext *D3D9_CreateThin3DContext() {
return T3DCreateDX9Context(d3d, d3dEx, adapterId, device, deviceEx);
}
typedef HRESULT (*DIRECT3DCREATE9EX)(UINT, IDirect3D9Ex**);
bool IsWin7OrLater() {
DWORD version = GetVersion();
DWORD major = (DWORD)(LOBYTE(LOWORD(version)));
DWORD minor = (DWORD)(HIBYTE(LOWORD(version)));
return (major > 6) || ((major == 6) && (minor >= 1));
}
bool D3D9_Init(HWND hWnd, bool windowed, std::string *error_message) {
DIRECT3DCREATE9EX g_pfnCreate9ex;
HMODULE hD3D9 = LoadLibrary(TEXT("d3d9.dll"));
if (!hD3D9) {
ELOG("Missing d3d9.dll");
*error_message = "D3D9.dll missing";
return false;
}
g_pfnCreate9ex = (DIRECT3DCREATE9EX)GetProcAddress(hD3D9, "Direct3DCreate9Ex");
has9Ex = (g_pfnCreate9ex != NULL);
if (has9Ex) {
HRESULT result = g_pfnCreate9ex(D3D_SDK_VERSION, &d3dEx);
d3d = d3dEx;
if (FAILED(result)) {
*error_message = "D3D9Ex available but context creation failed";
return false;
}
} else {
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if (!d3d) {
*error_message = "Failed to create D3D9 context";
return false;
}
}
FreeLibrary(hD3D9);
D3DCAPS9 d3dCaps;
D3DDISPLAYMODE d3ddm;
if (FAILED(d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm))) {
*error_message = "GetAdapterDisplayMode failed";
d3d->Release();
return false;
}
adapterId = D3DADAPTER_DEFAULT;
if (FAILED(d3d->GetDeviceCaps(adapterId, D3DDEVTYPE_HAL, &d3dCaps))) {
*error_message = "GetDeviceCaps failed (???)";
d3d->Release();
return false;
}
HRESULT hr;
if (FAILED(hr = d3d->CheckDeviceFormat(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
d3ddm.Format,
D3DUSAGE_DEPTHSTENCIL,
D3DRTYPE_SURFACE,
D3DFMT_D24S8))) {
if (hr == D3DERR_NOTAVAILABLE) {
*error_message = "D24S8 depth/stencil not available";
d3d->Release();
return false;
}
}
DWORD dwBehaviorFlags = D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE;
if (d3dCaps.VertexProcessingCaps != 0)
dwBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
else
dwBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
RECT rc;
GetClientRect(hWnd, &rc);
int xres = rc.right - rc.left;
int yres = rc.bottom - rc.top;
D3DPRESENT_PARAMETERS pp;
memset(&pp, 0, sizeof(pp));
pp.BackBufferWidth = xres;
pp.BackBufferHeight = yres;
pp.BackBufferFormat = d3ddm.Format;
pp.MultiSampleType = D3DMULTISAMPLE_NONE;
pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
pp.Windowed = windowed;
pp.hDeviceWindow = hWnd;
pp.EnableAutoDepthStencil = true;
pp.AutoDepthStencilFormat = D3DFMT_D24S8;
pp.PresentationInterval = (g_Config.bVSync) ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
if (has9Ex) {
if (windowed && IsWin7OrLater()) {
// This new flip mode gives higher performance.
// TODO: This makes it slower?
//pp.BackBufferCount = 2;
//pp.SwapEffect = D3DSWAPEFFECT_FLIPEX;
}
hr = d3dEx->CreateDeviceEx(adapterId, D3DDEVTYPE_HAL, hWnd, dwBehaviorFlags, &pp, NULL, &deviceEx);
device = deviceEx;
} else {
hr = d3d->CreateDevice(adapterId, D3DDEVTYPE_HAL, hWnd, dwBehaviorFlags, &pp, &device);
}
if (FAILED(hr)) {
*error_message = "Failed to create D3D device";
d3d->Release();
return false;
}
device->BeginScene();
DX9::pD3Ddevice = device;
DX9::pD3DdeviceEx = deviceEx;
LoadD3DX9Dynamic();
if (!DX9::CompileShaders(*error_message)) {
*error_message = "Unable to compile shaders: " + *error_message;
device->EndScene();
device->Release();
d3d->Release();
DX9::pD3Ddevice = nullptr;
DX9::pD3DdeviceEx = nullptr;
device = nullptr;
UnloadD3DXDynamic();
return false;
}
DX9::fbo_init(d3d);
if (deviceEx && IsWin7OrLater()) {
// TODO: This makes it slower?
//deviceEx->SetMaximumFrameLatency(1);
}
return true;
}
void D3D9_Resize(HWND window) {
// TODO!
}
void D3D9_Shutdown() {
DX9::DestroyShaders();
DX9::fbo_shutdown();
device->EndScene();
device->Release();
d3d->Release();
UnloadD3DXDynamic();
DX9::pD3Ddevice = nullptr;
DX9::pD3DdeviceEx = nullptr;
device = nullptr;
hWnd = nullptr;
}

View File

@ -3,11 +3,13 @@
#include "base/timeutil.h"
#include "base/NativeApp.h"
#include "base/mutex.h"
#include "i18n/i18n.h"
#include "util/text/utf8.h"
#include "Common/Log.h"
#include "Common/StringUtils.h"
#include "../Globals.h"
#include "Windows/EmuThread.h"
#include "Windows/W32Util/Misc.h"
#include "Windows/WndMainWindow.h"
#include "Windows/resource.h"
#include "Core/Reporting.h"
@ -126,12 +128,38 @@ unsigned int WINAPI TheThread(void *)
std::string error_string;
if (!host->InitGraphics(&error_string)) {
I18NCategory *err = GetI18NCategory("Error");
Reporting::ReportMessage("Graphics init error: %s", error_string.c_str());
std::string full_error = StringFromFormat( "Failed initializing OpenGL. Try upgrading your graphics drivers.\n\nError message:\n\n%s", error_string.c_str());
MessageBox(0, ConvertUTF8ToWString(full_error).c_str(), L"OpenGL Error", MB_OK | MB_ICONERROR);
const char *defaultErrorOpenGL = "Failed initializing graphics. Try upgrading your graphics drivers.\n\nWould you like to try switching to DirectX 9?\n\nError message:";
const char *defaultErrorDirect3D9 = "Failed initializing graphics. Try upgrading your graphics drivers.\n\nWould you like to try switching to OpenGL?\n\nError message:";
const char *genericError;
int nextBackend = GPU_BACKEND_DIRECT3D9;
switch (g_Config.iGPUBackend) {
case GPU_BACKEND_DIRECT3D9:
nextBackend = GPU_BACKEND_OPENGL;
genericError = err->T("GenericDirect3D9Error", defaultErrorDirect3D9);
break;
case GPU_BACKEND_OPENGL:
default:
nextBackend = GPU_BACKEND_DIRECT3D9;
genericError = err->T("GenericOpenGLError", defaultErrorOpenGL);
break;
}
std::string full_error = StringFromFormat("%s\n\n%s", genericError, error_string.c_str());
std::wstring title = ConvertUTF8ToWString(err->T("GenericGraphicsError", "Graphics Error"));
bool yes = IDYES == MessageBox(0, ConvertUTF8ToWString(full_error).c_str(), title.c_str(), MB_ICONERROR | MB_YESNO);
ERROR_LOG(BOOT, full_error.c_str());
// No safe way out without OpenGL.
if (yes) {
// Change the config to the alternative and restart.
g_Config.iGPUBackend = nextBackend;
g_Config.Save();
W32Util::ExitAndRestart();
}
// No safe way out without graphics.
ExitProcess(1);
}

View File

@ -162,7 +162,7 @@ bool GL_Init(HWND window, std::string *error_message) {
}
// Avoid further error messages. Let's just bail, it's safe, and we can't continue.
ExitProcess(0);
ExitProcess(1);
}
if (GLEW_OK != glewInit()) {

View File

@ -1,336 +1,336 @@
// Used by ppsspp.rc
//
#define VS_USER_DEFINED 100
#define IDR_MENU1 101
#define IDD_DISASM 102
#define IDC_FUNCTIONLIST 103
#define IDC_DISASMVIEW 104
#define IDC_GOTOPC 105
#define IDC_LEFTTABS 106
#define IDC_RAM 107
#define IDC_STEPOVER 108
#define IDC_TABDATATYPE 109
#define IDC_CALLSTACK 110
#define ID_MEMVIEW_GOTOINDISASM 112
#define ID_DISASM_DYNARECRESULTS 113
#define IDI_PPSSPP 115
#define IDD_CONFIG 116
#define IDI_STOPDISABLE 118
#define ID_DEBUG_DISASSEMBLY 119
#define ID_DEBUG_REGISTERS 120
#define WHEEL_DELTA 120
#define ID_DEBUG_LOG 121
#define ID_DEBUG_BREAKPOINTS 122
#define ID_FILE_LOADSTATEFILE 126
#define ID_FILE_SAVESTATEFILE 127
#define ID_EMULATION_RESET 130
#define IDD_ABOUTBOX 133
#define ID_DEBUG_LOADMAPFILE 134
#define ID_CONFIG_RESOLUTION 141
#define ID_OPTIONS_FULLSCREEN 154
#define ID_OPTIONS_SETTINGS 155
#define ID_OPTIONS_SHOWERRORS 158
#define ID_PLUGINS_LOADDEFAULTPLUGINS 159
#define IDD_MEMORY 160
#define ID_DEBUG_MEMORYVIEW 161
#define IDR_ACCELS 162
#define ID_FILE_BOOTDVD 166
#define ID_OPTIONS_ENABLEFRAMEBUFFER 167
#define IDR_POPUPMENUS 169
#define ID_DEBUG_MEMORYCHECKS 173
#define IDD_DIALOG2 186
#define IDD_MEMORYSEARCH 187
#define ID_DEBUG_MEMORYSEARCH 188
#define ID_DEBUG_EXPERIMENT 189
#define IDR_MENU2 190
#define ID_DISASM_GOTOINMEMORYVIEW 197
#define ID_DISASM_TOGGLEBREAKPOINT 198
#define ID_MEMVIEW_DUMP 199
#define ID_OPTIONS_LOGGPFIFO 200
#define ID_VIEW_TOOLBAR202 202
#define ID_VIEW_STATUSBAR 203
#define ID_HELP_INDEX204 204
#define ID_HELP_ 206
#define ID_HELP_HOMEPAGE 208
#define ID_DEBUG_COMPILESIGNATUREFILE 209
#define ID_DEBUG_USESIGNATUREFILE 210
#define ID_DEBUG_UNLOADALLSYMBOLS 211
#define ID_DEBUG_RESETSYMBOLTABLE 212
#define IDI_STOP 223
#define IDD_INPUTBOX 226
#define IDD_VFPU 231
#define IDD_BREAKPOINT 233
#define ID_FILE_LOAD_DIR 234
#define IDR_DEBUGACCELS 237
#define ID_DEBUG_DISPLAYMEMVIEW 238
#define ID_DEBUG_DISPLAYBREAKPOINTLIST 239
#define ID_DEBUG_DISPLAYTHREADLIST 240
#define ID_DEBUG_DISPLAYSTACKFRAMELIST 241
#define ID_DEBUG_ADDBREAKPOINT 242
#define ID_DEBUG_STEPOVER 243
#define ID_DEBUG_STEPINTO 244
#define ID_DEBUG_RUNTOLINE 245
#define ID_DEBUG_STEPOUT 246
#define ID_DEBUG_DSIPLAYREGISTERLIST 247
#define ID_DEBUG_DSIPLAYFUNCTIONLIST 248
#define ID_MEMVIEW_COPYADDRESS 249
#define IDD_GEDEBUGGER 250
#define IDD_TABDISPLAYLISTS 251
#define IDD_GEDBG_TAB_VALUES 252
#define IDD_DUMPMEMORY 253
#define IDD_GEDBG_TAB_VERTICES 254
#define IDD_GEDBG_TAB_MATRICES 255
#define IDC_STOPGO 1001
#define IDC_ADDRESS 1002
#define IDC_DEBUG_COUNT 1003
#define IDC_MEMORY 1006
#define IDC_SH4REGISTERS 1007
#define IDC_REGISTERS 1007
#define IDC_BREAKPOINTS 1008
#define IDC_STEP 1009
#define IDC_VERSION 1010
#define IDC_UP 1014
#define IDC_DOWN 1015
#define IDC_BREAKPOINTS_LIST 1015
#define IDC_ADD 1016
#define IDC_BREAKPOINT_EDIT 1017
#define IDC_REMOVE 1018
#define IDC_REMOVE_ALL 1019
#define IDC_REGISTER_TAB 1019
#define IDC_HIDE 1020
#define IDC_TOGGLEBREAKPOINT 1049
#define IDC_STAGE 1059
#define IDC_MEMVIEW 1069
#define IDC_GOTOLR 1070
#define IDC_GOTOINT 1071
#define IDC_MEMSORT 1073
#define IDC_ALLFUNCTIONS 1075
#define IDC_RESULTS 1093
#define IDC_SYMBOLS 1097
#define IDC_X86ASM 1098
#define IDC_INPUTBOX 1098
#define IDC_MODENORMAL 1099
#define IDC_MODESYMBOLS 1100
#define IDC_LOG_SHOW 1101
#define IDC_UPDATELOG 1108
#define IDC_SETPC 1118
#define IDC_UPDATEMISC 1134
#define IDC_CODEADDRESS 1135
#define IDC_BLOCKNUMBER 1136
#define IDC_PREVBLOCK 1138
#define IDC_REGIONS 1142
#define IDC_REGLIST 1146
#define IDC_VALUENAME 1148
#define IDC_FILELIST 1150
#define IDC_BROWSE 1159
#define IDC_SHOWVFPU 1161
#define IDC_LISTCONTROLS 1162
#define IDC_FORCE_INPUT_DEVICE 1163
#define IDC_BREAKPOINTLIST 1164
#define IDC_DEBUGMEMVIEW 1165
#define IDC_BREAKPOINT_OK 1166
#define IDC_BREAKPOINT_CANCEL 1167
#define IDC_BREAKPOINT_ADDRESS 1168
#define IDC_BREAKPOINT_SIZE 1169
#define IDC_BREAKPOINT_CONDITION 1170
#define IDC_BREAKPOINT_EXECUTE 1171
#define IDC_BREAKPOINT_MEMORY 1172
#define IDC_BREAKPOINT_READ 1173
#define IDC_BREAKPOINT_WRITE 1174
#define IDC_BREAKPOINT_ENABLED 1175
#define IDC_BREAKPOINT_LOG 1176
#define IDC_BREAKPOINT_ONCHANGE 1177
#define IDC_THREADLIST 1178
#define IDC_THREADNAME 1179
#define IDC_DISASMSTATUSBAR 1180
#define IDC_STACKFRAMES 1181
#define IDC_GEDBG_VALUES 1182
#define IDC_DUMP_USERMEMORY 1183
#define IDC_DUMP_VRAM 1184
#define IDC_DUMP_SCRATCHPAD 1185
#define IDC_DUMP_CUSTOMRANGE 1186
#define IDC_DUMP_STARTADDRESS 1187
#define IDC_DUMP_SIZE 1188
#define IDC_DUMP_FILENAME 1189
#define IDC_DUMP_BROWSEFILENAME 1190
#define IDC_GEDBG_FRAMEBUFADDR 1191
#define IDC_GEDBG_TEXADDR 1192
#define IDC_GEDBG_FBTABS 1193
#define IDC_GEDBG_VERTICES 1194
#define IDC_GEDBG_RAWVERTS 1195
#define IDC_GEDBG_MATRICES 1196
#define ID_SHADERS_BASE 5000
#define ID_FILE_EXIT 40000
#define ID_DEBUG_SAVEMAPFILE 40001
#define ID_DISASM_ADDHLE 40002
#define ID_FUNCLIST_KILLFUNCTION 40003
#define ID_DISASM_RUNTOHERE 40004
#define ID_MEMVIEW_COPYVALUE_8 40005
#define ID_DISASM_COPYINSTRUCTIONDISASM 40006
#define ID_DISASM_COPYINSTRUCTIONHEX 40007
#define ID_EMULATION_SPEEDLIMIT 40008
#define ID_TOGGLE_PAUSE 40009
#define ID_EMULATION_STOP 40010
#define ID_FILE_LOAD 40011
#define ID_HELP_ABOUT 40012
#define ID_DISASM_FOLLOWBRANCH 40013
#define ID_DEBUG_IGNOREILLEGALREADS 40014
#define ID_DISASM_COPYADDRESS 40015
#define ID_REGLIST_GOTOINMEMORYVIEW 40016
#define ID_REGLIST_COPYVALUE 40017
#define ID_REGLIST_COPY 40018
#define ID_REGLIST_GOTOINDISASM 40019
#define ID_REGLIST_CHANGE 40020
#define ID_DISASM_RENAMEFUNCTION 40021
#define ID_DISASM_SETPCTOHERE 40022
#define ID_HELP_OPENWEBSITE 40023
#define ID_OPTIONS_SCREENAUTO 40024
#define ID_OPTIONS_SCREEN1X 40025
#define ID_OPTIONS_SCREEN2X 40026
#define ID_OPTIONS_SCREEN3X 40027
#define ID_OPTIONS_SCREEN4X 40028
#define ID_OPTIONS_SCREEN5X 40029
#define ID_OPTIONS_HARDWARETRANSFORM 40030
#define IDC_STEPHLE 40032
#define ID_OPTIONS_LINEARFILTERING 40033
#define ID_FILE_QUICKSAVESTATE 40034
#define ID_FILE_QUICKLOADSTATE 40035
#define ID_FILE_QUICKSAVESTATE_HC 40036
#define ID_FILE_QUICKLOADSTATE_HC 40037
#define ID_OPTIONS_CONTROLS 40038
#define ID_DEBUG_RUNONLOAD 40039
#define ID_DEBUG_DUMPNEXTFRAME 40040
#define ID_OPTIONS_VERTEXCACHE 40041
#define ID_OPTIONS_SHOWFPS 40042
#define ID_OPTIONS_STRETCHDISPLAY 40043
#define ID_OPTIONS_FRAMESKIP 40044
#define IDC_MEMCHECK 40045
#define ID_FILE_MEMSTICK 40046
#define ID_FILE_LOAD_MEMSTICK 40047
#define ID_EMULATION_SOUND 40048
#define ID_OPTIONS_MIPMAP 40049
#define ID_TEXTURESCALING_OFF 40050
#define ID_TEXTURESCALING_XBRZ 40051
#define ID_TEXTURESCALING_HYBRID 40052
#define ID_TEXTURESCALING_2X 40053
#define ID_TEXTURESCALING_3X 40054
#define ID_TEXTURESCALING_4X 40055
#define ID_TEXTURESCALING_5X 40056
#define ID_TEXTURESCALING_DEPOSTERIZE 40057
#define ID_TEXTURESCALING_BICUBIC 40058
#define ID_TEXTURESCALING_HYBRID_BICUBIC 40059
#define IDB_IMAGE_PSP 40060
#define IDC_STATIC_IMAGE_PSP 40061
#define ID_CONTROLS_KEY_DISABLE 40062
#define ID_OPTIONS_TOPMOST 40063
#define ID_HELP_OPENFORUM 40064
#define ID_OPTIONS_VSYNC 40065
#define ID_DEBUG_TAKESCREENSHOT 40066
#define ID_OPTIONS_TEXTUREFILTERING_AUTO 40067
#define ID_OPTIONS_NEARESTFILTERING 40068
#define ID_DISASM_DISASSEMBLETOFILE 40069
#define ID_OPTIONS_LINEARFILTERING_CG 40070
#define ID_DISASM_DISABLEBREAKPOINT 40071
#define ID_DISASM_THREAD_FORCERUN 40072
#define ID_DISASM_THREAD_KILL 40073
#define ID_FILE_SAVESTATE_NEXT_SLOT 40074
#define ID_FILE_SAVESTATE_NEXT_SLOT_HC 40075
#define ID_OPTIONS_READFBOTOMEMORYGPU 40076
#define ID_OPTIONS_READFBOTOMEMORYCPU 40077
#define ID_OPTIONS_NONBUFFEREDRENDERING 40078
#define ID_OPTIONS_FRAMESKIP_0 40079
#define ID_OPTIONS_FRAMESKIP_1 40080
#define ID_OPTIONS_FRAMESKIP_2 40081
#define ID_OPTIONS_FRAMESKIP_3 40082
#define ID_OPTIONS_FRAMESKIP_4 40083
#define ID_OPTIONS_FRAMESKIP_5 40084
#define ID_OPTIONS_FRAMESKIP_6 40085
#define ID_OPTIONS_FRAMESKIP_7 40086
#define ID_OPTIONS_FRAMESKIP_8 40087
#define ID_OPTIONS_FRAMESKIP_AUTO 40088
#define ID_OPTIONS_FRAMESKIPDUMMY 40089
#define ID_OPTIONS_RESOLUTIONDUMMY 40090
#define ID_DISASM_ASSEMBLE 40091
#define ID_DISASM_ADDNEWBREAKPOINT 40092
#define ID_DISASM_EDITBREAKPOINT 40093
#define ID_EMULATION_CHEATS 40096
#define ID_HELP_CHINESE_FORUM 40097
#define ID_OPTIONS_MORE_SETTINGS 40098
#define ID_FILE_SAVESTATE_SLOT_1 40099
#define ID_FILE_SAVESTATE_SLOT_2 40100
#define ID_FILE_SAVESTATE_SLOT_3 40101
#define ID_FILE_SAVESTATE_SLOT_4 40102
#define ID_FILE_SAVESTATE_SLOT_5 40103
#define ID_OPTIONS_WINDOW1X 40104
#define ID_OPTIONS_WINDOW2X 40105
#define ID_OPTIONS_WINDOW3X 40106
#define ID_OPTIONS_WINDOW4X 40107
#define ID_OPTIONS_WINDOW5X 40108
#define ID_OPTIONS_BUFFEREDRENDERING 40109
#define ID_DEBUG_SHOWDEBUGSTATISTICS 40110
#define ID_OPTIONS_SCREEN6X 40111
#define ID_OPTIONS_SCREEN7X 40112
#define ID_OPTIONS_SCREEN8X 40113
#define ID_OPTIONS_SCREEN9X 40114
#define ID_OPTIONS_SCREEN10X 40115
#define ID_DEBUG_GEDEBUGGER 40116
#define IDC_GEDBG_STEPDRAW 40117
#define IDC_GEDBG_RESUME 40118
#define IDC_GEDBG_FRAME 40119
#define IDC_GEDBG_MAINTAB 40120
#define IDC_GEDBG_TEX 40121
#define IDC_GEDBG_STEP 40122
#define IDC_GEDBG_LISTS_ALLLISTS 40123
#define IDC_GEDBG_LISTS_STACK 40124
#define IDC_GEDBG_LISTS_SELECTEDLIST 40125
#define ID_OPTIONS_FXAA 40126
#define IDC_DEBUG_BOTTOMTABS 40127
#define ID_DEBUG_HIDEBOTTOMTABS 40128
#define ID_DEBUG_TOGGLEBOTTOMTABTITLES 40129
#define ID_GEDBG_SETSTALLADDR 40130
#define ID_GEDBG_GOTOPC 40131
#define ID_GEDBG_GOTOADDR 40132
#define IDC_GEDBG_STEPTEX 40133
#define IDC_GEDBG_STEPFRAME 40134
#define IDC_GEDBG_BREAKTEX 40135
#define ID_OPTIONS_PAUSE_FOCUS 40136
#define ID_TEXTURESCALING_AUTO 40137
#define IDC_GEDBG_STEPPRIM 40138
#define ID_DISASM_ADDFUNCTION 40139
#define ID_DISASM_REMOVEFUNCTION 40140
#define ID_OPTIONS_LANGUAGE 40141
#define ID_MEMVIEW_COPYVALUE_16 40142
#define ID_MEMVIEW_COPYVALUE_32 40143
#define ID_EMULATION_SWITCH_UMD 40144
#define ID_DEBUG_EXTRACTFILE 40145
#define ID_OPTIONS_IGNOREWINKEY 40146
#define IDC_MODULELIST 40147
#define IDC_GEDBG_TEXLEVELDOWN 40148
#define IDC_GEDBG_TEXLEVELUP 40149
#define ID_DEBUG_LOADSYMFILE 40150
#define ID_DEBUG_SAVESYMFILE 40151
#define ID_OPTIONS_BUFLINEARFILTER 40152
#define ID_OPTIONS_BUFNEARESTFILTER 40153
#define ID_OPTIONS_DIRECTX 40154
#define ID_OPTIONS_OPENGL 40155
// Dummy option to let the buffered rendering hotkey cycle through all the options.
#define ID_OPTIONS_BUFFEREDRENDERINGDUMMY 40500
#define IDC_STEPOUT 40501
#define ID_HELP_BUYGOLD 40502
#define IDC_STATIC -1
// Next default values for new objects
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 256
#define _APS_NEXT_COMMAND_VALUE 40152
#define _APS_NEXT_CONTROL_VALUE 1197
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
// Used by ppsspp.rc
//
#define VS_USER_DEFINED 100
#define IDR_MENU1 101
#define IDD_DISASM 102
#define IDC_FUNCTIONLIST 103
#define IDC_DISASMVIEW 104
#define IDC_GOTOPC 105
#define IDC_LEFTTABS 106
#define IDC_RAM 107
#define IDC_STEPOVER 108
#define IDC_TABDATATYPE 109
#define IDC_CALLSTACK 110
#define ID_MEMVIEW_GOTOINDISASM 112
#define ID_DISASM_DYNARECRESULTS 113
#define IDI_PPSSPP 115
#define IDD_CONFIG 116
#define IDI_STOPDISABLE 118
#define ID_DEBUG_DISASSEMBLY 119
#define ID_DEBUG_REGISTERS 120
#define WHEEL_DELTA 120
#define ID_DEBUG_LOG 121
#define ID_DEBUG_BREAKPOINTS 122
#define ID_FILE_LOADSTATEFILE 126
#define ID_FILE_SAVESTATEFILE 127
#define ID_EMULATION_RESET 130
#define IDD_ABOUTBOX 133
#define ID_DEBUG_LOADMAPFILE 134
#define ID_CONFIG_RESOLUTION 141
#define ID_OPTIONS_FULLSCREEN 154
#define ID_OPTIONS_SETTINGS 155
#define ID_OPTIONS_SHOWERRORS 158
#define ID_PLUGINS_LOADDEFAULTPLUGINS 159
#define IDD_MEMORY 160
#define ID_DEBUG_MEMORYVIEW 161
#define IDR_ACCELS 162
#define ID_FILE_BOOTDVD 166
#define ID_OPTIONS_ENABLEFRAMEBUFFER 167
#define IDR_POPUPMENUS 169
#define ID_DEBUG_MEMORYCHECKS 173
#define IDD_DIALOG2 186
#define IDD_MEMORYSEARCH 187
#define ID_DEBUG_MEMORYSEARCH 188
#define ID_DEBUG_EXPERIMENT 189
#define IDR_MENU2 190
#define ID_DISASM_GOTOINMEMORYVIEW 197
#define ID_DISASM_TOGGLEBREAKPOINT 198
#define ID_MEMVIEW_DUMP 199
#define ID_OPTIONS_LOGGPFIFO 200
#define ID_VIEW_TOOLBAR202 202
#define ID_VIEW_STATUSBAR 203
#define ID_HELP_INDEX204 204
#define ID_HELP_ 206
#define ID_HELP_HOMEPAGE 208
#define ID_DEBUG_COMPILESIGNATUREFILE 209
#define ID_DEBUG_USESIGNATUREFILE 210
#define ID_DEBUG_UNLOADALLSYMBOLS 211
#define ID_DEBUG_RESETSYMBOLTABLE 212
#define IDI_STOP 223
#define IDD_INPUTBOX 226
#define IDD_VFPU 231
#define IDD_BREAKPOINT 233
#define ID_FILE_LOAD_DIR 234
#define IDR_DEBUGACCELS 237
#define ID_DEBUG_DISPLAYMEMVIEW 238
#define ID_DEBUG_DISPLAYBREAKPOINTLIST 239
#define ID_DEBUG_DISPLAYTHREADLIST 240
#define ID_DEBUG_DISPLAYSTACKFRAMELIST 241
#define ID_DEBUG_ADDBREAKPOINT 242
#define ID_DEBUG_STEPOVER 243
#define ID_DEBUG_STEPINTO 244
#define ID_DEBUG_RUNTOLINE 245
#define ID_DEBUG_STEPOUT 246
#define ID_DEBUG_DSIPLAYREGISTERLIST 247
#define ID_DEBUG_DSIPLAYFUNCTIONLIST 248
#define ID_MEMVIEW_COPYADDRESS 249
#define IDD_GEDEBUGGER 250
#define IDD_TABDISPLAYLISTS 251
#define IDD_GEDBG_TAB_VALUES 252
#define IDD_DUMPMEMORY 253
#define IDD_GEDBG_TAB_VERTICES 254
#define IDD_GEDBG_TAB_MATRICES 255
#define IDC_STOPGO 1001
#define IDC_ADDRESS 1002
#define IDC_DEBUG_COUNT 1003
#define IDC_MEMORY 1006
#define IDC_SH4REGISTERS 1007
#define IDC_REGISTERS 1007
#define IDC_BREAKPOINTS 1008
#define IDC_STEP 1009
#define IDC_VERSION 1010
#define IDC_UP 1014
#define IDC_DOWN 1015
#define IDC_BREAKPOINTS_LIST 1015
#define IDC_ADD 1016
#define IDC_BREAKPOINT_EDIT 1017
#define IDC_REMOVE 1018
#define IDC_REMOVE_ALL 1019
#define IDC_REGISTER_TAB 1019
#define IDC_HIDE 1020
#define IDC_TOGGLEBREAKPOINT 1049
#define IDC_STAGE 1059
#define IDC_MEMVIEW 1069
#define IDC_GOTOLR 1070
#define IDC_GOTOINT 1071
#define IDC_MEMSORT 1073
#define IDC_ALLFUNCTIONS 1075
#define IDC_RESULTS 1093
#define IDC_SYMBOLS 1097
#define IDC_X86ASM 1098
#define IDC_INPUTBOX 1098
#define IDC_MODENORMAL 1099
#define IDC_MODESYMBOLS 1100
#define IDC_LOG_SHOW 1101
#define IDC_UPDATELOG 1108
#define IDC_SETPC 1118
#define IDC_UPDATEMISC 1134
#define IDC_CODEADDRESS 1135
#define IDC_BLOCKNUMBER 1136
#define IDC_PREVBLOCK 1138
#define IDC_REGIONS 1142
#define IDC_REGLIST 1146
#define IDC_VALUENAME 1148
#define IDC_FILELIST 1150
#define IDC_BROWSE 1159
#define IDC_SHOWVFPU 1161
#define IDC_LISTCONTROLS 1162
#define IDC_FORCE_INPUT_DEVICE 1163
#define IDC_BREAKPOINTLIST 1164
#define IDC_DEBUGMEMVIEW 1165
#define IDC_BREAKPOINT_OK 1166
#define IDC_BREAKPOINT_CANCEL 1167
#define IDC_BREAKPOINT_ADDRESS 1168
#define IDC_BREAKPOINT_SIZE 1169
#define IDC_BREAKPOINT_CONDITION 1170
#define IDC_BREAKPOINT_EXECUTE 1171
#define IDC_BREAKPOINT_MEMORY 1172
#define IDC_BREAKPOINT_READ 1173
#define IDC_BREAKPOINT_WRITE 1174
#define IDC_BREAKPOINT_ENABLED 1175
#define IDC_BREAKPOINT_LOG 1176
#define IDC_BREAKPOINT_ONCHANGE 1177
#define IDC_THREADLIST 1178
#define IDC_THREADNAME 1179
#define IDC_DISASMSTATUSBAR 1180
#define IDC_STACKFRAMES 1181
#define IDC_GEDBG_VALUES 1182
#define IDC_DUMP_USERMEMORY 1183
#define IDC_DUMP_VRAM 1184
#define IDC_DUMP_SCRATCHPAD 1185
#define IDC_DUMP_CUSTOMRANGE 1186
#define IDC_DUMP_STARTADDRESS 1187
#define IDC_DUMP_SIZE 1188
#define IDC_DUMP_FILENAME 1189
#define IDC_DUMP_BROWSEFILENAME 1190
#define IDC_GEDBG_FRAMEBUFADDR 1191
#define IDC_GEDBG_TEXADDR 1192
#define IDC_GEDBG_FBTABS 1193
#define IDC_GEDBG_VERTICES 1194
#define IDC_GEDBG_RAWVERTS 1195
#define IDC_GEDBG_MATRICES 1196
#define ID_SHADERS_BASE 5000
#define ID_FILE_EXIT 40000
#define ID_DEBUG_SAVEMAPFILE 40001
#define ID_DISASM_ADDHLE 40002
#define ID_FUNCLIST_KILLFUNCTION 40003
#define ID_DISASM_RUNTOHERE 40004
#define ID_MEMVIEW_COPYVALUE_8 40005
#define ID_DISASM_COPYINSTRUCTIONDISASM 40006
#define ID_DISASM_COPYINSTRUCTIONHEX 40007
#define ID_EMULATION_SPEEDLIMIT 40008
#define ID_TOGGLE_PAUSE 40009
#define ID_EMULATION_STOP 40010
#define ID_FILE_LOAD 40011
#define ID_HELP_ABOUT 40012
#define ID_DISASM_FOLLOWBRANCH 40013
#define ID_DEBUG_IGNOREILLEGALREADS 40014
#define ID_DISASM_COPYADDRESS 40015
#define ID_REGLIST_GOTOINMEMORYVIEW 40016
#define ID_REGLIST_COPYVALUE 40017
#define ID_REGLIST_COPY 40018
#define ID_REGLIST_GOTOINDISASM 40019
#define ID_REGLIST_CHANGE 40020
#define ID_DISASM_RENAMEFUNCTION 40021
#define ID_DISASM_SETPCTOHERE 40022
#define ID_HELP_OPENWEBSITE 40023
#define ID_OPTIONS_SCREENAUTO 40024
#define ID_OPTIONS_SCREEN1X 40025
#define ID_OPTIONS_SCREEN2X 40026
#define ID_OPTIONS_SCREEN3X 40027
#define ID_OPTIONS_SCREEN4X 40028
#define ID_OPTIONS_SCREEN5X 40029
#define ID_OPTIONS_HARDWARETRANSFORM 40030
#define IDC_STEPHLE 40032
#define ID_OPTIONS_LINEARFILTERING 40033
#define ID_FILE_QUICKSAVESTATE 40034
#define ID_FILE_QUICKLOADSTATE 40035
#define ID_FILE_QUICKSAVESTATE_HC 40036
#define ID_FILE_QUICKLOADSTATE_HC 40037
#define ID_OPTIONS_CONTROLS 40038
#define ID_DEBUG_RUNONLOAD 40039
#define ID_DEBUG_DUMPNEXTFRAME 40040
#define ID_OPTIONS_VERTEXCACHE 40041
#define ID_OPTIONS_SHOWFPS 40042
#define ID_OPTIONS_STRETCHDISPLAY 40043
#define ID_OPTIONS_FRAMESKIP 40044
#define IDC_MEMCHECK 40045
#define ID_FILE_MEMSTICK 40046
#define ID_FILE_LOAD_MEMSTICK 40047
#define ID_EMULATION_SOUND 40048
#define ID_OPTIONS_MIPMAP 40049
#define ID_TEXTURESCALING_OFF 40050
#define ID_TEXTURESCALING_XBRZ 40051
#define ID_TEXTURESCALING_HYBRID 40052
#define ID_TEXTURESCALING_2X 40053
#define ID_TEXTURESCALING_3X 40054
#define ID_TEXTURESCALING_4X 40055
#define ID_TEXTURESCALING_5X 40056
#define ID_TEXTURESCALING_DEPOSTERIZE 40057
#define ID_TEXTURESCALING_BICUBIC 40058
#define ID_TEXTURESCALING_HYBRID_BICUBIC 40059
#define IDB_IMAGE_PSP 40060
#define IDC_STATIC_IMAGE_PSP 40061
#define ID_CONTROLS_KEY_DISABLE 40062
#define ID_OPTIONS_TOPMOST 40063
#define ID_HELP_OPENFORUM 40064
#define ID_OPTIONS_VSYNC 40065
#define ID_DEBUG_TAKESCREENSHOT 40066
#define ID_OPTIONS_TEXTUREFILTERING_AUTO 40067
#define ID_OPTIONS_NEARESTFILTERING 40068
#define ID_DISASM_DISASSEMBLETOFILE 40069
#define ID_OPTIONS_LINEARFILTERING_CG 40070
#define ID_DISASM_DISABLEBREAKPOINT 40071
#define ID_DISASM_THREAD_FORCERUN 40072
#define ID_DISASM_THREAD_KILL 40073
#define ID_FILE_SAVESTATE_NEXT_SLOT 40074
#define ID_FILE_SAVESTATE_NEXT_SLOT_HC 40075
#define ID_OPTIONS_READFBOTOMEMORYGPU 40076
#define ID_OPTIONS_READFBOTOMEMORYCPU 40077
#define ID_OPTIONS_NONBUFFEREDRENDERING 40078
#define ID_OPTIONS_FRAMESKIP_0 40079
#define ID_OPTIONS_FRAMESKIP_1 40080
#define ID_OPTIONS_FRAMESKIP_2 40081
#define ID_OPTIONS_FRAMESKIP_3 40082
#define ID_OPTIONS_FRAMESKIP_4 40083
#define ID_OPTIONS_FRAMESKIP_5 40084
#define ID_OPTIONS_FRAMESKIP_6 40085
#define ID_OPTIONS_FRAMESKIP_7 40086
#define ID_OPTIONS_FRAMESKIP_8 40087
#define ID_OPTIONS_FRAMESKIP_AUTO 40088
#define ID_OPTIONS_FRAMESKIPDUMMY 40089
#define ID_OPTIONS_RESOLUTIONDUMMY 40090
#define ID_DISASM_ASSEMBLE 40091
#define ID_DISASM_ADDNEWBREAKPOINT 40092
#define ID_DISASM_EDITBREAKPOINT 40093
#define ID_EMULATION_CHEATS 40096
#define ID_HELP_CHINESE_FORUM 40097
#define ID_OPTIONS_MORE_SETTINGS 40098
#define ID_FILE_SAVESTATE_SLOT_1 40099
#define ID_FILE_SAVESTATE_SLOT_2 40100
#define ID_FILE_SAVESTATE_SLOT_3 40101
#define ID_FILE_SAVESTATE_SLOT_4 40102
#define ID_FILE_SAVESTATE_SLOT_5 40103
#define ID_OPTIONS_WINDOW1X 40104
#define ID_OPTIONS_WINDOW2X 40105
#define ID_OPTIONS_WINDOW3X 40106
#define ID_OPTIONS_WINDOW4X 40107
#define ID_OPTIONS_WINDOW5X 40108
#define ID_OPTIONS_BUFFEREDRENDERING 40109
#define ID_DEBUG_SHOWDEBUGSTATISTICS 40110
#define ID_OPTIONS_SCREEN6X 40111
#define ID_OPTIONS_SCREEN7X 40112
#define ID_OPTIONS_SCREEN8X 40113
#define ID_OPTIONS_SCREEN9X 40114
#define ID_OPTIONS_SCREEN10X 40115
#define ID_DEBUG_GEDEBUGGER 40116
#define IDC_GEDBG_STEPDRAW 40117
#define IDC_GEDBG_RESUME 40118
#define IDC_GEDBG_FRAME 40119
#define IDC_GEDBG_MAINTAB 40120
#define IDC_GEDBG_TEX 40121
#define IDC_GEDBG_STEP 40122
#define IDC_GEDBG_LISTS_ALLLISTS 40123
#define IDC_GEDBG_LISTS_STACK 40124
#define IDC_GEDBG_LISTS_SELECTEDLIST 40125
#define ID_OPTIONS_FXAA 40126
#define IDC_DEBUG_BOTTOMTABS 40127
#define ID_DEBUG_HIDEBOTTOMTABS 40128
#define ID_DEBUG_TOGGLEBOTTOMTABTITLES 40129
#define ID_GEDBG_SETSTALLADDR 40130
#define ID_GEDBG_GOTOPC 40131
#define ID_GEDBG_GOTOADDR 40132
#define IDC_GEDBG_STEPTEX 40133
#define IDC_GEDBG_STEPFRAME 40134
#define IDC_GEDBG_BREAKTEX 40135
#define ID_OPTIONS_PAUSE_FOCUS 40136
#define ID_TEXTURESCALING_AUTO 40137
#define IDC_GEDBG_STEPPRIM 40138
#define ID_DISASM_ADDFUNCTION 40139
#define ID_DISASM_REMOVEFUNCTION 40140
#define ID_OPTIONS_LANGUAGE 40141
#define ID_MEMVIEW_COPYVALUE_16 40142
#define ID_MEMVIEW_COPYVALUE_32 40143
#define ID_EMULATION_SWITCH_UMD 40144
#define ID_DEBUG_EXTRACTFILE 40145
#define ID_OPTIONS_IGNOREWINKEY 40146
#define IDC_MODULELIST 40147
#define IDC_GEDBG_TEXLEVELDOWN 40148
#define IDC_GEDBG_TEXLEVELUP 40149
#define ID_DEBUG_LOADSYMFILE 40150
#define ID_DEBUG_SAVESYMFILE 40151
#define ID_OPTIONS_BUFLINEARFILTER 40152
#define ID_OPTIONS_BUFNEARESTFILTER 40153
#define ID_OPTIONS_DIRECTX 40154
#define ID_OPTIONS_OPENGL 40155
// Dummy option to let the buffered rendering hotkey cycle through all the options.
#define ID_OPTIONS_BUFFEREDRENDERINGDUMMY 40500
#define IDC_STEPOUT 40501
#define ID_HELP_BUYGOLD 40502
#define IDC_STATIC -1
// Next default values for new objects
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 256
#define _APS_NEXT_COMMAND_VALUE 40152
#define _APS_NEXT_CONTROL_VALUE 1197
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif