Add mini unit testing framework to Dolphin itself - use it to find bugs and verify the portable powerpc fp number classifier. also random cleanup.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3432 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard 2009-06-13 22:08:01 +00:00
parent df7b29da32
commit 31f7020b2d
18 changed files with 1159 additions and 620 deletions

View File

@ -19,6 +19,7 @@
#define _SI_DEVICEGCCONTROLLER_H
#include "../PluginManager.h"
#include "SI_Device.h"
//////////////////////////////////////////////////////////////////////////
// standard gamecube controller

View File

@ -405,25 +405,45 @@ void faddsx(UGeckoInstruction _inst)
void fdivx(UGeckoInstruction _inst)
{
rPS0(_inst.FD) = rPS0(_inst.FA) / rPS0(_inst.FB);
double a = rPS0(_inst.FA);
double b = rPS0(_inst.FB);
if (a == 0.0f && b == 0.0f)
rPS0(_inst.FD) = rPS1(_inst.FD) = 0.0; // NAN?
else
rPS0(_inst.FD) = rPS1(_inst.FD) = a / b;
if (fabs(rPS0(_inst.FB)) == 0.0) {
if (!FPSCR.ZX)
FPSCR.FX = 1;
FPSCR.ZX = 1;
FPSCR.XX = 1;
}
if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
}
void fdivsx(UGeckoInstruction _inst)
{
rPS0(_inst.FD) = rPS1(_inst.FD) = static_cast<float>(rPS0(_inst.FA) / rPS0(_inst.FB));
if (fabs(rPS0(_inst.FB)) == 0.0) {
float a = rPS0(_inst.FA);
float b = rPS0(_inst.FB);
if (a != a || b != b)
rPS0(_inst.FD) = rPS1(_inst.FD) = 0.0; // NAN?
else
rPS0(_inst.FD) = rPS1(_inst.FD) = a / b;
if (b == 0.0) {
if (!FPSCR.ZX)
FPSCR.FX = 1;
FPSCR.ZX = 1;
FPSCR.XX = 1;
}
if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
}
void fresx(UGeckoInstruction _inst)
{
rPS0(_inst.FD) = rPS1(_inst.FD) = static_cast<float>(1.0f / rPS0(_inst.FB));
double b = rPS0(_inst.FB);
rPS0(_inst.FD) = rPS1(_inst.FD) = 1.0 / b;
if (fabs(rPS0(_inst.FB)) == 0.0) {
if (!FPSCR.ZX)
FPSCR.FX = 1;
FPSCR.ZX = 1;
FPSCR.XX = 1;
}
if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
}
@ -480,16 +500,24 @@ void fsubsx(UGeckoInstruction _inst)
if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
}
void frsqrtex(UGeckoInstruction _inst)
{
rPS0(_inst.FD) = 1.0f / (sqrt(rPS0(_inst.FB)));
double b = rPS0(_inst.FB);
if (b <= 0.0)
rPS0(_inst.FD) = 0.0;
else
rPS0(_inst.FD) = 1.0f / (sqrt(b));
if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
}
void fsqrtx(UGeckoInstruction _inst)
{
rPS0(_inst.FD) = sqrt(rPS0(_inst.FB));
double b = rPS0(_inst.FB);
if (b < 0.0)
{
FPSCR.VXSQRT = 1;
}
rPS0(_inst.FD) = sqrt(b);
if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
}

View File

@ -161,6 +161,23 @@ ps_adds1
*/
//#define NAN_CHECK
static void CheckForNans()
{
static bool lastNan[32];
for (int i = 0; i < 32; i++) {
double v = rPS0(i);
if (v != v) {
if (!lastNan[i]) {
lastNan[i] = true;
PanicAlert("PC = %08x Got NAN in R%i", PC, i);
}
} else {
lastNan[i] = false;
}
}
}
Jit64 jit;
@ -171,13 +188,13 @@ namespace CPUCompare
extern u32 m_BlockStart;
}
void Jit(u32 em_address)
{
void Jit(u32 em_address)
{
jit.Jit(em_address);
}
}
void Jit64::Init()
{
void Jit64::Init()
{
asm_routines.compareEnabled = ::Core::g_CoreStartupParameter.bRunCompareClient;
jo.optimizeStack = true;
@ -212,28 +229,28 @@ namespace CPUCompare
blocks.Init();
asm_routines.Init();
}
}
void Jit64::ClearCache()
{
void Jit64::ClearCache()
{
blocks.Clear();
trampolines.ClearCodeSpace();
ClearCodeSpace();
}
}
void Jit64::Shutdown()
{
void Jit64::Shutdown()
{
FreeCodeSpace();
blocks.Shutdown();
trampolines.Shutdown();
asm_routines.Shutdown();
}
}
// This is only called by Default() in this file. It will execute an instruction with the interpreter functions.
void Jit64::WriteCallInterpreter(UGeckoInstruction inst)
{
// This is only called by Default() in this file. It will execute an instruction with the interpreter functions.
void Jit64::WriteCallInterpreter(UGeckoInstruction inst)
{
gpr.Flush(FLUSH_ALL);
@ -253,48 +270,48 @@ namespace CPUCompare
MOV(32, R(EAX), M(&NPC));
WriteRfiExitDestInEAX();
}
}
}
void Jit64::unknown_instruction(UGeckoInstruction inst)
{
void Jit64::unknown_instruction(UGeckoInstruction inst)
{
// CCPU::Break();
PanicAlert("unknown_instruction %08x - Fix me ;)", inst.hex);
}
}
void Jit64::Default(UGeckoInstruction _inst)
{
void Jit64::Default(UGeckoInstruction _inst)
{
WriteCallInterpreter(_inst.hex);
}
}
void Jit64::HLEFunction(UGeckoInstruction _inst)
{
void Jit64::HLEFunction(UGeckoInstruction _inst)
{
gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL);
ABI_CallFunctionCC((void*)&HLE::Execute, js.compilerPC, _inst.hex);
MOV(32, R(EAX), M(&NPC));
WriteExitDestInEAX(0);
}
}
void Jit64::DoNothing(UGeckoInstruction _inst)
{
void Jit64::DoNothing(UGeckoInstruction _inst)
{
// Yup, just don't do anything.
}
}
void Jit64::NotifyBreakpoint(u32 em_address, bool set)
{
void Jit64::NotifyBreakpoint(u32 em_address, bool set)
{
int block_num = blocks.GetBlockNumberFromStartAddress(em_address);
if (block_num >= 0)
{
blocks.DestroyBlock(block_num, false);
}
}
}
static const bool ImHereDebug = false;
static const bool ImHereLog = false;
static std::map<u32, int> been_here;
static const bool ImHereDebug = false;
static const bool ImHereLog = false;
static std::map<u32, int> been_here;
void ImHere()
{
void ImHere()
{
static FILE *f = 0;
if (ImHereLog) {
if (!f)
@ -315,16 +332,18 @@ namespace CPUCompare
DEBUG_LOG(DYNA_REC, "I'm here - PC = %08x , LR = %08x", PC, LR);
//printf("I'm here - PC = %08x , LR = %08x", PC, LR);
been_here[PC] = 1;
}
}
void Jit64::Cleanup()
{
void Jit64::Cleanup()
{
if (jo.optimizeGatherPipe && js.fifoBytesThisBlock > 0)
ABI_CallFunction((void *)&GPFifo::CheckGatherPipe);
}
if (GetAsyncKeyState(VK_LSHIFT))
ABI_CallFunction(thunks.ProtectFunction((void *)&CheckForNans, 0));
}
void Jit64::WriteExit(u32 destination, int exit_num)
{
void Jit64::WriteExit(u32 destination, int exit_num)
{
Cleanup();
SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
@ -346,41 +365,41 @@ namespace CPUCompare
MOV(32, M(&PC), Imm32(destination));
JMP(asm_routines.dispatcher, true);
}
}
}
void Jit64::WriteExitDestInEAX(int exit_num)
{
void Jit64::WriteExitDestInEAX(int exit_num)
{
MOV(32, M(&PC), R(EAX));
Cleanup();
SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
JMP(asm_routines.dispatcher, true);
}
}
void Jit64::WriteRfiExitDestInEAX()
{
void Jit64::WriteRfiExitDestInEAX()
{
MOV(32, M(&PC), R(EAX));
Cleanup();
SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
JMP(asm_routines.testExceptions, true);
}
}
void Jit64::WriteExceptionExit(u32 exception)
{
void Jit64::WriteExceptionExit(u32 exception)
{
Cleanup();
OR(32, M(&PowerPC::ppcState.Exceptions), Imm32(exception));
MOV(32, M(&PC), Imm32(js.compilerPC + 4));
JMP(asm_routines.testExceptions, true);
}
}
void STACKALIGN Jit64::Run()
{
void STACKALIGN Jit64::Run()
{
CompiledCode pExecAddr = (CompiledCode)asm_routines.enterCode;
pExecAddr();
//Will return when PowerPC::state changes
}
}
void Jit64::SingleStep()
{
void Jit64::SingleStep()
{
// NOT USED, NOT TESTED, PROBABLY NOT WORKING YET
// PanicAlert("Single");
/*
@ -389,10 +408,10 @@ namespace CPUCompare
const u8 *code = DoJit(PowerPC::ppcState.pc, &temp_codebuffer, &temp_block);
CompiledCode pExecAddr = (CompiledCode)code;
pExecAddr();*/
}
}
void STACKALIGN Jit64::Jit(u32 em_address)
{
void STACKALIGN Jit64::Jit(u32 em_address)
{
if (GetSpaceLeft() < 0x10000 || blocks.IsFull())
{
WARN_LOG(DYNA_REC, "JIT cache full - clearing.")
@ -406,10 +425,11 @@ namespace CPUCompare
int block_num = blocks.AllocateBlock(em_address);
JitBlock *b = blocks.GetBlock(block_num);
blocks.FinalizeBlock(block_num, jo.enableBlocklink, DoJit(em_address, &code_buffer, b));
}
}
const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buffer, JitBlock *b)
{
const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buffer, JitBlock *b)
{
if (em_address == 0)
PanicAlert("ERROR : Trying to compile at 0. LR=%08x", LR);
@ -475,11 +495,14 @@ namespace CPUCompare
// get start tic
PROFILER_QUERY_PERFORMACE_COUNTER(&b->ticStart);
}
#if defined(_DEBUG) || defined(DEBUGFAST)
//#if defined(_DEBUG) || defined(DEBUGFAST)
// should help logged stacktraces become more accurate
MOV(32, M(&PC), Imm32(js.blockStart));
#endif
//#endif
// if (em_address == 0x801e4188)
// INT3();
//Start up the register allocators
//They use the information in gpa/fpa to preload commonly used registers.
gpr.Start(js.gpa);
@ -543,4 +566,4 @@ namespace CPUCompare
b->codeSize = (u32)(GetCodePtr() - normalEntry);
b->originalSize = size;
return normalEntry;
}
}

View File

@ -40,8 +40,8 @@
using namespace Gen;
void Jit64::sc(UGeckoInstruction inst)
{
void Jit64::sc(UGeckoInstruction inst)
{
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITBranchOff)
{Default(inst); return;} // turn off from debugger
@ -50,10 +50,10 @@ using namespace Gen;
gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL);
WriteExceptionExit(EXCEPTION_SYSCALL);
}
}
void Jit64::rfi(UGeckoInstruction inst)
{
void Jit64::rfi(UGeckoInstruction inst)
{
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITBranchOff)
{Default(inst); return;} // turn off from debugger
@ -75,10 +75,10 @@ using namespace Gen;
// NPC = SRR0;
MOV(32, R(EAX), M(&SRR0));
WriteRfiExitDestInEAX();
}
}
void Jit64::bx(UGeckoInstruction inst)
{
void Jit64::bx(UGeckoInstruction inst)
{
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITBranchOff)
{Default(inst); return;} // turn off from debugger
@ -114,13 +114,13 @@ using namespace Gen;
// TODO: investigate the good old method of merging blocks here.
PanicAlert("bx not last instruction of block"); // this should not happen
}
}
}
// TODO - optimize to hell and beyond
// TODO - make nice easy to optimize special cases for the most common
// variants of this instruction.
void Jit64::bcx(UGeckoInstruction inst)
{
// TODO - optimize to hell and beyond
// TODO - make nice easy to optimize special cases for the most common
// variants of this instruction.
void Jit64::bcx(UGeckoInstruction inst)
{
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITBranchOff)
{Default(inst); return;} // turn off from debugger
@ -213,10 +213,10 @@ using namespace Gen;
SetJumpTarget(skip);
WriteExit(js.compilerPC + 4, 1);
}
}
}
void Jit64::bcctrx(UGeckoInstruction inst)
{
void Jit64::bcctrx(UGeckoInstruction inst)
{
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITBranchOff)
{Default(inst); return;} // turn off from debugger
@ -256,11 +256,11 @@ using namespace Gen;
MOV(32, M(&LR), Imm32(js.compilerPC + 4)); // LR = PC + 4;
AND(32, R(EAX), Imm32(0xFFFFFFFC));
WriteExitDestInEAX(0);
}
}
void Jit64::bclrx(UGeckoInstruction inst)
{
void Jit64::bclrx(UGeckoInstruction inst)
{
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITBranchOff)
{Default(inst); return;} // turn off from debugger
@ -286,4 +286,4 @@ using namespace Gen;
Default(inst);
MOV(32, R(EAX), M(&NPC));
WriteExitDestInEAX(0);
}
}

View File

@ -196,6 +196,8 @@
MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(0x8)); // _x86Reg < 0
SetJumpTarget(continue1);
SetJumpTarget(continue2);
// TODO: If we ever care about SO, borrow a trick from
// http://maws.mameworld.info/maws/mamesrc/src/emu/cpu/powerpc/drc_ops.c : bt, adc
} else {
int test_bit = 8 >> (js.next_inst.BI & 3);
bool condition = (js.next_inst.BO & 8) ? false : true;

View File

@ -215,25 +215,39 @@ const float m_65535 = 65535.0f;
#define QUANTIZE_OVERFLOW_SAFE
// according to Intel Docs CVTPS2DQ writes 0x80000000 if the source floating point value is out of int32 range
// while it's OK for large negatives, it isn't for positives
// I don't know whether the overflow actually happens in any games
// but it potentially can cause problems, so we need some clamping
// TODO(ector): Improve 64-bit version
static void WriteDual32(u64 value, u32 address)
{
Memory::Write_U32((u32)(value >> 32), address);
Memory::Write_U32((u32)value, address + 4);
}
void AsmRoutineManager::GenQuantizedStores() {
const u8* storePairedIllegal = AlignCode4();
UD2();
const u8* storePairedFloat = AlignCode4();
// IN: value = XMM0, two singles in bottom. PPC address = ECX.
#ifdef _M_X64
MOVQ_xmm(R(RAX), XMM0);
ROL(64, R(RAX), Imm8(32));
// INT3();
MOVQ_xmm(M(&psTemp[0]), XMM0);
MOV(64, R(RAX), M(&psTemp[0]));
//INT3();
//MOVQ_xmm(R(RAX), XMM0);
//INT3();
ROL(64, R(RAX), Imm8(32)); // Swap the two - the big BSWAP will unswap.
TEST(32, R(ECX), Imm32(0x0C000000));
FixupBranch argh = J_CC(CC_NZ);
BSWAP(64, RAX);
MOV(64, MComplex(RBX, RCX, 1, 0), R(RAX));
MOV(64, MComplex(RBX, RCX, SCALE_1, 0), R(RAX));
FixupBranch arg2 = J();
SetJumpTarget(argh);
ABI_CallFunctionRR(thunks.ProtectFunction((void *)&Memory::Write_U64, 2), RAX, RCX);
ABI_CallFunctionRR(thunks.ProtectFunction((void *)&WriteDual32, 2), RAX, RCX);
SetJumpTarget(arg2);
#else
MOVQ_xmm(M(&psTemp[0]), XMM0);
@ -258,6 +272,7 @@ void AsmRoutineManager::GenQuantizedStores() {
RET();
const u8* storePairedU8 = AlignCode4();
INT3();
SHR(32, R(EAX), Imm8(6));
MOVSS(XMM1, MDisp(EAX, (u32)(u64)m_quantizeTableS));
PUNPCKLDQ(XMM1, R(XMM1));
@ -280,6 +295,7 @@ void AsmRoutineManager::GenQuantizedStores() {
RET();
const u8* storePairedS8 = AlignCode4();
INT3();
SHR(32, R(EAX), Imm8(6));
MOVSS(XMM1, MDisp(EAX, (u32)(u64)m_quantizeTableS));
PUNPCKLDQ(XMM1, R(XMM1));
@ -302,6 +318,7 @@ void AsmRoutineManager::GenQuantizedStores() {
RET();
const u8* storePairedU16 = AlignCode4();
INT3();
SHR(32, R(EAX), Imm8(6));
MOVSS(XMM1, MDisp(EAX, (u32)(u64)m_quantizeTableS));
PUNPCKLDQ(XMM1, R(XMM1));
@ -333,6 +350,7 @@ void AsmRoutineManager::GenQuantizedStores() {
RET();
const u8* storePairedS16 = AlignCode4();
INT3();
SHR(32, R(EAX), Imm8(6));
MOVSS(XMM1, MDisp(EAX, (u32)(u64)m_quantizeTableS));
PUNPCKLDQ(XMM1, R(XMM1));

View File

@ -444,7 +444,7 @@ static GekkoOPTemplate table31_2[] =
static GekkoOPTemplate table59[] =
{
{18, Interpreter::fdivsx, &Jit64::fp_arith_s, {"fdivsx", OPTYPE_FPU, FL_RC_BIT_F, 16}},
{18, Interpreter::fdivsx, &Jit64::Default, /*TODO*/ {"fdivsx", OPTYPE_FPU, FL_RC_BIT_F, 16}},
{20, Interpreter::fsubsx, &Jit64::fp_arith_s, {"fsubsx", OPTYPE_FPU, FL_RC_BIT_F}},
{21, Interpreter::faddsx, &Jit64::fp_arith_s, {"faddsx", OPTYPE_FPU, FL_RC_BIT_F}},
// {22, Interpreter::fsqrtsx, &Jit64::Default, {"fsqrtsx", OPTYPE_FPU, FL_RC_BIT_F}}, // Not implemented on gekko
@ -687,7 +687,7 @@ void InitTables()
}
#define OPLOG
#define OP_TO_LOG "mcrfs"
#define OP_TO_LOG "mffs"
#ifdef OPLOG
namespace {

View File

@ -357,7 +357,7 @@ void OnIdleIL()
int PPCFPClass(double dvalue)
{
#ifdef _WIN32
/* // win32-only reference implementation, to compare to:
switch (_fpclass(dvalue))
{
case _FPCLASS_SNAN:
@ -371,9 +371,9 @@ int PPCFPClass(double dvalue)
case _FPCLASS_PN: return 0x4;
case _FPCLASS_PINF: return 0x5;
default: return 0x4;
}
#else
// TODO: Make sure the below is equivalent to the above - then switch win32 implementation to it.
}*/
// TODO: Optimize the below to be as fast as possible.
union {
double d;
u64 i;
@ -395,7 +395,7 @@ int PPCFPClass(double dvalue)
return 0x9;
} else {
// OK let's dissect this thing.
int sign = (int)(value.i & 0x8000000000000000ULL) ? 1 : 0;
int sign = value.i >> 63;
int exp = (int)((value.i >> 52) & 0x7FF);
if (exp >= 1 && exp <= 2046) {
// Nice normalized number.
@ -419,12 +419,22 @@ int PPCFPClass(double dvalue)
}
return 0x4;
#endif
}
} // namespace
// FPSCR update functions
void UpdateFPRF(double dvalue)
{
FPSCR.FPRF = PowerPC::PPCFPClass(dvalue);
}
void UpdateFEX() {
FPSCR.FEX = (FPSCR.XX & FPSCR.XE) |
(FPSCR.ZX & FPSCR.ZE) |
(FPSCR.UX & FPSCR.UE) |
(FPSCR.OX & FPSCR.OE) |
(FPSCR.VX & FPSCR.VE);
}

View File

@ -91,6 +91,8 @@ volatile CPUState *GetStatePtr(); // this oddity is here instead of an extern d
void CompactCR();
void ExpandCR();
int PPCFPClass(double dvalue);
void OnIdle(u32 _uThreadAddr);
void OnIdleIL();

View File

@ -96,7 +96,7 @@
AdditionalLibraryDirectories="..\..\..\Externals\wxWidgets\lib;..\..\..\Externals\LZO\win32\$(ConfigurationName)"
IgnoreAllDefaultLibraries="false"
IgnoreDefaultLibraryNames="msvcrt"
GenerateDebugInformation="false"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
GenerateMapFile="false"
MapFileName="$(TargetDir)linkermap.map"
@ -768,7 +768,7 @@
AdditionalLibraryDirectories="..\..\..\Externals\wxWidgets\lib;..\..\..\Externals\LZO\win32\$(ConfigurationName)"
IgnoreAllDefaultLibraries="false"
IgnoreDefaultLibraryNames="msvcrt"
GenerateDebugInformation="false"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
GenerateMapFile="false"
MapFileName="$(TargetDir)linkermap.map"

View File

@ -20,7 +20,7 @@ EventHandler::~EventHandler() {
}
EventHandler *EventHandler::GetInstance() {
fprintf(stderr, "handler instance %p\n", m_Instance);
// fprintf(stderr, "handler instance %p\n", m_Instance);
if (! m_Instance)
m_Instance = new EventHandler();
@ -30,13 +30,13 @@ EventHandler *EventHandler::GetInstance() {
void EventHandler::Destroy() {
if (m_Instance)
delete m_Instance;
fprintf(stderr, "deleting instance %p\n", m_Instance);
// fprintf(stderr, "deleting instance %p\n", m_Instance);
m_Instance = 0;
}
bool EventHandler::RegisterEventListener(listenFuncPtr func, Keys key) {
if (key.inputType == KeyboardInput) {
fprintf(stderr, "Registering %d:%d %p %p \n", key.keyCode, key.mods, func, this);
// fprintf(stderr, "Registering %d:%d %p %p \n", key.keyCode, key.mods, func, this);
if (key.keyCode == sf::Key::Count || key.mods >= NUMMODS ||
key.keyCode >= NUMKEYS)
return false;

View File

@ -3,7 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 10.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "Core\Core\Core.vcproj", "{F0B874CB-4476-4199-9315-8343D05AE684}"
ProjectSection(ProjectDependencies) = postProject
{C7E5D50A-2916-464B-86A7-E10B3CC88ADA} = {C7E5D50A-2916-464B-86A7-E10B3CC88ADA}
{33546D62-7F34-4EA6-A88E-D538B36E16BF} = {33546D62-7F34-4EA6-A88E-D538B36E16BF}
{11F55366-12EC-4C44-A8CB-1D4E315D61ED} = {11F55366-12EC-4C44-A8CB-1D4E315D61ED}
{3E03C179-8251-46E4-81F4-466F114BAC63} = {3E03C179-8251-46E4-81F4-466F114BAC63}
{0E231FB1-F3C9-4724-ACCB-DE8BCB3C089E} = {0E231FB1-F3C9-4724-ACCB-DE8BCB3C089E}
{29C2ABC1-ADA5-42CD-A5FC-96022D52A510} = {29C2ABC1-ADA5-42CD-A5FC-96022D52A510}
{1C8436C9-DBAF-42BE-83BC-CF3EC9175ABE} = {1C8436C9-DBAF-42BE-83BC-CF3EC9175ABE}
@ -185,6 +187,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SOIL", "..\Externals\SOIL\S
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SFML_Network", "..\Externals\SFML\build\vc2008\sfml-network.vcproj", "{823DDC98-42D5-4A38-88CF-9DC06C788AE4}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests", "UnitTests\UnitTests.vcproj", "{40C636FA-B5BF-4D67-ABC8-376B524A7551}"
ProjectSection(ProjectDependencies) = postProject
{F0B874CB-4476-4199-9315-8343D05AE684} = {F0B874CB-4476-4199-9315-8343D05AE684}
{C573CAF7-EE6A-458E-8049-16C0BF34C2E9} = {C573CAF7-EE6A-458E-8049-16C0BF34C2E9}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@ -623,6 +631,19 @@ Global
{823DDC98-42D5-4A38-88CF-9DC06C788AE4}.Release|Win32.Build.0 = Release|Win32
{823DDC98-42D5-4A38-88CF-9DC06C788AE4}.Release|x64.ActiveCfg = Release|x64
{823DDC98-42D5-4A38-88CF-9DC06C788AE4}.Release|x64.Build.0 = Release|x64
{40C636FA-B5BF-4D67-ABC8-376B524A7551}.Debug|Win32.ActiveCfg = Debug|Win32
{40C636FA-B5BF-4D67-ABC8-376B524A7551}.Debug|Win32.Build.0 = Debug|Win32
{40C636FA-B5BF-4D67-ABC8-376B524A7551}.Debug|x64.ActiveCfg = Debug|Win32
{40C636FA-B5BF-4D67-ABC8-376B524A7551}.DebugFast|Win32.ActiveCfg = Debug|Win32
{40C636FA-B5BF-4D67-ABC8-376B524A7551}.DebugFast|Win32.Build.0 = Debug|Win32
{40C636FA-B5BF-4D67-ABC8-376B524A7551}.DebugFast|x64.ActiveCfg = Debug|Win32
{40C636FA-B5BF-4D67-ABC8-376B524A7551}.Release_JITIL|Win32.ActiveCfg = Release|Win32
{40C636FA-B5BF-4D67-ABC8-376B524A7551}.Release_JITIL|Win32.Build.0 = Release|Win32
{40C636FA-B5BF-4D67-ABC8-376B524A7551}.Release_JITIL|x64.ActiveCfg = Release|Win32
{40C636FA-B5BF-4D67-ABC8-376B524A7551}.Release|Win32.ActiveCfg = Release|Win32
{40C636FA-B5BF-4D67-ABC8-376B524A7551}.Release|Win32.Build.0 = Release|Win32
{40C636FA-B5BF-4D67-ABC8-376B524A7551}.Release|x64.ActiveCfg = Release|x64
{40C636FA-B5BF-4D67-ABC8-376B524A7551}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -144,7 +144,7 @@ bool OpenGL_ReportFBOError(const char *function, const char *file, int line);
#if defined(_DEBUG) || defined(DEBUGFAST)
#define GL_REPORT_ERRORD() OpenGL_ReportGLError(__FUNCTION__, __FILE__, __LINE__)
#else
#define GL_REPORT_ERRORD() GL_NO_ERROR
#define GL_REPORT_ERRORD()
#endif
#endif // GLTEST ??

View File

@ -81,8 +81,13 @@ void DrawMessages()
}
}
GL_REPORT_ERRORD();
if (enabled)
glEnable(GL_BLEND);
GL_REPORT_ERRORD();
}
} // namespace

View File

@ -1122,6 +1122,7 @@ void Renderer::SwapBuffers()
fpscount = 0;
}
// ---------------------------------------------------------------------
GL_REPORT_ERRORD();
for (int i = 0; i < 8; i++) {
glActiveTexture(GL_TEXTURE0 + i);
@ -1132,8 +1133,12 @@ void Renderer::SwapBuffers()
DrawDebugText();
GL_REPORT_ERRORD();
OSD::DrawMessages();
GL_REPORT_ERRORD();
#if defined(DVPROFILE)
if (g_bWriteProfile) {
//g_bWriteProfile = 0;
@ -1148,6 +1153,9 @@ void Renderer::SwapBuffers()
#endif
// Copy the rendered frame to the real window
OpenGL_SwapBuffers();
GL_REPORT_ERRORD();
// Clear framebuffer
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
@ -1359,6 +1367,7 @@ void Renderer::RenderText(const char* pstr, int left, int top, u32 color)
left * 2.0f / (float)nBackbufferWidth - 1,
1 - top * 2.0f / (float)nBackbufferHeight,
0, nBackbufferWidth, nBackbufferHeight);
GL_REPORT_ERRORD();
}

View File

@ -16,20 +16,7 @@
// http://code.google.com/p/dolphin-emu/
#include "Globals.h"
#ifdef _WIN32
#include <windows.h>
#endif
#if defined(__APPLE__)
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif
#include "GLUtil.h"
#include <string.h>
@ -154,13 +141,28 @@ RasterFont::~RasterFont()
void RasterFont::printString(const char *s, double x, double y, double z)
{
int length = strlen(s);
if (!length)
return;
// Sanitize string to avoid GL errors.
char *s2 = new char[length + 1];
strcpy(s2, s);
for (int i = 0; i < length; i++) {
if (s2[i] < 32 || s2[i] > 126)
s2[i] = '!';
}
// go to the right spot
glRasterPos3d(x, y, z);
GL_REPORT_ERRORD();
glPushAttrib (GL_LIST_BIT);
glListBase(fontOffset);
glCallLists((GLsizei)strlen(s), GL_UNSIGNED_BYTE, (GLubyte *) s);
glPopAttrib ();
glCallLists((GLsizei)strlen(s2), GL_UNSIGNED_BYTE, (GLubyte *) s2);
GL_REPORT_ERRORD();
glPopAttrib();
GL_REPORT_ERRORD();
}
void RasterFont::printCenteredString(const char *s, double y, int screen_width, double z)

View File

@ -0,0 +1,89 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <cmath>
#include <iostream>
#include "PowerPC/PowerPC.h"
#include "HW/SI_DeviceGCController.h"
using namespace std;
int fail_count = 0;
#define EXPECT_EQ(a, b) \
if ((a) != (b)) { \
cout << "FAIL: " << #a << " %s is not equal to " << #b << endl; \
cout << "Actual: " << a << endl << "Expected: " << b << endl; \
fail_count++; \
}
void CoreTests()
{
// Tests that our fp classifier is correct.
EXPECT_EQ(PowerPC::PPCFPClass(1.0), 0x4);
EXPECT_EQ(PowerPC::PPCFPClass(-1.0), 0x8);
EXPECT_EQ(PowerPC::PPCFPClass(1235223.0), 0x4);
EXPECT_EQ(PowerPC::PPCFPClass(-126323521.0), 0x8);
EXPECT_EQ(PowerPC::PPCFPClass(1.0E-308), 0x14);
EXPECT_EQ(PowerPC::PPCFPClass(-1.0E-308), 0x18);
EXPECT_EQ(PowerPC::PPCFPClass(0.0), 0x2);
EXPECT_EQ(PowerPC::PPCFPClass(-0.0), 0x12);
EXPECT_EQ(PowerPC::PPCFPClass(HUGE_VAL), 0x5); // weird #define for infinity
EXPECT_EQ(PowerPC::PPCFPClass(-HUGE_VAL), 0x9);
EXPECT_EQ(PowerPC::PPCFPClass(sqrt(-1.0)), 0x11); // SNAN
}
int main(int argc, _TCHAR* argv[])
{
CoreTests();
if (fail_count == 0)
{
printf("All tests passed.\n");
}
return 0;
}
// Pretend that we are a host so we can link to core.... urgh.
//==============================================================
void Host_UpdateMainFrame(){}
void Host_UpdateDisasmDialog(){}
void Host_UpdateLogDisplay(){}
void Host_UpdateMemoryView(){}
void Host_NotifyMapLoaded(){}
void Host_UpdateBreakPointView(){}
void Host_SetDebugMode(bool enable){}
void Host_SetWaitCursor(bool enable){}
void Host_UpdateStatusBar(const char* _pText, int Filed = 0){}
#ifdef SETUP_TIMER_WAITING
void Host_UpdateGUI(){}
#endif
void Host_SysMessage(const char *fmt, ...){}
void Host_SetWiiMoteConnectionState(int _State){}
void Host_UpdateLeds(int bits){}
void Host_UpdateSpeakerStatus(int index, int bits){}
void Host_UpdateStatus(){}
int CSIDevice_GCController::GetNetInput(u8 numPAD, SPADStatus PadStatus, u32 *PADStatus)
{
return 0;
}

View File

@ -0,0 +1,329 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="UnitTests"
ProjectGUID="{40C636FA-B5BF-4D67-ABC8-376B524A7551}"
RootNamespace="UnitTests"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../Core/Core/Src;../Core/Common/Src;../PluginSpecs;../Core/InputCommon/Src"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="../Core/Core/Src;../Core/Common/Src;../PluginSpecs;../Core/InputCommon/Src"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../Core/Core/Src;../Core/Common/Src;../PluginSpecs;../Core/InputCommon/Src"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="../Core/Core/Src;../Core/Common/Src;../PluginSpecs;../Core/InputCommon/Src"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath=".\UnitTests.cpp"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>