mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-21 18:29:05 +02:00
Merge branch 'master' into framebuffer-texture
Conflicts: GPU/GLES/TextureCache.cpp
This commit is contained in:
commit
aef2376b34
75 files changed
+2801
-579
No files matched your search
@@ -26,6 +26,9 @@ Windows/ipch
|
||||
# For ppsspp.ini, etc.
|
||||
*.ini
|
||||
|
||||
# Qt Linguist files
|
||||
*.qm
|
||||
|
||||
Logs
|
||||
Memstick
|
||||
|
||||
|
||||
+5
-1
@@ -918,7 +918,11 @@ if(WIN32)
|
||||
endif()
|
||||
|
||||
if(HEADLESS)
|
||||
add_executable(PPSSPPHeadless headless/Headless.cpp headless/StubHost.h)
|
||||
add_executable(PPSSPPHeadless
|
||||
headless/Headless.cpp
|
||||
headless/StubHost.h
|
||||
headless/Compare.cpp
|
||||
headless/Compare.h)
|
||||
target_link_libraries(PPSSPPHeadless ${CoreLibName}
|
||||
${COCOA_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
|
||||
setup_target_project(PPSSPPHeadless headless)
|
||||
|
||||
+289
-21
@@ -78,11 +78,25 @@ bool TryMakeOperand2_AllowNegation(s32 imm, Operand2 &op2, bool *negated)
|
||||
}
|
||||
}
|
||||
|
||||
void ARMXEmitter::MOVI2R(ARMReg reg, u32 val)
|
||||
void ARMXEmitter::MOVI2R(ARMReg reg, u32 val, bool optimize)
|
||||
{
|
||||
Operand2 op2;
|
||||
bool inverse;
|
||||
if (TryMakeOperand2_AllowInverse(val, op2, &inverse)) {
|
||||
if (!optimize)
|
||||
{
|
||||
// Only used in backpatch atm
|
||||
// Only support ARMv7 right now
|
||||
if (cpu_info.bArmV7) {
|
||||
MOVW(reg, val & 0xFFFF);
|
||||
MOVT(reg, val, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ARMv6 version won't use backpatch for now
|
||||
// Run again with optimizations
|
||||
MOVI2R(reg, val);
|
||||
}
|
||||
} else if (TryMakeOperand2_AllowInverse(val, op2, &inverse)) {
|
||||
if (!inverse)
|
||||
MOV(reg, op2);
|
||||
else
|
||||
@@ -115,7 +129,14 @@ void ARMXEmitter::MOVI2R(ARMReg reg, u32 val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Moves IMM to memory location
|
||||
void ARMXEmitter::ARMABI_MOVI2M(Operand2 op, Operand2 val)
|
||||
{
|
||||
// This moves imm to a memory location
|
||||
MOVW(R14, val); MOVT(R14, val, true);
|
||||
MOVW(R12, op); MOVT(R12, op, true);
|
||||
STR(R12, R14); // R10 is what we want to store
|
||||
}
|
||||
void ARMXEmitter::QuickCallFunction(ARMReg reg, void *func) {
|
||||
MOVI2R(reg, (u32)(func));
|
||||
BL(reg);
|
||||
@@ -404,7 +425,7 @@ void ARMXEmitter::MOVT(ARMReg Rd, Operand2 Rm, bool TopBits) { WriteInstruction(
|
||||
|
||||
void ARMXEmitter::WriteInstruction (u32 Op, ARMReg Rd, ARMReg Rn, Operand2 Rm, bool SetFlags) // This can get renamed later
|
||||
{
|
||||
u32 op = InstOps[Op][Rm.GetType()]; // Type always decided by last operand
|
||||
s32 op = InstOps[Op][Rm.GetType()]; // Type always decided by last operand
|
||||
u32 Data = Rm.GetData();
|
||||
if (Rm.GetType() == TYPE_IMM)
|
||||
{
|
||||
@@ -419,7 +440,7 @@ void ARMXEmitter::WriteInstruction (u32 Op, ARMReg Rd, ARMReg Rn, Operand2 Rm, b
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (op == (u32)-1)
|
||||
if (op == -1)
|
||||
_assert_msg_(DYNA_REC, false, "%s not yet support %d", InstNames[Op], Rm.GetType());
|
||||
Write32(condition | (op << 21) | (SetFlags ? (1 << 20) : 0) | Rn << 16 | Rd << 12 | Data);
|
||||
}
|
||||
@@ -486,6 +507,10 @@ void ARMXEmitter::REV (ARMReg dest, ARMReg src )
|
||||
{
|
||||
Write32(condition | (107 << 20) | (15 << 16) | (dest << 12) | (243 << 4) | src);
|
||||
}
|
||||
void ARMXEmitter::REV16(ARMReg dest, ARMReg src)
|
||||
{
|
||||
Write32(condition | (0x3DF << 16) | (dest << 12) | (0xFD << 4) | src);
|
||||
}
|
||||
|
||||
void ARMXEmitter::_MSR (bool write_nzcvq, bool write_g, Operand2 op2)
|
||||
{
|
||||
@@ -526,8 +551,17 @@ void ARMXEmitter::DMB ()
|
||||
{
|
||||
Write32(0xF57FF05E);
|
||||
}
|
||||
void ARMXEmitter::SVC(Operand2 op)
|
||||
{
|
||||
Write32(condition | (0x0F << 24) | op.Imm24());
|
||||
}
|
||||
|
||||
void ARMXEmitter::LDR (ARMReg dest, ARMReg src, Operand2 op) { WriteStoreOp(0x41, src, dest, op);}
|
||||
void ARMXEmitter::LDRH(ARMReg dest, ARMReg src, Operand2 op)
|
||||
{
|
||||
u8 Imm = op.Imm8();
|
||||
Write32(condition | (0x05 << 20) | (src << 16) | (dest << 12) | ((Imm >> 4) << 8) | (0xB << 4) | (Imm & 0x0F));
|
||||
}
|
||||
void ARMXEmitter::LDRB(ARMReg dest, ARMReg src, Operand2 op) { WriteStoreOp(0x45, src, dest, op);}
|
||||
|
||||
void ARMXEmitter::LDR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add)
|
||||
@@ -569,19 +603,249 @@ void ARMXEmitter::LDMFD(ARMReg dest, bool WriteBack, const int Regnum, ...)
|
||||
WriteRegStoreOp(0x89, dest, WriteBack, RegList);
|
||||
}
|
||||
|
||||
// NEON and ASIMD
|
||||
ARMReg ARMXEmitter::SubBase(ARMReg Reg)
|
||||
{
|
||||
if (Reg >= S0)
|
||||
{
|
||||
if (Reg >= D0)
|
||||
{
|
||||
if (Reg >= Q0)
|
||||
return (ARMReg)((Reg - Q0) * 2); // Always gets encoded as a double register
|
||||
return (ARMReg)(Reg - D0);
|
||||
}
|
||||
return (ARMReg)(Reg - S0);
|
||||
}
|
||||
return Reg;
|
||||
}
|
||||
// NEON Specific
|
||||
void ARMXEmitter::VADD(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
|
||||
{
|
||||
_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to VADD(integer)");
|
||||
_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use VADD(integer) when CPU doesn't support it");
|
||||
|
||||
// Gets encoded as a double register
|
||||
Vd = SubBase(Vd);
|
||||
Vn = SubBase(Vn);
|
||||
Vm = SubBase(Vm);
|
||||
|
||||
Write32((0xF2 << 24) | ((Vd & 0x10) << 18) | (Size << 20) | ((Vn & 0xF) << 16) \
|
||||
| ((Vd & 0xF) << 12) | (0x8 << 8) | ((Vn & 0x10) << 3) | (1 << 6) \
|
||||
| ((Vm & 0x10) << 2) | (Vm & 0xF));
|
||||
|
||||
}
|
||||
void ARMXEmitter::VSUB(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
|
||||
{
|
||||
_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to VSUB(integer)");
|
||||
_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use VSUB(integer) when CPU doesn't support it");
|
||||
|
||||
// Gets encoded as a double register
|
||||
Vd = SubBase(Vd);
|
||||
Vn = SubBase(Vn);
|
||||
Vm = SubBase(Vm);
|
||||
|
||||
Write32((0xF3 << 24) | ((Vd & 0x10) << 18) | (Size << 20) | ((Vn & 0xF) << 16) \
|
||||
| ((Vd & 0xF) << 12) | (0x8 << 8) | ((Vn & 0x10) << 3) | (1 << 6) \
|
||||
| ((Vm & 0x10) << 2) | (Vm & 0xF));
|
||||
|
||||
}
|
||||
|
||||
// VFP Specific
|
||||
|
||||
void ARMXEmitter::VLDR(ARMReg Dest, ARMReg Base, Operand2 op)
|
||||
{
|
||||
_assert_msg_(DYNA_REC, Dest >= S0 && Dest <= D31, "Passed Invalid dest register to VLDR");
|
||||
_assert_msg_(DYNA_REC, Base <= R15, "Passed invalid Base register to VLDR");
|
||||
_assert_msg_(DYNA_REC, !(op.Imm12() & 4), "Offset needs to be word aligned");
|
||||
bool single_reg = Dest < D0;
|
||||
|
||||
Dest = SubBase(Dest);
|
||||
|
||||
if (single_reg)
|
||||
Dest = (ARMReg)(Dest - S0);
|
||||
{
|
||||
Write32(NO_COND | (0x1B << 23) | ((Dest & 0x1) << 22) | (1 << 20) | (Base << 16) \
|
||||
| ((Dest & 0x1E) << 11) | (10 << 8) | (op.Imm12() >> 2));
|
||||
|
||||
}
|
||||
else
|
||||
Dest = (ARMReg)(Dest - D0);
|
||||
Write32(NO_COND | (13 << 24) | ((Dest & 0x10) << 18) | (1 << 20) | (Base << 16) \
|
||||
| (5 << 9) | (!single_reg << 8) | op.Imm8());
|
||||
{
|
||||
Write32(NO_COND | (0x1B << 23) | ((Dest & 0x10) << 18) | (1 << 20) | (Base << 16) \
|
||||
| ((Dest & 0xF) << 12) | (11 << 8) | (op.Imm12() >> 2));
|
||||
}
|
||||
}
|
||||
void ARMXEmitter::VSTR(ARMReg Src, ARMReg Base, Operand2 op)
|
||||
{
|
||||
_assert_msg_(DYNA_REC, Src >= S0 && Src <= D31, "Passed invalid src register to VSTR");
|
||||
_assert_msg_(DYNA_REC, Base <= R15, "Passed invalid base register to VSTR");
|
||||
_assert_msg_(DYNA_REC, !(op.Imm12() & 4), "Offset needs to be word aligned");
|
||||
bool single_reg = Src < D0;
|
||||
|
||||
Src = SubBase(Src);
|
||||
|
||||
if (single_reg)
|
||||
{
|
||||
Write32(NO_COND | (0x1B << 23) | ((Src & 0x1) << 22) | (Base << 16) \
|
||||
| ((Src & 0x1E) << 11) | (10 << 8) | (op.Imm12() >> 2));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Write32(NO_COND | (0x1B << 23) | ((Src & 0x10) << 18) | (Base << 16) \
|
||||
| ((Src & 0xF) << 12) | (11 << 8) | (op.Imm12() >> 2));
|
||||
}
|
||||
}
|
||||
void ARMXEmitter::VCMP(ARMReg Vd, ARMReg Vm)
|
||||
{
|
||||
_assert_msg_(DYNA_REC, Vd < Q0, "Passed invalid Vd to VCMP");
|
||||
bool single_reg = Vd < D0;
|
||||
|
||||
Vd = SubBase(Vd);
|
||||
Vm = SubBase(Vm);
|
||||
|
||||
if (single_reg)
|
||||
{
|
||||
Write32(NO_COND | (0x1D << 23) | ((Vd & 0x1) << 22) | (0x34 << 16) | ((Vd & 0x1E) << 11) \
|
||||
| (0x2B << 6) | ((Vm & 0x1) << 5) | (Vm >> 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
Write32(NO_COND | (0x1D << 23) | ((Vd & 0x10) << 18) | (0x34 << 16) | ((Vd & 0xF) << 12) \
|
||||
| (0x2F << 6) | ((Vm & 0x10) << 1) | (Vm & 0xF));
|
||||
}
|
||||
}
|
||||
void ARMXEmitter::VCMP(ARMReg Vd)
|
||||
{
|
||||
_assert_msg_(DYNA_REC, Vd < Q0, "Passed invalid Vd to VCMP");
|
||||
bool single_reg = Vd < D0;
|
||||
|
||||
Vd = SubBase(Vd);
|
||||
|
||||
if (single_reg)
|
||||
{
|
||||
Write32(NO_COND | (0x1D << 23) | ((Vd & 0x1) << 22) | (0x35 << 16) | ((Vd & 0x1E) << 11) \
|
||||
| (0x2B << 6));
|
||||
}
|
||||
else
|
||||
{
|
||||
Write32(NO_COND | (0x1D << 23) | ((Vd & 0x10) << 18) | (0x35 << 16) | ((Vd & 0xF) << 12) \
|
||||
| (0x2F << 6));
|
||||
}
|
||||
}
|
||||
void ARMXEmitter::VDIV(ARMReg Vd, ARMReg Vn, ARMReg Vm)
|
||||
{
|
||||
_assert_msg_(DYNA_REC, Vd < Q0, "Pased invalid dest register to VSQRT");
|
||||
_assert_msg_(DYNA_REC, Vn < Q0, "Passed invalid Vn to VSQRT");
|
||||
_assert_msg_(DYNA_REC, Vm < Q0, "Passed invalid Vm to VSQRT");
|
||||
bool single_reg = Vd < D0;
|
||||
|
||||
Vd = SubBase(Vd);
|
||||
Vn = SubBase(Vn);
|
||||
Vm = SubBase(Vm);
|
||||
|
||||
if (single_reg)
|
||||
{
|
||||
Write32(NO_COND | (0x1D << 23) | ((Vd & 0x1) << 22) | ((Vn & 0x1E) << 16) \
|
||||
| ((Vd & 0x1E) << 11) | (0xA << 8) | ((Vn & 0x1) << 7) | ((Vm & 0x1) << 5) \
|
||||
| (Vm >> 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
Write32(NO_COND | (0x1D << 23) | ((Vd & 0x10) << 18) | ((Vn & 0xF) << 16) \
|
||||
| ((Vd & 0xF) << 12) | (0xB << 8) | ((Vn & 0x10) << 3) | ((Vm & 0x10) << 2) \
|
||||
| (Vm & 0xF));
|
||||
}
|
||||
}
|
||||
void ARMXEmitter::VSQRT(ARMReg Vd, ARMReg Vm)
|
||||
{
|
||||
_assert_msg_(DYNA_REC, Vd < Q0, "Pased invalid dest register to VSQRT");
|
||||
_assert_msg_(DYNA_REC, Vm < Q0, "Passed invalid Vm to VSQRT");
|
||||
bool single_reg = Vd < D0;
|
||||
|
||||
Vd = SubBase(Vd);
|
||||
Vm = SubBase(Vm);
|
||||
|
||||
if (single_reg)
|
||||
{
|
||||
Write32(NO_COND | (0x1D << 23) | ((Vd & 0x1) << 22) | (0x31 << 16) \
|
||||
| ((Vd & 0x1E) << 11) | (0x2B << 6) | ((Vm & 0x1) << 5) | (Vm >> 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
Write32(NO_COND | (0x1D << 23) | ((Vd & 0x10) << 18) | (0x31 << 16) \
|
||||
| ((Vd & 0xF) << 12) | (0x2F << 6) | ((Vm & 0x10) << 2) | (Vm & 0xF));
|
||||
}
|
||||
}
|
||||
// VFP and ASIMD
|
||||
void ARMXEmitter::VADD(ARMReg Vd, ARMReg Vn, ARMReg Vm)
|
||||
{
|
||||
_assert_msg_(DYNA_REC, Vd >= S0, "Passed invalid dest register to VADD");
|
||||
_assert_msg_(DYNA_REC, Vn >= S0, "Passed invalid Vn to VADD");
|
||||
_assert_msg_(DYNA_REC, Vm >= S0, "Passed invalid Vm to VADD");
|
||||
bool single_reg = Vd < D0;
|
||||
bool double_reg = Vd < Q0;
|
||||
|
||||
Vd = SubBase(Vd);
|
||||
Vn = SubBase(Vn);
|
||||
Vm = SubBase(Vm);
|
||||
|
||||
if (single_reg)
|
||||
{
|
||||
Write32(NO_COND | (0x1C << 23) | ((Vd & 0x1) << 22) | (0x3 << 20) \
|
||||
| ((Vn & 0x1E) << 15) | ((Vd & 0x1E) << 12) | (0x5 << 9) \
|
||||
| ((Vn & 0x1) << 7) | ((Vm & 0x1) << 5) | (Vm >> 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (double_reg)
|
||||
{
|
||||
Write32(NO_COND | (0x1C << 23) | ((Vd & 0x10) << 18) | (0x3 << 20) \
|
||||
| ((Vn & 0xF) << 16) | ((Vd & 0xF) << 12) | (0xB << 8) \
|
||||
| ((Vn & 0x10) << 3) | ((Vm & 0x10) << 2) | (Vm & 0xF));
|
||||
}
|
||||
else
|
||||
{
|
||||
_assert_msg_(DYNA_REC, cpu_info.bNEON, "Trying to use VADD with Quad Reg without support!");
|
||||
Write32((0xF2 << 24) | ((Vd & 0x10) << 18) | ((Vn & 0xF) << 16) \
|
||||
| ((Vd & 0xF) << 12) | (0xD << 8) | ((Vn & 0x10) << 3) \
|
||||
| (1 << 6) | ((Vm & 0x10) << 2) | (Vm & 0xF));
|
||||
}
|
||||
}
|
||||
}
|
||||
void ARMXEmitter::VSUB(ARMReg Vd, ARMReg Vn, ARMReg Vm)
|
||||
{
|
||||
_assert_msg_(DYNA_REC, Vd >= S0, "Passed invalid dest register to VSUB");
|
||||
_assert_msg_(DYNA_REC, Vn >= S0, "Passed invalid Vn to VSUB");
|
||||
_assert_msg_(DYNA_REC, Vm >= S0, "Passed invalid Vm to VSUB");
|
||||
bool single_reg = Vd < D0;
|
||||
bool double_reg = Vd < Q0;
|
||||
|
||||
Vd = SubBase(Vd);
|
||||
Vn = SubBase(Vn);
|
||||
Vm = SubBase(Vm);
|
||||
|
||||
if (single_reg)
|
||||
{
|
||||
Write32(NO_COND | (0x1C << 23) | ((Vd & 0x1) << 22) | (0x3 << 20) \
|
||||
| ((Vn & 0x1E) << 15) | ((Vd & 0x1E) << 12) | (0x5 << 9) \
|
||||
| ((Vn & 0x1) << 7) | (1 << 6) | ((Vm & 0x1) << 5) | (Vm >> 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (double_reg)
|
||||
{
|
||||
Write32(NO_COND | (0x1C << 23) | ((Vd & 0x10) << 18) | (0x3 << 20) \
|
||||
| ((Vn & 0xF) << 16) | ((Vd & 0xF) << 12) | (0xB << 8) \
|
||||
| ((Vn & 0x10) << 3) | (1 << 6) | ((Vm & 0x10) << 2) | (Vm & 0xF));
|
||||
}
|
||||
else
|
||||
{
|
||||
_assert_msg_(DYNA_REC, cpu_info.bNEON, "Trying to use VADD with Quad Reg without support!");
|
||||
Write32((0xF2 << 24) | (1 << 21) | ((Vd & 0x10) << 18) | ((Vn & 0xF) << 16) \
|
||||
| ((Vd & 0xF) << 12) | (0xD << 8) | ((Vn & 0x10) << 3) \
|
||||
| (1 << 6) | ((Vm & 0x10) << 2) | (Vm & 0xF));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ARMXEmitter::VMOV(ARMReg Dest, ARMReg Src)
|
||||
{
|
||||
if (Dest > R15)
|
||||
@@ -600,6 +864,7 @@ void ARMXEmitter::VMOV(ARMReg Dest, ARMReg Src)
|
||||
{
|
||||
// Move 64bit from Arm reg
|
||||
_assert_msg_(DYNA_REC, false, "This VMOV doesn't support moving 64bit ARM to NEON");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -613,13 +878,13 @@ void ARMXEmitter::VMOV(ARMReg Dest, ARMReg Src)
|
||||
Src = (ARMReg)(Src - S0);
|
||||
Write32(NO_COND | (0xE1 << 20) | ((Src & 0x1E) << 15) | (Dest << 12) \
|
||||
| (0xA << 8) | ((Src & 0x1) << 7) | (1 << 4));
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Move 64bit To Arm reg
|
||||
_assert_msg_(DYNA_REC, false, "This VMOV doesn't support moving 64bit ARM From NEON");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -632,32 +897,35 @@ void ARMXEmitter::VMOV(ARMReg Dest, ARMReg Src)
|
||||
int SrcSize = Src < D0 ? 1 : Src < Q0 ? 2 : 4;
|
||||
int DestSize = Dest < D0 ? 1 : Dest < Q0 ? 2 : 4;
|
||||
bool Single = DestSize == 1;
|
||||
bool Quad = DestSize == 4;
|
||||
|
||||
_assert_msg_(DYNA_REC, SrcSize == DestSize, "VMOV doesn't support moving different register sizes");
|
||||
|
||||
Dest = SubBase(Dest);
|
||||
Src = SubBase(Src);
|
||||
|
||||
if (Single)
|
||||
{
|
||||
Dest = (ARMReg)(Dest - S0);
|
||||
Src = (ARMReg)(Src - S0);
|
||||
Write32(NO_COND | (0x1D << 23) | ((Dest & 0x1) << 22) | (0x3 << 20) | ((Dest & 0x1E) << 11) \
|
||||
| (0x5 << 9) | (1 << 6) | ((Src & 0x1) << 5) | ((Src & 0x1E) >> 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Double and quad
|
||||
bool Quad = DestSize == 4;
|
||||
if (Quad)
|
||||
{
|
||||
_assert_msg_(DYNA_REC, cpu_info.bNEON, "Trying to use quad registers when you don't support ASIMD.");
|
||||
// Gets encoded as a Double register
|
||||
Dest = (ARMReg)((Dest - Q0) * 2);
|
||||
Src = (ARMReg)((Src - Q0) * 2);
|
||||
Write32((0xF2 << 24) | ((Dest & 0x10) << 18) | (2 << 20) | ((Src & 0xF) << 16) \
|
||||
| ((Dest & 0xF) << 12) | (1 << 8) | ((Src & 0x10) << 3) | (1 << 6) \
|
||||
| ((Src & 0x10) << 1) | (1 << 4) | (Src & 0xF));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Dest = (ARMReg)(Dest - D0);
|
||||
Src = (ARMReg)(Src - D0);
|
||||
Write32(NO_COND | (0x1D << 23) | ((Dest & 0x10) << 18) | (0x3 << 20) | ((Dest & 0xF) << 12) \
|
||||
| (0x2D << 6) | ((Src & 0x10) << 1) | (Src & 0xF));
|
||||
}
|
||||
Write32((0xF2 << 24) | ((Dest & 0x10) << 18) | (1 << 21) | ((Src & 0xF) << 16) \
|
||||
| ((Dest & 0xF) << 12) | (1 << 8) | ((Src & 0x10) << 3) | (Quad << 6) \
|
||||
| ((Src & 0x10) << 1) | (1 << 4) | (Src & 0xF));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+34
-8
@@ -97,6 +97,13 @@ enum ShiftType
|
||||
ST_ROR = 3,
|
||||
ST_RRX = 4
|
||||
};
|
||||
enum IntegerSize
|
||||
{
|
||||
I_I8 = 0,
|
||||
I_I16,
|
||||
I_I32,
|
||||
I_I64
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -309,6 +316,9 @@ bool TryMakeOperand2_AllowNegation(s32 imm, Operand2 &op2, bool *negated);
|
||||
inline Operand2 R(ARMReg Reg) { return Operand2(Reg, TYPE_REG); }
|
||||
inline Operand2 IMM(u32 Imm) { return Operand2(Imm, TYPE_IMM); }
|
||||
inline Operand2 Mem(void *ptr) { return Operand2((u32)ptr, TYPE_IMM); }
|
||||
//usage: struct {int e;} s; STRUCT_OFFSET(s,e)
|
||||
#define STRUCT_OFF(str,elem) ((u32)((u32)&(str).elem-(u32)&(str)))
|
||||
|
||||
|
||||
struct FixupBranch
|
||||
{
|
||||
@@ -418,6 +428,7 @@ public:
|
||||
void SBC (ARMReg dest, ARMReg src, Operand2 op2);
|
||||
void SBCS(ARMReg dest, ARMReg src, Operand2 op2);
|
||||
void REV (ARMReg dest, ARMReg src);
|
||||
void REV16 (ARMReg dest, ARMReg src);
|
||||
void RSC (ARMReg dest, ARMReg src, Operand2 op2);
|
||||
void RSCS(ARMReg dest, ARMReg src, Operand2 op2);
|
||||
void TST ( ARMReg src, Operand2 op2);
|
||||
@@ -459,6 +470,7 @@ public:
|
||||
void LDR (ARMReg dest, ARMReg src, Operand2 op2 = 0);
|
||||
// Offset adds to the base register in LDR
|
||||
void LDR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add);
|
||||
void LDRH(ARMReg dest, ARMReg src, Operand2 op = 0);
|
||||
void LDRB(ARMReg dest, ARMReg src, Operand2 op2 = 0);
|
||||
void STR (ARMReg dest, ARMReg src, Operand2 op2 = 0);
|
||||
// Offset adds on to the destination register in STR
|
||||
@@ -473,23 +485,37 @@ public:
|
||||
// dest contains the result if the instruction managed to store the value
|
||||
void STREX(ARMReg dest, ARMReg base, ARMReg op);
|
||||
void DMB ();
|
||||
void SVC(Operand2 op);
|
||||
|
||||
// NEON and ASIMD instructions
|
||||
// None of these will be created with conditional since ARM
|
||||
// is deprecating conditional execution of ASIMD instructions.
|
||||
// Some ASIMD instructions don't even have a conditional encoding.
|
||||
// ASIMD instructions don't even have a conditional encoding.
|
||||
|
||||
// Subtracts the base from the register to give us the real one
|
||||
ARMReg SubBase(ARMReg Reg);
|
||||
// NEON Only
|
||||
void VADD(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VSUB(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
|
||||
void VLDR(ARMReg dest, ARMReg Base, Operand2 op);
|
||||
// VFP Only
|
||||
void VLDR(ARMReg Dest, ARMReg Base, Operand2 op);
|
||||
void VSTR(ARMReg Src, ARMReg Base, Operand2 op);
|
||||
void VCMP(ARMReg Vd, ARMReg Vm);
|
||||
// Compares against zero
|
||||
void VCMP(ARMReg Vd);
|
||||
void VDIV(ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VSQRT(ARMReg Vd, ARMReg Vm);
|
||||
|
||||
// NEON and VFP
|
||||
void VADD(ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VSUB(ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VMOV(ARMReg Dest, ARMReg Src);
|
||||
|
||||
void QuickCallFunction(ARMReg scratchreg, void *func);
|
||||
// Utility functions
|
||||
void MOVI2R(ARMReg reg, u32 val);
|
||||
void ARMABI_ShowConditions();
|
||||
void ARMABI_Return();
|
||||
|
||||
void UpdateAPSR(bool NZCVQ, u8 Flags, bool GE, u8 GEval);
|
||||
|
||||
void MOVI2R(ARMReg reg, u32 val, bool optimize = true);
|
||||
void ARMABI_MOVI2M(Operand2 op, Operand2 val);
|
||||
}; // class ARMXEmitter
|
||||
|
||||
|
||||
|
||||
@@ -33,7 +33,9 @@
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#ifndef __SYMBIAN32__
|
||||
#include <type_traits>
|
||||
#endif
|
||||
|
||||
#include "Common.h"
|
||||
#include "FileUtil.h"
|
||||
@@ -44,6 +46,18 @@ namespace std {
|
||||
using tr1::is_pointer;
|
||||
}
|
||||
#endif
|
||||
#ifdef __SYMBIAN32__
|
||||
namespace std {
|
||||
template <bool bool_value>
|
||||
struct bool_constant {
|
||||
typedef bool_constant<bool_value> type;
|
||||
static const bool value = bool_value;
|
||||
};
|
||||
template <bool bool_value> const bool bool_constant<bool_value>::value;
|
||||
template <typename T> struct is_pointer : public bool_constant<false> {};
|
||||
template <typename T> struct is_pointer<T*> : public bool_constant<true> {};
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
struct LinkedListItem : public T
|
||||
|
||||
@@ -318,7 +318,7 @@ void ConsoleListener::SendToThread(LogTypes::LOG_LEVELS Level, const char *Text)
|
||||
Len = LOG_PENDING_MAX - 16;
|
||||
|
||||
char ColorAttr[16] = "";
|
||||
int ColorLen = 0;
|
||||
size_t ColorLen = 0;
|
||||
if (bUseColor)
|
||||
{
|
||||
// Not ANSI, since the console doesn't support it, but ANSI-like.
|
||||
@@ -333,7 +333,7 @@ void ConsoleListener::SendToThread(LogTypes::LOG_LEVELS Level, const char *Text)
|
||||
u32 prevLogWritePos = logWritePos;
|
||||
if (logWritePos + ColorLen + Len >= LOG_PENDING_MAX)
|
||||
{
|
||||
for (u32 i = 0; i < ColorLen; ++i)
|
||||
for (size_t i = 0; i < ColorLen; ++i)
|
||||
logPending[(logWritePos + i) % LOG_PENDING_MAX] = ColorAttr[i];
|
||||
logWritePos += ColorLen;
|
||||
if (logWritePos >= LOG_PENDING_MAX)
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
values.clear();
|
||||
for(int i = 0; i < temp.size(); i++)
|
||||
for(size_t i = 0; i < temp.size(); i++)
|
||||
{
|
||||
std::vector<std::string> key_val;
|
||||
SplitString(temp[i],'_',key_val);
|
||||
|
||||
@@ -1292,6 +1292,8 @@ void XEmitter::CVTDQ2PS(X64Reg regOp, OpArg arg) {WriteSSEOp(32, 0x5B, true, reg
|
||||
void XEmitter::CVTPD2DQ(X64Reg regOp, OpArg arg) {WriteSSEOp(64, 0xE6, false, regOp, arg);}
|
||||
void XEmitter::CVTPS2DQ(X64Reg regOp, OpArg arg) {WriteSSEOp(64, 0x5B, true, regOp, arg);}
|
||||
|
||||
void XEmitter::CVTSI2SS(X64Reg xregdest, OpArg arg) {WriteSSEOp(32, 0x2A, false, xregdest, arg);}
|
||||
void XEmitter::CVTSS2SI(X64Reg xregdest, OpArg arg) {WriteSSEOp(32, 0x2D, false, xregdest, arg);}
|
||||
void XEmitter::CVTTSS2SI(X64Reg xregdest, OpArg arg) {WriteSSEOp(32, 0x2C, false, xregdest, arg);}
|
||||
void XEmitter::CVTTPS2DQ(X64Reg xregdest, OpArg arg) {WriteSSEOp(32, 0x5B, false, xregdest, arg);}
|
||||
|
||||
|
||||
@@ -564,6 +564,8 @@ public:
|
||||
void CVTDQ2PS(X64Reg regOp, OpArg arg);
|
||||
void CVTPS2DQ(X64Reg regOp, OpArg arg);
|
||||
|
||||
void CVTSI2SS(X64Reg xregdest, OpArg arg); // Yeah, destination really is a GPR like EAX!
|
||||
void CVTSS2SI(X64Reg xregdest, OpArg arg); // Yeah, destination really is a GPR like EAX!
|
||||
void CVTTSS2SI(X64Reg xregdest, OpArg arg); // Yeah, destination really is a GPR like EAX!
|
||||
void CVTTPS2DQ(X64Reg regOp, OpArg arg);
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace
|
||||
if(dataSize == -1)
|
||||
{
|
||||
dataSize = pspFileSystem.GetFileInfo(filename).size;
|
||||
*data = new u8[dataSize];
|
||||
*data = new u8[(size_t)dataSize];
|
||||
}
|
||||
|
||||
size_t result = pspFileSystem.ReadFile(handle, *data, dataSize);
|
||||
|
||||
@@ -123,6 +123,12 @@ CISOFileBlockDevice::~CISOFileBlockDevice()
|
||||
|
||||
bool CISOFileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr)
|
||||
{
|
||||
if ((u32)blockNumber >= numBlocks)
|
||||
{
|
||||
memset(outPtr, 0, 2048);
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 idx = index[blockNumber];
|
||||
u32 idx2 = index[blockNumber+1];
|
||||
u8 inbuffer[4096]; //too big
|
||||
@@ -153,7 +159,7 @@ bool CISOFileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr)
|
||||
if(inflateInit2(&z, -15) != Z_OK)
|
||||
{
|
||||
ERROR_LOG(LOADER, "deflateInit ERROR : %s\n", (z.msg) ? z.msg : "???");
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
z.avail_in = readSize;
|
||||
z.next_out = outPtr;
|
||||
@@ -165,14 +171,17 @@ bool CISOFileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr)
|
||||
//if (status != Z_OK)
|
||||
{
|
||||
ERROR_LOG(LOADER, "block %d:inflate : %s[%d]\n", blockNumber, (z.msg) ? z.msg : "error", status);
|
||||
inflateEnd(&z);
|
||||
return 1;
|
||||
}
|
||||
int cmp_size = blockSize - z.avail_out;
|
||||
if (cmp_size != (int)blockSize)
|
||||
{
|
||||
ERROR_LOG(LOADER, "block %d : block size error %d != %d\n", blockNumber, cmp_size, blockSize);
|
||||
return 1;
|
||||
inflateEnd(&z);
|
||||
return false;
|
||||
}
|
||||
inflateEnd(&z);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -31,9 +31,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
#undef DeleteFile
|
||||
|
||||
|
||||
#if HOST_IS_CASE_SENSITIVE
|
||||
|
||||
static bool FixFilenameCase(const std::string &path, std::string &filename)
|
||||
@@ -248,7 +245,7 @@ bool DirectoryFileSystem::RenameFile(const std::string &from, const std::string
|
||||
return retValue;
|
||||
}
|
||||
|
||||
bool DirectoryFileSystem::DeleteFile(const std::string &filename) {
|
||||
bool DirectoryFileSystem::RemoveFile(const std::string &filename) {
|
||||
std::string fullName = GetLocalPath(filename);
|
||||
#ifdef _WIN32
|
||||
bool retValue = (::DeleteFileA(fullName.c_str()) == TRUE);
|
||||
@@ -266,7 +263,7 @@ bool DirectoryFileSystem::DeleteFile(const std::string &filename) {
|
||||
fullName = GetLocalPath(fullName);
|
||||
|
||||
#ifdef _WIN32
|
||||
retValue = (::DeleteFile(fullName.c_str()) == TRUE);
|
||||
retValue = (::DeleteFileA(fullName.c_str()) == TRUE);
|
||||
#else
|
||||
retValue = (0 == unlink(fullName.c_str()));
|
||||
#endif
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
bool MkDir(const std::string &dirname);
|
||||
bool RmDir(const std::string &dirname);
|
||||
bool RenameFile(const std::string &from, const std::string &to);
|
||||
bool DeleteFile(const std::string &filename);
|
||||
bool RemoveFile(const std::string &filename);
|
||||
bool GetHostPath(const std::string &inpath, std::string &outpath);
|
||||
|
||||
private:
|
||||
|
||||
@@ -110,7 +110,7 @@ public:
|
||||
virtual bool MkDir(const std::string &dirname) = 0;
|
||||
virtual bool RmDir(const std::string &dirname) = 0;
|
||||
virtual bool RenameFile(const std::string &from, const std::string &to) = 0;
|
||||
virtual bool DeleteFile(const std::string &filename) = 0;
|
||||
virtual bool RemoveFile(const std::string &filename) = 0;
|
||||
virtual bool GetHostPath(const std::string &inpath, std::string &outpath) = 0;
|
||||
};
|
||||
|
||||
@@ -130,7 +130,7 @@ public:
|
||||
virtual bool MkDir(const std::string &dirname) {return false;}
|
||||
virtual bool RmDir(const std::string &dirname) {return false;}
|
||||
virtual bool RenameFile(const std::string &from, const std::string &to) {return false;}
|
||||
virtual bool DeleteFile(const std::string &filename) {return false;}
|
||||
virtual bool RemoveFile(const std::string &filename) {return false;}
|
||||
virtual bool GetHostPath(const std::string &inpath, std::string &outpath) {return false;}
|
||||
};
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
virtual bool MkDir(const std::string &dirname) {return false;}
|
||||
virtual bool RmDir(const std::string &dirname) {return false;}
|
||||
virtual bool RenameFile(const std::string &from, const std::string &to) {return false;}
|
||||
virtual bool DeleteFile(const std::string &filename) {return false;}
|
||||
virtual bool RemoveFile(const std::string &filename) {return false;}
|
||||
|
||||
private:
|
||||
struct TreeEntry
|
||||
|
||||
@@ -363,13 +363,13 @@ bool MetaFileSystem::RenameFile(const std::string &from, const std::string &to)
|
||||
}
|
||||
}
|
||||
|
||||
bool MetaFileSystem::DeleteFile(const std::string &filename)
|
||||
bool MetaFileSystem::RemoveFile(const std::string &filename)
|
||||
{
|
||||
std::string of;
|
||||
IFileSystem *system;
|
||||
if (MapFilePath(filename, of, &system))
|
||||
{
|
||||
return system->DeleteFile(of);
|
||||
return system->RemoveFile(of);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -89,7 +89,7 @@ public:
|
||||
virtual bool MkDir(const std::string &dirname);
|
||||
virtual bool RmDir(const std::string &dirname);
|
||||
virtual bool RenameFile(const std::string &from, const std::string &to);
|
||||
virtual bool DeleteFile(const std::string &filename);
|
||||
virtual bool RemoveFile(const std::string &filename);
|
||||
|
||||
// TODO: void IoCtl(...)
|
||||
|
||||
|
||||
+15
-3
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "Thread.h"
|
||||
#include "../Core/CoreTiming.h"
|
||||
#include "../Core/CoreParameter.h"
|
||||
#include "../MIPS/MIPS.h"
|
||||
#include "../HLE/HLE.h"
|
||||
#include "sceAudio.h"
|
||||
@@ -78,7 +79,7 @@ static int hCountTotal; //unused
|
||||
static int vCount;
|
||||
static int isVblank;
|
||||
static bool hasSetMode;
|
||||
double lastFrameTime;
|
||||
static double lastFrameTime;
|
||||
|
||||
std::vector<WaitVBlankInfo> vblankWaitingThreads;
|
||||
|
||||
@@ -269,12 +270,11 @@ void hleEnterVblank(u64 userdata, int cyclesLate) {
|
||||
host->EndFrame();
|
||||
|
||||
#ifdef _WIN32
|
||||
static double lastFrameTime = 0.0;
|
||||
// Best place to throttle the frame rate on non vsynced platforms is probably here. Let's try it.
|
||||
time_update();
|
||||
if (lastFrameTime == 0.0)
|
||||
lastFrameTime = time_now_d();
|
||||
if (!GetAsyncKeyState(VK_TAB)) {
|
||||
if (!GetAsyncKeyState(VK_TAB) && !PSP_CoreParameter().headLess) {
|
||||
while (time_now_d() < lastFrameTime + 1.0 / 60.0) {
|
||||
Common::SleepCurrentThread(1);
|
||||
time_update();
|
||||
@@ -357,6 +357,18 @@ u32 sceDisplaySetFramebuf() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool __DisplayGetFramebuf(u8 **topaddr, u32 *linesize, u32 *pixelFormat, int mode) {
|
||||
const FrameBufferState &fbState = mode == 1 ? latchedFramebuf : framebuf;
|
||||
if (topaddr != NULL)
|
||||
*topaddr = Memory::GetPointer(fbState.topaddr);
|
||||
if (linesize != NULL)
|
||||
*linesize = fbState.pspFramebufLinesize;
|
||||
if (pixelFormat != NULL)
|
||||
*pixelFormat = fbState.pspFramebufFormat;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
u32 sceDisplayGetFramebuf(u32 topaddrPtr, u32 linesizePtr, u32 pixelFormatPtr, int mode) {
|
||||
const FrameBufferState &fbState = mode == 1 ? latchedFramebuf : framebuf;
|
||||
DEBUG_LOG(HLE,"sceDisplayGetFramebuf(*%08x = %08x, *%08x = %08x, *%08x = %08x, %i)",
|
||||
|
||||
@@ -26,6 +26,9 @@ void Register_sceDisplay();
|
||||
// will return true once after every end-of-frame.
|
||||
bool __DisplayFrameDone();
|
||||
|
||||
// Get information about the current framebuffer.
|
||||
bool __DisplayGetFramebuf(u8 **topaddr, u32 *linesize, u32 *pixelFormat, int mode);
|
||||
|
||||
typedef void (*VblankCallback)();
|
||||
// Listen for vblank events. Only register during init.
|
||||
void __DisplayListenVblank(VblankCallback callback);
|
||||
+15
-3
@@ -17,7 +17,6 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#undef DeleteFile
|
||||
#endif
|
||||
|
||||
#include "../Config.h"
|
||||
@@ -38,6 +37,9 @@
|
||||
#include "sceKernelMemory.h"
|
||||
#include "sceKernelThread.h"
|
||||
|
||||
// For headless screenshots.
|
||||
#include "sceDisplay.h"
|
||||
|
||||
#define ERROR_ERRNO_FILE_NOT_FOUND 0x80010002
|
||||
|
||||
#define ERROR_MEMSTICK_DEVCTL_BAD_PARAMS 0x80220081
|
||||
@@ -144,9 +146,10 @@ public:
|
||||
p.Do(callbackID);
|
||||
p.Do(callbackArg);
|
||||
p.Do(asyncResult);
|
||||
p.Do(closePending);
|
||||
p.Do(pendingAsyncResult);
|
||||
p.Do(sectorBlockMode);
|
||||
p.Do(closePending);
|
||||
p.Do(info);
|
||||
p.Do(openMode);
|
||||
p.DoMarker("File");
|
||||
}
|
||||
@@ -549,7 +552,7 @@ u32 sceIoRemove(const char *filename) {
|
||||
if(!pspFileSystem.GetFileInfo(filename).exists)
|
||||
return ERROR_ERRNO_FILE_NOT_FOUND;
|
||||
|
||||
pspFileSystem.DeleteFile(filename);
|
||||
pspFileSystem.RemoveFile(filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -782,6 +785,15 @@ u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 outPtr,
|
||||
SaveState::Verify();
|
||||
// TODO: Maybe save/load to a file just to be sure?
|
||||
return 0;
|
||||
|
||||
case 0x20: // EMULATOR_DEVCTL__EMIT_SCREENSHOT
|
||||
u8 *topaddr;
|
||||
u32 linesize, pixelFormat;
|
||||
|
||||
__DisplayGetFramebuf(&topaddr, &linesize, &pixelFormat, 0);
|
||||
// TODO: Convert based on pixel format / mode / something?
|
||||
host->SendDebugScreenshot(topaddr, linesize, 272);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ERROR_LOG(HLE, "sceIoDevCtl: UNKNOWN PARAMETERS");
|
||||
|
||||
@@ -157,6 +157,7 @@ void __KernelDoState(PointerWrap &p)
|
||||
p.DoMarker("KernelObjects");
|
||||
|
||||
__InterruptsDoState(p);
|
||||
// Memory needs to be after kernel objects, which may free kernel memory.
|
||||
__KernelMemoryDoState(p);
|
||||
__KernelThreadingDoState(p);
|
||||
__KernelAlarmDoState(p);
|
||||
|
||||
@@ -1249,7 +1249,7 @@ void sceKernelCheckThreadStack()
|
||||
u32 error;
|
||||
Thread *t = kernelObjects.Get<Thread>(__KernelGetCurThread(), error);
|
||||
if (t) {
|
||||
u32 diff = abs((long)((s64)t->stackBlock - (s64)currentMIPS->r[MIPS_REG_SP]));
|
||||
u32 diff = labs((long)((s64)t->stackBlock - (s64)currentMIPS->r[MIPS_REG_SP]));
|
||||
WARN_LOG(HLE, "%i=sceKernelCheckThreadStack()", diff);
|
||||
RETURN(diff);
|
||||
} else {
|
||||
|
||||
@@ -63,6 +63,7 @@ public:
|
||||
|
||||
// Used for headless.
|
||||
virtual void SendDebugOutput(const std::string &output) {}
|
||||
virtual void SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h) {}
|
||||
};
|
||||
|
||||
extern Host *host;
|
||||
@@ -57,6 +57,7 @@ namespace MIPSComp
|
||||
{
|
||||
s32 simm = (s32)(s16)(op & 0xFFFF); // sign extension
|
||||
u32 uimm = op & 0xFFFF;
|
||||
u32 suimm = (u32)(s32)simm;
|
||||
|
||||
int rt = _RT;
|
||||
int rs = _RS;
|
||||
@@ -113,29 +114,27 @@ namespace MIPSComp
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
case 11: // R(rt) = R(rs) < uimm; break; //sltiu
|
||||
{
|
||||
gpr.MapDirtyIn(rt, rs);
|
||||
Operand2 op2;
|
||||
bool negated;
|
||||
if (TryMakeOperand2_AllowNegation(uimm, op2, &negated)) {
|
||||
if (TryMakeOperand2_AllowNegation(suimm, op2, &negated)) {
|
||||
if (!negated)
|
||||
CMP(gpr.R(rs), op2);
|
||||
else
|
||||
CMN(gpr.R(rs), op2);
|
||||
} else {
|
||||
ARMABI_MOVI2R(R0, uimm);
|
||||
MOVI2R(R0, suimm);
|
||||
CMP(gpr.R(rs), R0);
|
||||
}
|
||||
SetCC(CC_LO);
|
||||
ARMABI_MOVI2R(gpr.R(rt), 1);
|
||||
MOVI2R(gpr.R(rt), 1);
|
||||
SetCC(CC_HS);
|
||||
ARMABI_MOVI2R(gpr.R(rt), 0);
|
||||
MOVI2R(gpr.R(rt), 0);
|
||||
SetCC(CC_AL);
|
||||
}
|
||||
break;
|
||||
*/
|
||||
|
||||
case 15: // R(rt) = uimm << 16; //lui
|
||||
gpr.SetImm(rt, uimm << 16);
|
||||
|
||||
@@ -266,10 +266,10 @@ const MIPSInstruction tableSpecial2[64] =
|
||||
//24
|
||||
{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
|
||||
//32
|
||||
INSTR("cvt.s.w", &Jit::Comp_Generic, Dis_FPU2op, Int_FPU2op, 0),
|
||||
INSTR("cvt.s.w", &Jit::Comp_FPU2op, Dis_FPU2op, Int_FPU2op, 0),
|
||||
{-2}, {-2}, {-2},
|
||||
//36
|
||||
INSTR("cvt.w.s", &Jit::Comp_Generic, Dis_FPU2op, Int_FPU2op, 0),
|
||||
INSTR("cvt.w.s", &Jit::Comp_FPU2op, Dis_FPU2op, Int_FPU2op, 0),
|
||||
{-2},
|
||||
INSTR("dis.int", &Jit::Comp_Generic, Dis_Generic, Int_Interrupt, 0),
|
||||
{-2},
|
||||
|
||||
@@ -181,15 +181,12 @@ void Jit::Comp_FPU2op(u32 op)
|
||||
fpr.ReleaseSpillLocks();
|
||||
break;
|
||||
|
||||
case 12: //FsI(fd) = (int)floorf(F(fs)+0.5f); break; //round.w.s
|
||||
|
||||
case 4: //F(fd) = sqrtf(F(fs)); break; //sqrt
|
||||
/* fpr.Lock(fd, fs); // this probably works, just badly tested
|
||||
fpr.SpillLock(fd, fs); // this probably works, just badly tested
|
||||
fpr.BindToRegister(fd, fd == fs, true);
|
||||
SQRTSS(fpr.RX(fd), fpr.R(fs));
|
||||
fpr.UnlockAll();
|
||||
break;*/
|
||||
Comp_Generic(op);
|
||||
fpr.ReleaseSpillLocks();
|
||||
return;
|
||||
|
||||
case 13: //FsI(fd) = F(fs)>=0 ? (int)floorf(F(fs)) : (int)ceilf(F(fs)); break;//trunc.w.s
|
||||
@@ -200,9 +197,15 @@ void Jit::Comp_FPU2op(u32 op)
|
||||
fpr.ReleaseSpillLocks();
|
||||
break;
|
||||
|
||||
case 32: //F(fd) = (float)FsI(fs); break; //cvt.s.w
|
||||
fpr.StoreFromRegister(fs);
|
||||
CVTSI2SS(XMM0, fpr.R(fs));
|
||||
MOVSS(fpr.R(fd), XMM0);
|
||||
break;
|
||||
|
||||
case 12: //FsI(fd) = (int)floorf(F(fs)+0.5f); break; //round.w.s
|
||||
case 14: //FsI(fd) = (int)ceilf (F(fs)); break; //ceil.w.s
|
||||
case 15: //FsI(fd) = (int)floorf(F(fs)); break; //floor.w.s
|
||||
case 32: //F(fd) = (float)FsI(fs); break; //cvt.s.w
|
||||
case 36: //FsI(fd) = (int) F(fs); break; //cvt.w.s
|
||||
default:
|
||||
Comp_Generic(op);
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common/Log.h"
|
||||
#include "Common/x64Emitter.h"
|
||||
@@ -81,7 +80,7 @@ void FPURegCache::ReleaseSpillLocks() {
|
||||
regs[i].locked = false;
|
||||
}
|
||||
|
||||
void FPURegCache::BindToRegister(int i, bool doLoad, bool makeDirty) {
|
||||
void FPURegCache::BindToRegister(const int i, bool doLoad, bool makeDirty) {
|
||||
_assert_msg_(DYNA_REC, !regs[i].location.IsImm(), "WTF - load - imm");
|
||||
if (!regs[i].away) {
|
||||
// Reg is at home in the memory register file. Let's pull it out.
|
||||
@@ -206,4 +205,4 @@ void FPURegCache::FlushR(X64Reg reg) {
|
||||
if (xregs[reg].mipsReg != -1) {
|
||||
StoreFromRegister(xregs[reg].mipsReg);
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -77,9 +77,10 @@ namespace SaveState
|
||||
Memory::DoState(p);
|
||||
MemoryStick_DoState(p);
|
||||
currentMIPS->DoState(p);
|
||||
pspFileSystem.DoState(p);
|
||||
HLEDoState(p);
|
||||
__KernelDoState(p);
|
||||
// Kernel object destructors might close open files, so do the filesystem last.
|
||||
pspFileSystem.DoState(p);
|
||||
}
|
||||
|
||||
void Enqueue(SaveState::Operation op)
|
||||
|
||||
@@ -124,7 +124,6 @@ static const int flushBeforeCommandList[] = {
|
||||
GE_CMD_SIGNAL,
|
||||
GE_CMD_FINISH,
|
||||
GE_CMD_BJUMP,
|
||||
GE_CMD_OFFSETADDR,
|
||||
GE_CMD_REGION1,GE_CMD_REGION2,
|
||||
GE_CMD_FRAMEBUFPTR,
|
||||
GE_CMD_FRAMEBUFWIDTH,
|
||||
@@ -515,6 +514,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
|
||||
// Throughmode changed, let's make the proj matrix dirty.
|
||||
shaderManager_->DirtyUniform(DIRTY_PROJMATRIX);
|
||||
}
|
||||
shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET);
|
||||
// This sets through-mode or not, as well.
|
||||
break;
|
||||
|
||||
@@ -679,6 +679,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
|
||||
case GE_CMD_TEXSIZE0:
|
||||
gstate_c.curTextureWidth = 1 << (gstate.texsize[0] & 0xf);
|
||||
gstate_c.curTextureHeight = 1 << ((gstate.texsize[0]>>8) & 0xf);
|
||||
shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET);
|
||||
//fall thru - ignoring the mipmap sizes for now
|
||||
case GE_CMD_TEXSIZE1:
|
||||
case GE_CMD_TEXSIZE2:
|
||||
@@ -799,16 +800,8 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
|
||||
case GE_CMD_VIEWPORTY1:
|
||||
case GE_CMD_VIEWPORTX2:
|
||||
case GE_CMD_VIEWPORTY2:
|
||||
break;
|
||||
|
||||
case GE_CMD_VIEWPORTZ1:
|
||||
gstate_c.zScale = getFloat24(data) / 65535.f;
|
||||
break;
|
||||
|
||||
case GE_CMD_VIEWPORTZ2:
|
||||
gstate_c.zOff = getFloat24(data) / 65535.f;
|
||||
break;
|
||||
|
||||
case GE_CMD_LIGHTENABLE0:
|
||||
case GE_CMD_LIGHTENABLE1:
|
||||
case GE_CMD_LIGHTENABLE2:
|
||||
|
||||
@@ -77,7 +77,7 @@ void GenerateFragmentShader(char *buffer)
|
||||
|
||||
|
||||
#if defined(GLSL_ES_1_0)
|
||||
WRITE(p, "precision mediump float;\n");
|
||||
WRITE(p, "precision lowp float;\n");
|
||||
#elif !defined(FORCE_OPENGL_2_0)
|
||||
WRITE(p, "#version 110\n");
|
||||
#endif
|
||||
@@ -86,30 +86,38 @@ void GenerateFragmentShader(char *buffer)
|
||||
|
||||
int doTexture = (gstate.textureMapEnable & 1) && !(gstate.clearmode & 1);
|
||||
bool enableFog = gstate.isFogEnabled() && !gstate.isModeThrough() && !gstate.isModeClear();
|
||||
bool enableAlphaTest = (gstate.alphaTestEnable & 1) && !gstate.isModeClear();
|
||||
bool enableColorTest = (gstate.colorTestEnable & 1) && !gstate.isModeClear();
|
||||
|
||||
|
||||
if (doTexture)
|
||||
WRITE(p, "uniform sampler2D tex;\n");
|
||||
if ((gstate.alphaTestEnable & 1) || (gstate.colorTestEnable & 1)) {
|
||||
if (enableAlphaTest || enableColorTest) {
|
||||
WRITE(p, "uniform vec4 u_alphacolorref;\n");
|
||||
}
|
||||
WRITE(p, "uniform vec3 u_texenv;\n");
|
||||
if (gstate.textureMapEnable & 1) {
|
||||
WRITE(p, "uniform vec3 u_texenv;\n");
|
||||
}
|
||||
WRITE(p, "varying vec4 v_color0;\n");
|
||||
if (lmode)
|
||||
WRITE(p, "varying vec3 v_color1;\n");
|
||||
if (enableFog) {
|
||||
WRITE(p, "uniform vec3 u_fogcolor;\n");
|
||||
#if defined(GLSL_ES_1_0)
|
||||
WRITE(p, "varying mediump float v_fogdepth;\n");
|
||||
#else
|
||||
WRITE(p, "varying float v_fogdepth;\n");
|
||||
#endif
|
||||
}
|
||||
if (doTexture)
|
||||
WRITE(p, "varying vec2 v_texcoord;\n");
|
||||
|
||||
WRITE(p, "void main() {\n");
|
||||
WRITE(p, " vec4 v;\n");
|
||||
|
||||
if (gstate.clearmode & 1)
|
||||
{
|
||||
// Clear mode does not allow any fancy shading.
|
||||
WRITE(p, " v = v_color0;\n");
|
||||
WRITE(p, " gl_FragColor = v_color0;\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -119,59 +127,58 @@ void GenerateFragmentShader(char *buffer)
|
||||
WRITE(p, " vec4 s = vec4(v_color1, 0.0);\n");
|
||||
secondary = " + s";
|
||||
} else {
|
||||
WRITE(p, " vec4 s = vec4(0.0, 0.0, 0.0, 0.0);\n");
|
||||
secondary = "";
|
||||
}
|
||||
|
||||
if (gstate.textureMapEnable & 1) {
|
||||
WRITE(p, " vec4 t = texture2D(tex, v_texcoord);\n");
|
||||
WRITE(p, " vec4 p = clamp(v_color0, 0.0, 1.0);\n");
|
||||
WRITE(p, " vec4 p = v_color0;\n");
|
||||
|
||||
if (gstate.texfunc & 0x100) { // texfmt == RGBA
|
||||
switch (gstate.texfunc & 0x7) {
|
||||
case GE_TEXFUNC_MODULATE:
|
||||
WRITE(p, " v = t * p%s;\n", secondary); break;
|
||||
WRITE(p, " vec4 v = t * p%s;\n", secondary); break;
|
||||
case GE_TEXFUNC_DECAL:
|
||||
WRITE(p, " v = vec4(1.0 - t.a * p.rgb + t.a * u_texenv.rgb, p.a)%s;\n", secondary); break;
|
||||
WRITE(p, " vec4 v = vec4(1.0 - t.a * p.rgb + t.a * u_texenv.rgb, p.a)%s;\n", secondary); break;
|
||||
case GE_TEXFUNC_BLEND:
|
||||
WRITE(p, " v = vec4((1.0 - t.rgb) * p.rgb + t.rgb * u_texenv.rgb, p.a * t.a)%s;\n", secondary); break;
|
||||
WRITE(p, " vec4 v = vec4((1.0 - t.rgb) * p.rgb + t.rgb * u_texenv.rgb, p.a * t.a)%s;\n", secondary); break;
|
||||
case GE_TEXFUNC_REPLACE:
|
||||
WRITE(p, " v = t%s;\n", secondary); break;
|
||||
WRITE(p, " vec4 v = t%s;\n", secondary); break;
|
||||
case GE_TEXFUNC_ADD:
|
||||
WRITE(p, " v = vec4(t.rgb + p.rgb, p.a * t.a)%s;\n", secondary); break;
|
||||
WRITE(p, " vec4 v = vec4(t.rgb + p.rgb, p.a * t.a)%s;\n", secondary); break;
|
||||
default:
|
||||
WRITE(p, " v = p;\n"); break;
|
||||
WRITE(p, " vec4 v = p;\n"); break;
|
||||
}
|
||||
} else { // texfmt == RGB
|
||||
switch (gstate.texfunc & 0x7) {
|
||||
case GE_TEXFUNC_MODULATE:
|
||||
WRITE(p, " v = vec4(t.rgb * p.rgb, p.a)%s;\n", secondary); break;
|
||||
WRITE(p, " vec4 v = vec4(t.rgb * p.rgb, p.a)%s;\n", secondary); break;
|
||||
case GE_TEXFUNC_DECAL:
|
||||
WRITE(p, " v = vec4(t.rgb, p.a)%s;\n", secondary); break;
|
||||
WRITE(p, " vec4 v = vec4(t.rgb, p.a)%s;\n", secondary); break;
|
||||
case GE_TEXFUNC_BLEND:
|
||||
WRITE(p, " v = vec4(1.0 - t.rgb) * p.rgb + t.rgb * u_texenv.rgb, p.a)%s;\n", secondary); break;
|
||||
WRITE(p, " vec4 v = vec4(1.0 - t.rgb) * p.rgb + t.rgb * u_texenv.rgb, p.a)%s;\n", secondary); break;
|
||||
case GE_TEXFUNC_REPLACE:
|
||||
WRITE(p, " v = vec4(t.rgb, p.a)%s;\n", secondary); break;
|
||||
WRITE(p, " vec4 v = vec4(t.rgb, p.a)%s;\n", secondary); break;
|
||||
case GE_TEXFUNC_ADD:
|
||||
WRITE(p, " v = vec4(t.rgb + p.rgb, p.a)%s;\n", secondary); break;
|
||||
WRITE(p, " vec4 v = vec4(t.rgb + p.rgb, p.a)%s;\n", secondary); break;
|
||||
default:
|
||||
WRITE(p, " v = p;\n"); break;
|
||||
WRITE(p, " vec4 v = p;\n"); break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No texture mapping
|
||||
WRITE(p, " v = clamp(v_color0, 0.0, 1.0)%s;\n", secondary);
|
||||
WRITE(p, " vec4 v = v_color0 %s;\n", secondary);
|
||||
}
|
||||
// Color doubling
|
||||
if (gstate.texfunc & 0x10000) {
|
||||
WRITE(p, " v = v * vec4(2.0, 2.0, 2.0, 2.0);");
|
||||
WRITE(p, " v = v * 2.0;\n");
|
||||
}
|
||||
|
||||
if (gstate.alphaTestEnable & 1) {
|
||||
if (enableAlphaTest) {
|
||||
int alphaTestFunc = gstate.alphatest & 7;
|
||||
const char *alphaTestFuncs[] = { "#", "#", " == ", " != ", " < ", " <= ", " > ", " >= " }; // never/always don't make sense
|
||||
if (alphaTestFuncs[alphaTestFunc][0] != '#')
|
||||
WRITE(p, "if (!(v.a %s u_alphacolorref.a)) discard;", alphaTestFuncs[alphaTestFunc]);
|
||||
WRITE(p, " if (!(v.a %s u_alphacolorref.a)) discard;\n", alphaTestFuncs[alphaTestFunc]);
|
||||
}
|
||||
|
||||
// Disabled for now until we actually find a need for it.
|
||||
@@ -187,20 +194,20 @@ void GenerateFragmentShader(char *buffer)
|
||||
|
||||
if (enableFog) {
|
||||
WRITE(p, " float fogCoef = clamp(v_fogdepth, 0.0, 1.0);\n");
|
||||
WRITE(p, " v = mix(vec4(u_fogcolor, v.a), v, fogCoef);\n");
|
||||
WRITE(p, " gl_FragColor = mix(vec4(u_fogcolor, v.a), v, fogCoef);\n");
|
||||
// WRITE(p, " v.x = v_depth;\n");
|
||||
} else {
|
||||
WRITE(p, " gl_FragColor = v;\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef DEBUG_SHADER
|
||||
if (doTexture) {
|
||||
WRITE(p, " v = texture2D(tex, v_texcoord);\n");
|
||||
WRITE(p, " gl_FragColor = texture2D(tex, v_texcoord);\n");
|
||||
} else {
|
||||
WRITE(p, " v = vec4(1,0,1,1);\n");
|
||||
WRITE(p, " gl_FragColor = vec4(1,0,1,1);\n");
|
||||
}
|
||||
#endif
|
||||
WRITE(p, " gl_FragColor = v;\n");
|
||||
WRITE(p, "}\n");
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ Shader::Shader(const char *code, uint32_t shaderType) {
|
||||
OutputDebugString(code);
|
||||
#endif
|
||||
shader = glCreateShader(shaderType);
|
||||
glShaderSource(shader, 1, &code, 0);
|
||||
glShaderSource(shader, 1, &code, 0);
|
||||
glCompileShader(shader);
|
||||
GLint success;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
||||
@@ -264,7 +264,16 @@ void LinkedShader::updateUniforms() {
|
||||
|
||||
// Texturing
|
||||
if (u_uvscaleoffset != -1 && (dirtyUniforms & DIRTY_UVSCALEOFFSET)) {
|
||||
const float uvscaleoff[4] = { gstate_c.uScale, gstate_c.vScale, gstate_c.uOff, gstate_c.vOff};
|
||||
float uvscaleoff[4] = { gstate_c.uScale, gstate_c.vScale, gstate_c.uOff, gstate_c.vOff};
|
||||
if (gstate.isModeThrough()) {
|
||||
uvscaleoff[0] /= gstate_c.curTextureWidth;
|
||||
uvscaleoff[1] /= gstate_c.curTextureHeight;
|
||||
uvscaleoff[2] /= gstate_c.curTextureWidth;
|
||||
uvscaleoff[3] /= gstate_c.curTextureHeight;
|
||||
} else {
|
||||
uvscaleoff[0] *= 2.0f;
|
||||
uvscaleoff[1] *= 2.0f;
|
||||
}
|
||||
glUniform4fv(u_uvscaleoffset, 1, uvscaleoff);
|
||||
}
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ void TransformDrawEngine::ApplyDrawState(int prim) {
|
||||
bool wantDepthTest = gstate.isModeClear() || gstate.isDepthTestEnabled();
|
||||
glstate.depthTest.set(wantDepthTest);
|
||||
if(wantDepthTest) {
|
||||
// Force GL_ALWAYS if mode clear
|
||||
// Force GL_ALWAYS if mode clear - without depth test, no depth write.
|
||||
int depthTestFunc = gstate.isModeClear() ? 1 : gstate.getDepthTestFunc();
|
||||
glstate.depthFunc.set(ztests[depthTestFunc]);
|
||||
}
|
||||
@@ -208,10 +208,6 @@ void TransformDrawEngine::ApplyDrawState(int prim) {
|
||||
|
||||
bool wantDepthWrite = gstate.isModeClear() || gstate.isDepthWriteEnabled();
|
||||
glstate.depthWrite.set(wantDepthWrite ? GL_TRUE : GL_FALSE);
|
||||
|
||||
float depthRangeMin = gstate_c.zOff - gstate_c.zScale;
|
||||
float depthRangeMax = gstate_c.zOff + gstate_c.zScale;
|
||||
glstate.depthRange.set(depthRangeMin, depthRangeMax);
|
||||
}
|
||||
|
||||
void TransformDrawEngine::UpdateViewportAndProjection() {
|
||||
@@ -240,14 +236,13 @@ void TransformDrawEngine::UpdateViewportAndProjection() {
|
||||
if (throughmode) {
|
||||
// No viewport transform here. Let's experiment with using region.
|
||||
glstate.viewport.set((0 + regionX1) * renderWidthFactor, (0 - regionY1) * renderHeightFactor, (regionX2 - regionX1) * renderWidthFactor, (regionY2 - regionY1) * renderHeightFactor);
|
||||
glstate.depthRange.set(1.0, 0.0);
|
||||
} else {
|
||||
// These we can turn into a glViewport call, offset by offsetX and offsetY. Math after.
|
||||
float vpXa = getFloat24(gstate.viewportx1);
|
||||
float vpXb = getFloat24(gstate.viewportx2);
|
||||
float vpYa = getFloat24(gstate.viewporty1);
|
||||
float vpYb = getFloat24(gstate.viewporty2);
|
||||
float vpZa = getFloat24(gstate.viewportz1); // / 65536.0f should map it to OpenGL's 0.0-1.0 Z range
|
||||
float vpZb = getFloat24(gstate.viewportz2); // / 65536.0f
|
||||
|
||||
// The viewport transform appears to go like this:
|
||||
// Xscreen = -offsetX + vpXb + vpXa * Xview
|
||||
@@ -263,10 +258,6 @@ void TransformDrawEngine::UpdateViewportAndProjection() {
|
||||
float vpWidth = fabsf(gstate_c.vpWidth);
|
||||
float vpHeight = fabsf(gstate_c.vpHeight);
|
||||
|
||||
// TODO: These two should feed into glDepthRange somehow.
|
||||
float vpZ0 = (vpZb - vpZa) / 65536.0f;
|
||||
float vpZ1 = (vpZa * 2) / 65536.0f;
|
||||
|
||||
vpX0 *= renderWidthFactor;
|
||||
vpY0 *= renderHeightFactor;
|
||||
vpWidth *= renderWidthFactor;
|
||||
@@ -277,5 +268,11 @@ void TransformDrawEngine::UpdateViewportAndProjection() {
|
||||
glstate.viewport.set(vpX0, vpY0, vpWidth, vpHeight);
|
||||
// Sadly, as glViewport takes integers, we will not be able to support sub pixel offsets this way. But meh.
|
||||
// shaderManager_->DirtyUniform(DIRTY_PROJMATRIX);
|
||||
|
||||
float zScale = getFloat24(gstate.viewportz1) / 65535.f;
|
||||
float zOff = getFloat24(gstate.viewportz2) / 65535.f;
|
||||
float depthRangeMin = zOff - zScale;
|
||||
float depthRangeMax = zOff + zScale;
|
||||
glstate.depthRange.set(depthRangeMin, depthRangeMax);
|
||||
}
|
||||
}
|
||||
+127
-57
@@ -112,6 +112,8 @@ void TextureCache::InvalidateAll(bool force) {
|
||||
}
|
||||
|
||||
TextureCache::TexCacheEntry *TextureCache::GetEntryAt(u32 texaddr) {
|
||||
// If no CLUT, as in framebuffer textures, cache key is simply texaddr.
|
||||
auto iter = cache.find(texaddr);
|
||||
for (auto entry = cache.begin(); entry != cache.end(); ++entry) {
|
||||
if (entry->second.addr == texaddr) {
|
||||
return &entry->second;
|
||||
@@ -121,11 +123,13 @@ TextureCache::TexCacheEntry *TextureCache::GetEntryAt(u32 texaddr) {
|
||||
}
|
||||
|
||||
void TextureCache::NotifyFramebuffer(u32 address, FBO *fbo) {
|
||||
// Must be in VRAM so | 0x04000000 it is.
|
||||
TexCacheEntry *entry = GetEntryAt(address | 0x04000000);
|
||||
if (entry) {
|
||||
INFO_LOG(HLE, "Render to texture detected at %08x!", address);
|
||||
if (!entry->fbo)
|
||||
entry->fbo = fbo;
|
||||
// TODO: Delete the original non-fbo texture too.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,9 +374,9 @@ GLenum getClutDestFormat(GEPaletteFormat format) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const u8 texByteAlignMap[] = {2, 2, 2, 4};
|
||||
static const u8 texByteAlignMap[] = {2, 2, 2, 4};
|
||||
|
||||
const GLuint MinFiltGL[8] = {
|
||||
static const GLuint MinFiltGL[8] = {
|
||||
GL_NEAREST,
|
||||
GL_LINEAR,
|
||||
GL_NEAREST,
|
||||
@@ -383,11 +387,16 @@ const GLuint MinFiltGL[8] = {
|
||||
GL_LINEAR_MIPMAP_LINEAR,
|
||||
};
|
||||
|
||||
const GLuint MagFiltGL[2] = {
|
||||
static const GLuint MagFiltGL[2] = {
|
||||
GL_NEAREST,
|
||||
GL_LINEAR
|
||||
};
|
||||
|
||||
// OpenGL ES 2.0 workaround. Let's see if this hackery works.
|
||||
#ifndef GL_TEXTURE_LOD_BIAS
|
||||
#define GL_TEXTURE_LOD_BIAS 0x8501
|
||||
#endif
|
||||
|
||||
// This should not have to be done per texture! OpenGL is silly yo
|
||||
// TODO: Dirty-check this against the current texture.
|
||||
void TextureCache::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
|
||||
@@ -396,8 +405,17 @@ void TextureCache::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
|
||||
bool sClamp = gstate.texwrap & 1;
|
||||
bool tClamp = (gstate.texwrap>>8) & 1;
|
||||
|
||||
// TODO: remove this line when we support mipmaps
|
||||
minFilt &= 1; // no mipmaps yet
|
||||
if (entry.maxLevel == 0) {
|
||||
// Enforce no mip filtering, for safety.
|
||||
minFilt &= 1; // no mipmaps yet
|
||||
} else {
|
||||
// TODO: Is this a signed value? Which direction?
|
||||
float lodBias = 0.0; // -(float)((gstate.texlevel >> 16) & 0xFF) / 16.0f;
|
||||
if (force || entry.lodBias != lodBias) {
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, lodBias);
|
||||
entry.lodBias = lodBias;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_Config.bLinearFiltering) {
|
||||
magFilt |= 1;
|
||||
@@ -462,7 +480,7 @@ struct DXT5Block {
|
||||
};
|
||||
|
||||
static inline u32 makecol(int r, int g, int b, int a) {
|
||||
return (a << 24)|(r << 16)|(g << 8)|b;
|
||||
return (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
// This could probably be done faster by decoding two or four blocks at a time with SSE/NEON.
|
||||
@@ -641,7 +659,6 @@ void TextureCache::SetTexture() {
|
||||
return;
|
||||
}
|
||||
|
||||
u8 level = 0;
|
||||
u32 format = gstate.texformat & 0xF;
|
||||
if (format >= 11) {
|
||||
ERROR_LOG(G3D, "Unknown texture format %i", format);
|
||||
@@ -649,38 +666,50 @@ void TextureCache::SetTexture() {
|
||||
}
|
||||
bool hasClut = formatUsesClut[format];
|
||||
|
||||
const u8 *texptr = Memory::GetPointer(texaddr);
|
||||
|
||||
u32 clutformat = gstate.clutformat & 3;
|
||||
u32 clutaddr = GetClutAddr(clutformat == GE_CMODE_32BIT_ABGR8888 ? 4 : 2);
|
||||
|
||||
const u8 *texptr = Memory::GetPointer(texaddr);
|
||||
u32 texhash = texptr ? MiniHash((const u32*)texptr) : 0;
|
||||
u64 cachekey = texaddr;
|
||||
if (formatUsesClut[format])
|
||||
cachekey |= (u64)clutaddr << 32;
|
||||
|
||||
u64 cachekey = texaddr ^ texhash;
|
||||
if (hasClut) {
|
||||
cachekey |= (u64) clutaddr << 32;
|
||||
int maxLevel = ((gstate.texmode >> 16) & 0x7);
|
||||
|
||||
// Adjust maxLevel to actually present levels..
|
||||
for (int i = 0; i <= maxLevel; i++) {
|
||||
// If encountering levels pointing to nothing, adjust max level.
|
||||
u32 levelTexaddr = (gstate.texaddr[i] & 0xFFFFF0) | ((gstate.texbufwidth[i] << 8) & 0x0F000000);
|
||||
if (!Memory::IsValidAddress(levelTexaddr)) {
|
||||
maxLevel = i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
u32 texhash = MiniHash((const u32 *)Memory::GetPointer(texaddr));
|
||||
|
||||
int w = 1 << (gstate.texsize[0] & 0xf);
|
||||
int h = 1 << ((gstate.texsize[0]>>8) & 0xf);
|
||||
int h = 1 << ((gstate.texsize[0] >> 8) & 0xf);
|
||||
|
||||
// Check for FBO - slow!
|
||||
TexCacheEntry *fboEntry = GetEntryAt(texaddr);
|
||||
if (fboEntry && fboEntry->fbo) {
|
||||
fbo_bind_color_as_texture(fboEntry->fbo, 0);
|
||||
UpdateSamplingParams(*fboEntry, false);
|
||||
|
||||
int fbow, fboh;
|
||||
fbo_get_dimensions(fboEntry->fbo, &fbow, &fboh);
|
||||
|
||||
gstate_c.curTextureWidth = w / fbow; // except not -
|
||||
gstate_c.curTextureHeight = h / fboh;
|
||||
return;
|
||||
}
|
||||
|
||||
TexCache::iterator iter = cache.find(cachekey);
|
||||
if (iter != cache.end()) {
|
||||
//Validate the texture here (width, height etc)
|
||||
TexCacheEntry &entry = iter->second;
|
||||
// Check for FBO - slow!
|
||||
if (entry.fbo) {
|
||||
fbo_bind_color_as_texture(entry.fbo, 0);
|
||||
UpdateSamplingParams(entry, false);
|
||||
|
||||
int fbow, fboh;
|
||||
fbo_get_dimensions(entry.fbo, &fbow, &fboh);
|
||||
|
||||
// Almost certain this isn't right.
|
||||
gstate_c.curTextureWidth = fbow;
|
||||
gstate_c.curTextureHeight = fboh;
|
||||
return;
|
||||
}
|
||||
|
||||
//Validate the texture here (width, height etc)
|
||||
|
||||
int dim = gstate.texsize[0] & 0xF0F;
|
||||
bool match = true;
|
||||
@@ -710,6 +739,8 @@ void TextureCache::SetTexture() {
|
||||
match = false;
|
||||
}
|
||||
}
|
||||
if (entry.maxLevel != maxLevel)
|
||||
match = false;
|
||||
|
||||
if (match) {
|
||||
//got one!
|
||||
@@ -738,6 +769,8 @@ void TextureCache::SetTexture() {
|
||||
entry.format = format;
|
||||
entry.frameCounter = gpuStats.numFrames;
|
||||
entry.fbo = 0;
|
||||
entry.maxLevel = maxLevel;
|
||||
entry.lodBias = 0.0f;
|
||||
|
||||
if (format >= GE_TFMT_CLUT4 && format <= GE_TFMT_CLUT32) {
|
||||
entry.clutformat = clutformat;
|
||||
@@ -759,38 +792,86 @@ void TextureCache::SetTexture() {
|
||||
for (u32 i = 0; i < (entry.sizeInRAM * 2) / 4; ++i)
|
||||
entry.fullhash += *checkp++;
|
||||
|
||||
gstate_c.curTextureWidth=w;
|
||||
gstate_c.curTextureHeight=h;
|
||||
GLenum dstFmt = 0;
|
||||
u32 texByteAlign = 1;
|
||||
gstate_c.curTextureWidth = w;
|
||||
gstate_c.curTextureHeight = h;
|
||||
|
||||
glGenTextures(1, &entry.texture);
|
||||
glBindTexture(GL_TEXTURE_2D, entry.texture);
|
||||
|
||||
#ifdef USING_GLES2
|
||||
// GLES2 doesn't have support for a "Max lod" which is critical as PSP games often
|
||||
// don't specify mips all the way down. As a result, we either need to manually generate
|
||||
// the bottom few levels or rely on OpenGL's autogen mipmaps instead, which might not
|
||||
// be as good quality as the game's own (might even be better in some cases though).
|
||||
|
||||
// For now, I choose to use autogen mips on GLES2 and the game's own on other platforms.
|
||||
// As is usual, GLES3 will solve this problem nicely but wide distribution of that is
|
||||
// years away.
|
||||
LoadTextureLevel(entry, 0);
|
||||
if (entry.maxLevel > 0)
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
#else
|
||||
for (int i = 0; i <= entry.maxLevel; i++) {
|
||||
LoadTextureLevel(entry, i);
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, entry.maxLevel);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, entry.maxLevel);
|
||||
#endif
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 4);
|
||||
|
||||
UpdateSamplingParams(entry, true);
|
||||
|
||||
//glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
//glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
|
||||
cache[cachekey] = entry;
|
||||
}
|
||||
|
||||
|
||||
void TextureCache::LoadTextureLevel(TexCacheEntry &entry, int level)
|
||||
{
|
||||
void *finalBuf = NULL;
|
||||
|
||||
// TODO: only do this once
|
||||
u32 texByteAlign = 1;
|
||||
|
||||
// TODO: Look into using BGRA for 32-bit textures when the GL_EXT_texture_format_BGRA8888 extension is available, as it's faster than RGBA on some chips.
|
||||
GLenum dstFmt = 0;
|
||||
|
||||
// TODO: Actually decode the mipmaps.
|
||||
|
||||
switch (format)
|
||||
u32 texaddr = (gstate.texaddr[level] & 0xFFFFF0) | ((gstate.texbufwidth[level] << 8) & 0x0F000000);
|
||||
|
||||
int bufw = gstate.texbufwidth[level] & 0x3ff;
|
||||
|
||||
|
||||
int w = 1 << (gstate.texsize[level] & 0xf);
|
||||
int h = 1 << ((gstate.texsize[level] >> 8) & 0xf);
|
||||
const u8 *texptr = Memory::GetPointer(texaddr);
|
||||
|
||||
switch (entry.format)
|
||||
{
|
||||
case GE_TFMT_CLUT4:
|
||||
dstFmt = getClutDestFormat((GEPaletteFormat)(gstate.clutformat & 3));
|
||||
dstFmt = getClutDestFormat((GEPaletteFormat)(entry.clutformat));
|
||||
|
||||
switch (clutformat) {
|
||||
switch (entry.clutformat) {
|
||||
case GE_CMODE_16BIT_BGR5650:
|
||||
case GE_CMODE_16BIT_ABGR5551:
|
||||
case GE_CMODE_16BIT_ABGR4444:
|
||||
{
|
||||
ReadClut16(clutBuf16);
|
||||
const u16 *clut = clutBuf16;
|
||||
u32 clutSharingOff = 0;//gstate.mipmapShareClut ? 0 : level * 16;
|
||||
u32 clutSharingOffset = 0; //(gstate.mipmapShareClut & 1) ? 0 : level * 16;
|
||||
texByteAlign = 2;
|
||||
if (!(gstate.texmode & 1)) {
|
||||
const u8 *addr = Memory::GetPointer(texaddr);
|
||||
for (int i = 0; i < bufw * h; i += 2)
|
||||
{
|
||||
u8 index = *addr++;
|
||||
tmpTexBuf16[i + 0] = clut[GetClutIndex((index >> 0) & 0xf) + clutSharingOff];
|
||||
tmpTexBuf16[i + 1] = clut[GetClutIndex((index >> 4) & 0xf) + clutSharingOff];
|
||||
tmpTexBuf16[i + 0] = clut[GetClutIndex((index >> 0) & 0xf) + clutSharingOffset];
|
||||
tmpTexBuf16[i + 1] = clut[GetClutIndex((index >> 4) & 0xf) + clutSharingOffset];
|
||||
}
|
||||
} else {
|
||||
UnswizzleFromMem(texaddr, 0, level);
|
||||
@@ -800,7 +881,7 @@ void TextureCache::SetTexture() {
|
||||
u32 k, index;
|
||||
for (k = 0; k < 8; k++) {
|
||||
index = (n >> (k * 4)) & 0xf;
|
||||
tmpTexBuf16[i + k] = clut[GetClutIndex(index) + clutSharingOff];
|
||||
tmpTexBuf16[i + k] = clut[GetClutIndex(index) + clutSharingOffset];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -863,11 +944,11 @@ void TextureCache::SetTexture() {
|
||||
case GE_TFMT_4444:
|
||||
case GE_TFMT_5551:
|
||||
case GE_TFMT_5650:
|
||||
if (format == GE_TFMT_4444)
|
||||
if (entry.format == GE_TFMT_4444)
|
||||
dstFmt = GL_UNSIGNED_SHORT_4_4_4_4;
|
||||
else if (format == GE_TFMT_5551)
|
||||
else if (entry.format == GE_TFMT_5551)
|
||||
dstFmt = GL_UNSIGNED_SHORT_5_5_5_1;
|
||||
else if (format == GE_TFMT_5650)
|
||||
else if (entry.format == GE_TFMT_5650)
|
||||
dstFmt = GL_UNSIGNED_SHORT_5_6_5;
|
||||
texByteAlign = 2;
|
||||
|
||||
@@ -931,7 +1012,7 @@ void TextureCache::SetTexture() {
|
||||
break;
|
||||
|
||||
case GE_TFMT_DXT5:
|
||||
ERROR_LOG(G3D, "Unhandled compressed texture, format %i! swizzle=%i", format, gstate.texmode & 1);
|
||||
ERROR_LOG(G3D, "Unhandled compressed texture, format %i! swizzle=%i", entry.format, gstate.texmode & 1);
|
||||
dstFmt = GL_UNSIGNED_BYTE;
|
||||
{
|
||||
u32 *dst = tmpTexBuf32;
|
||||
@@ -951,7 +1032,7 @@ void TextureCache::SetTexture() {
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR_LOG(G3D, "Unknown Texture Format %d!!!", format);
|
||||
ERROR_LOG(G3D, "Unknown Texture Format %d!!!", entry.format);
|
||||
finalBuf = tmpTexBuf32;
|
||||
return;
|
||||
}
|
||||
@@ -999,19 +1080,8 @@ void TextureCache::SetTexture() {
|
||||
//glPixelStorei(GL_PACK_ROW_LENGTH, bufw);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, texByteAlign);
|
||||
|
||||
INFO_LOG(G3D, "Creating texture %i from %08x: %i x %i (stride: %i). fmt: %i", entry.texture, entry.addr, w, h, bufw, entry.format);
|
||||
INFO_LOG(HLE, "Creating texture level %i/%i from %08x: %i x %i (stride: %i). fmt: %i", level, entry.maxLevel, texaddr, w, h, bufw, entry.format);
|
||||
|
||||
glGenTextures(1, &entry.texture);
|
||||
glBindTexture(GL_TEXTURE_2D, entry.texture);
|
||||
GLuint components = dstFmt == GL_UNSIGNED_SHORT_5_6_5 ? GL_RGB : GL_RGBA;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, components, w, h, 0, components, dstFmt, finalBuf);
|
||||
// glGenerateMipmap(GL_TEXTURE_2D);
|
||||
UpdateSamplingParams(entry, true);
|
||||
|
||||
//glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
//glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
|
||||
cache[cachekey] = entry;
|
||||
glTexImage2D(GL_TEXTURE_2D, level, components, w, h, 0, components, dstFmt, finalBuf);
|
||||
}
|
||||
@@ -58,6 +58,8 @@ private:
|
||||
u32 texture; //GLuint
|
||||
int invalidHint;
|
||||
u32 fullhash;
|
||||
int maxLevel;
|
||||
float lodBias;
|
||||
|
||||
// Cache the current filter settings so we can avoid setting it again.
|
||||
u8 magFilt;
|
||||
@@ -70,6 +72,7 @@ private:
|
||||
void *UnswizzleFromMem(u32 texaddr, u32 bytesPerPixel, u32 level);
|
||||
void *readIndexedTex(int level, u32 texaddr, int bytesPerIndex);
|
||||
void UpdateSamplingParams(TexCacheEntry &entry, bool force);
|
||||
void LoadTextureLevel(TexCacheEntry &entry, int level);
|
||||
|
||||
TexCacheEntry *GetEntryAt(u32 texaddr);
|
||||
|
||||
|
||||
@@ -262,7 +262,7 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[
|
||||
}
|
||||
|
||||
Color4 lightDiff(gstate_c.lightColor[1][l], 0.0f);
|
||||
Color4 diff = (lightDiff * *diffuse) * (dot * lightScale);
|
||||
Color4 diff = (lightDiff * *diffuse) * (max(dot, 0.0f) * lightScale);
|
||||
|
||||
// Real PSP specular
|
||||
Vec3 toViewer(0,0,1);
|
||||
@@ -276,10 +276,10 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[
|
||||
halfVec.Normalize();
|
||||
|
||||
dot = halfVec * norm;
|
||||
if (dot >= 0)
|
||||
if (dot > 0)
|
||||
{
|
||||
Color4 lightSpec(gstate_c.lightColor[2][l], 0.0f);
|
||||
lightSum1 += (lightSpec * *specular * (powf(dot, specCoef_)*lightScale));
|
||||
lightSum1 += (lightSpec * *specular * (powf(dot, specCoef_) * lightScale));
|
||||
}
|
||||
}
|
||||
dots[l] = dot;
|
||||
@@ -315,6 +315,12 @@ static const GlTypeInfo GLComp[] = {
|
||||
{GL_UNSIGNED_BYTE, 2, GL_TRUE},// DEC_U8_2,
|
||||
{GL_UNSIGNED_BYTE, 3, GL_TRUE},// DEC_U8_3,
|
||||
{GL_UNSIGNED_BYTE, 4, GL_TRUE},// DEC_U8_4,
|
||||
{GL_UNSIGNED_SHORT, 1, GL_TRUE},// DEC_U16_1,
|
||||
{GL_UNSIGNED_SHORT, 2, GL_TRUE},// DEC_U16_2,
|
||||
{GL_UNSIGNED_SHORT, 3, GL_TRUE},// DEC_U16_3,
|
||||
{GL_UNSIGNED_SHORT, 4, GL_TRUE},// DEC_U16_4,
|
||||
{GL_UNSIGNED_BYTE, 2, GL_FALSE},// DEC_U8A_2,
|
||||
{GL_UNSIGNED_SHORT, 2, GL_FALSE},// DEC_U16A_2,
|
||||
};
|
||||
|
||||
static inline void VertexAttribSetup(int attrib, int fmt, int stride, u8 *ptr) {
|
||||
@@ -399,6 +405,13 @@ void TransformDrawEngine::SoftwareTransformAndDraw(
|
||||
vertexCount = 0x10000/3;
|
||||
#endif
|
||||
|
||||
float uscale = 1.0f;
|
||||
float vscale = 1.0f;
|
||||
if (throughmode) {
|
||||
uscale /= gstate_c.curTextureWidth;
|
||||
vscale /= gstate_c.curTextureHeight;
|
||||
}
|
||||
|
||||
Lighter lighter;
|
||||
float fog_end = getFloat24(gstate.fog1);
|
||||
float fog_slope = getFloat24(gstate.fog2);
|
||||
@@ -430,6 +443,9 @@ void TransformDrawEngine::SoftwareTransformAndDraw(
|
||||
|
||||
if (reader.hasUV()) {
|
||||
reader.ReadUV(uv);
|
||||
|
||||
uv[0] *= uscale;
|
||||
uv[1] *= vscale;
|
||||
}
|
||||
fogCoef = 1.0f;
|
||||
// Scale UV?
|
||||
@@ -529,8 +545,8 @@ void TransformDrawEngine::SoftwareTransformAndDraw(
|
||||
{
|
||||
case 0: // UV mapping
|
||||
// Texture scale/offset is only performed in this mode.
|
||||
uv[0] = ruv[0]*gstate_c.uScale + gstate_c.uOff;
|
||||
uv[1] = ruv[1]*gstate_c.vScale + gstate_c.vOff;
|
||||
uv[0] = uscale * (ruv[0]*gstate_c.uScale + gstate_c.uOff);
|
||||
uv[1] = vscale * (ruv[1]*gstate_c.vScale + gstate_c.vOff);
|
||||
break;
|
||||
case 1:
|
||||
{
|
||||
@@ -580,8 +596,12 @@ void TransformDrawEngine::SoftwareTransformAndDraw(
|
||||
memcpy(&transformed[index].x, v, 3 * sizeof(float));
|
||||
transformed[index].fog = fogCoef;
|
||||
memcpy(&transformed[index].u, uv, 2 * sizeof(float));
|
||||
memcpy(&transformed[index].color0, c0, 4 * sizeof(float));
|
||||
memcpy(&transformed[index].color1, c1, 3 * sizeof(float));
|
||||
for (int i = 0; i < 4; i++) {
|
||||
transformed[index].color0[i] = c0[i] * 255.0f;
|
||||
}
|
||||
for (int i = 0; i < 4; i++) {
|
||||
transformed[index].color1[i] = c1[i] * 255.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: expand rectangles.
|
||||
@@ -674,8 +694,8 @@ void TransformDrawEngine::SoftwareTransformAndDraw(
|
||||
}
|
||||
glVertexAttribPointer(program->a_position, 4, GL_FLOAT, GL_FALSE, vertexSize, drawBuffer);
|
||||
if (program->a_texcoord != -1) glVertexAttribPointer(program->a_texcoord, 2, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 4 * 4);
|
||||
if (program->a_color0 != -1) glVertexAttribPointer(program->a_color0, 4, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 6 * 4);
|
||||
if (program->a_color1 != -1) glVertexAttribPointer(program->a_color1, 3, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 10 * 4);
|
||||
if (program->a_color0 != -1) glVertexAttribPointer(program->a_color0, 4, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, ((uint8_t*)drawBuffer) + 6 * 4);
|
||||
if (program->a_color1 != -1) glVertexAttribPointer(program->a_color1, 3, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, ((uint8_t*)drawBuffer) + 7 * 4);
|
||||
if (drawIndexed) {
|
||||
if (useVBO) {
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_[curVbo_]);
|
||||
@@ -800,6 +820,7 @@ u32 TransformDrawEngine::ComputeHash() {
|
||||
u32 fullhash = 0;
|
||||
int vertexSize = dec.GetDecVtxFmt().stride;
|
||||
|
||||
// TODO: Add some caps both for numDrawCalls and num verts to check?
|
||||
for (int i = 0; i < numDrawCalls; i++) {
|
||||
if (!drawCalls[i].inds) {
|
||||
fullhash += CityHash32((const char *)drawCalls[i].verts, vertexSize * drawCalls[i].vertexCount);
|
||||
@@ -842,7 +863,7 @@ void TransformDrawEngine::ClearTrackedVertexArrays() {
|
||||
void TransformDrawEngine::DecimateTrackedVertexArrays() {
|
||||
int threshold = gpuStats.numFrames - VAI_KILL_AGE;
|
||||
for (auto iter = vai_.begin(); iter != vai_.end(); ) {
|
||||
if (iter->second->lastFrame < threshold ) {
|
||||
if (iter->second->lastFrame < threshold) {
|
||||
delete iter->second;
|
||||
vai_.erase(iter++);
|
||||
}
|
||||
@@ -901,6 +922,7 @@ void TransformDrawEngine::Flush() {
|
||||
u32 dataHash = ComputeHash();
|
||||
vai->hash = dataHash;
|
||||
vai->status = VertexArrayInfo::VAI_HASHING;
|
||||
vai->drawsUntilNextFullHash = 0;
|
||||
DecodeVerts(); // writes to indexGen
|
||||
goto rotateVBO;
|
||||
}
|
||||
@@ -909,27 +931,33 @@ void TransformDrawEngine::Flush() {
|
||||
// But if we get this far it's likely to be worth creating a vertex buffer.
|
||||
case VertexArrayInfo::VAI_HASHING:
|
||||
{
|
||||
u32 newHash = ComputeHash();
|
||||
vai->numDraws++;
|
||||
// TODO: tweak
|
||||
if (vai->numDraws > 100000) {
|
||||
vai->status = VertexArrayInfo::VAI_RELIABLE;
|
||||
}
|
||||
if (newHash == vai->hash) {
|
||||
gpuStats.numCachedDrawCalls++;
|
||||
if (vai->drawsUntilNextFullHash == 0) {
|
||||
u32 newHash = ComputeHash();
|
||||
// exponential backoff up to 16 frames
|
||||
vai->drawsUntilNextFullHash = std::min(16, vai->numDraws);
|
||||
// TODO: tweak
|
||||
//if (vai->numDraws > 1000) {
|
||||
// vai->status = VertexArrayInfo::VAI_RELIABLE;
|
||||
//}
|
||||
if (newHash != vai->hash) {
|
||||
vai->status = VertexArrayInfo::VAI_UNRELIABLE;
|
||||
if (vai->vbo) {
|
||||
glDeleteBuffers(1, &vai->vbo);
|
||||
vai->vbo = 0;
|
||||
}
|
||||
if (vai->ebo) {
|
||||
glDeleteBuffers(1, &vai->ebo);
|
||||
vai->ebo = 0;
|
||||
}
|
||||
DecodeVerts();
|
||||
goto rotateVBO;
|
||||
}
|
||||
} else {
|
||||
vai->status = VertexArrayInfo::VAI_UNRELIABLE;
|
||||
if (vai->vbo) {
|
||||
glDeleteBuffers(1, &vai->vbo);
|
||||
vai->vbo = 0;
|
||||
}
|
||||
if (vai->ebo) {
|
||||
glDeleteBuffers(1, &vai->ebo);
|
||||
vai->ebo = 0;
|
||||
}
|
||||
DecodeVerts();
|
||||
goto rotateVBO;
|
||||
vai->drawsUntilNextFullHash--;
|
||||
// TODO: "mini-hashing" the first 32 bytes of the vertex/index data or something.
|
||||
}
|
||||
|
||||
if (vai->vbo == 0) {
|
||||
DecodeVerts();
|
||||
vai->numVerts = indexGen.VertexCount();
|
||||
@@ -951,6 +979,7 @@ void TransformDrawEngine::Flush() {
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
} else {
|
||||
gpuStats.numCachedDrawCalls++;
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vai->vbo);
|
||||
if (vai->ebo)
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vai->ebo);
|
||||
|
||||
@@ -57,6 +57,7 @@ public:
|
||||
numDraws = 0;
|
||||
lastFrame = gpuStats.numFrames;
|
||||
numVerts = 0;
|
||||
drawsUntilNextFullHash = 0;
|
||||
}
|
||||
~VertexArrayInfo();
|
||||
enum Status {
|
||||
@@ -73,6 +74,7 @@ public:
|
||||
u32 vbo;
|
||||
u32 ebo;
|
||||
|
||||
// TODO: see if we can avoid having this full thing here.
|
||||
DecVtxFormat decFmt;
|
||||
|
||||
// Precalculated parameter for drawdrawElements
|
||||
@@ -83,6 +85,7 @@ public:
|
||||
u8 numDCs;
|
||||
int numDraws;
|
||||
int lastFrame; // So that we can forget.
|
||||
u16 drawsUntilNextFullHash;
|
||||
};
|
||||
|
||||
|
||||
|
||||
+36
-16
@@ -73,6 +73,12 @@ int DecFmtSize(u8 fmt) {
|
||||
case DEC_U8_2: return 4;
|
||||
case DEC_U8_3: return 4;
|
||||
case DEC_U8_4: return 4;
|
||||
case DEC_U16_1: return 4;
|
||||
case DEC_U16_2: return 4;
|
||||
case DEC_U16_3: return 8;
|
||||
case DEC_U16_4: return 8;
|
||||
case DEC_U8A_2: return 4;
|
||||
case DEC_U16A_2: return 4;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -118,10 +124,10 @@ void VertexDecoder::Step_WeightsU8() const
|
||||
|
||||
void VertexDecoder::Step_WeightsU16() const
|
||||
{
|
||||
float *wt = (float *)(decoded_ + decFmt.w0off);
|
||||
u16 *wt = (u16 *)(decoded_ + decFmt.w0off);
|
||||
const u16 *wdata = (const u16*)(ptr_);
|
||||
for (int j = 0; j < nweights; j++)
|
||||
wt[j] = (float)wdata[j] / 65535.0f;
|
||||
wt[j] = wdata[j];
|
||||
}
|
||||
|
||||
// Float weights should be uncommon, we can live with having to multiply these by 2.0
|
||||
@@ -138,41 +144,42 @@ void VertexDecoder::Step_WeightsFloat() const
|
||||
|
||||
void VertexDecoder::Step_TcU8() const
|
||||
{
|
||||
float *uv = (float *)(decoded_ + decFmt.uvoff);
|
||||
u8 *uv = (u8*)(decoded_ + decFmt.uvoff);
|
||||
const u8 *uvdata = (const u8*)(ptr_ + tcoff);
|
||||
for (int j = 0; j < 2; j++)
|
||||
uv[j] = (float)uvdata[j] / 128.0f;
|
||||
uv[0] = uvdata[0];
|
||||
uv[1] = uvdata[1];
|
||||
}
|
||||
|
||||
void VertexDecoder::Step_TcU16() const
|
||||
{
|
||||
float *uv = (float *)(decoded_ + decFmt.uvoff);
|
||||
u16 *uv = (u16 *)(decoded_ + decFmt.uvoff);
|
||||
const u16 *uvdata = (const u16*)(ptr_ + tcoff);
|
||||
uv[0] = (float)uvdata[0] / 32768.0f;
|
||||
uv[1] = (float)uvdata[1] / 32768.0f;
|
||||
uv[0] = uvdata[0];
|
||||
uv[1] = uvdata[1];
|
||||
}
|
||||
|
||||
void VertexDecoder::Step_TcU16Through() const
|
||||
{
|
||||
float *uv = (float *)(decoded_ + decFmt.uvoff);
|
||||
u16 *uv = (u16 *)(decoded_ + decFmt.uvoff);
|
||||
const u16 *uvdata = (const u16*)(ptr_ + tcoff);
|
||||
uv[0] = (float)uvdata[0] / (float)(gstate_c.curTextureWidth);
|
||||
uv[1] = (float)uvdata[1] / (float)(gstate_c.curTextureHeight);
|
||||
uv[0] = uvdata[0];
|
||||
uv[1] = uvdata[1];
|
||||
}
|
||||
|
||||
void VertexDecoder::Step_TcFloat() const
|
||||
{
|
||||
float *uv = (float *)(decoded_ + decFmt.uvoff);
|
||||
const float *uvdata = (const float*)(ptr_ + tcoff);
|
||||
memcpy(uv, uvdata, sizeof(float) * 2);
|
||||
uv[0] = uvdata[0] * 0.5f;
|
||||
uv[1] = uvdata[1] * 0.5f;
|
||||
}
|
||||
|
||||
void VertexDecoder::Step_TcFloatThrough() const
|
||||
{
|
||||
float *uv = (float *)(decoded_ + decFmt.uvoff);
|
||||
const float *uvdata = (const float*)(ptr_ + tcoff);
|
||||
uv[0] = uvdata[0] / (float)(gstate_c.curTextureWidth);
|
||||
uv[1] = uvdata[1] / (float)(gstate_c.curTextureHeight);
|
||||
uv[0] = uvdata[0] * 0.5f;
|
||||
uv[1] = uvdata[1] * 0.5f;
|
||||
}
|
||||
|
||||
void VertexDecoder::Step_Color565() const
|
||||
@@ -557,6 +564,9 @@ void VertexDecoder::SetVertexType(u32 fmt) {
|
||||
if (weighttype == GE_VTYPE_WEIGHT_8BIT >> GE_VTYPE_WEIGHT_SHIFT) {
|
||||
fmtBase = DEC_U8_1;
|
||||
weightSize = 1;
|
||||
} else if (weighttype == GE_VTYPE_WEIGHT_16BIT >> GE_VTYPE_WEIGHT_SHIFT) {
|
||||
fmtBase = DEC_U16_1;
|
||||
weightSize = 2;
|
||||
}
|
||||
|
||||
if (nweights < 5) {
|
||||
@@ -580,8 +590,18 @@ void VertexDecoder::SetVertexType(u32 fmt) {
|
||||
|
||||
steps_[numSteps_++] = throughmode ? tcstep_through[tc] : tcstep[tc];
|
||||
|
||||
// All UV decode to DEC_FLOAT2 currently.
|
||||
decFmt.uvfmt = DEC_FLOAT_2;
|
||||
switch (tc) {
|
||||
case GE_VTYPE_TC_8BIT >> GE_VTYPE_TC_SHIFT:
|
||||
decFmt.uvfmt = throughmode ? DEC_U8A_2 : DEC_U8_2;
|
||||
break;
|
||||
case GE_VTYPE_TC_16BIT >> GE_VTYPE_TC_SHIFT:
|
||||
decFmt.uvfmt = throughmode ? DEC_U16A_2 : DEC_U16_2;
|
||||
break;
|
||||
case GE_VTYPE_TC_FLOAT >> GE_VTYPE_TC_SHIFT:
|
||||
decFmt.uvfmt = DEC_FLOAT_2;
|
||||
break;
|
||||
}
|
||||
|
||||
decFmt.uvoff = decOff;
|
||||
decOff += DecFmtSize(decFmt.uvfmt);
|
||||
}
|
||||
|
||||
+78
-30
@@ -38,6 +38,12 @@ enum {
|
||||
DEC_U8_2,
|
||||
DEC_U8_3,
|
||||
DEC_U8_4,
|
||||
DEC_U16_1,
|
||||
DEC_U16_2,
|
||||
DEC_U16_3,
|
||||
DEC_U16_4,
|
||||
DEC_U8A_2,
|
||||
DEC_U16A_2,
|
||||
};
|
||||
|
||||
int DecFmtSize(u8 fmt);
|
||||
@@ -58,8 +64,8 @@ struct TransformedVertex
|
||||
{
|
||||
float x, y, z, fog; // in case of morph, preblend during decode
|
||||
float u; float v; // scaled by uscale, vscale, if there
|
||||
float color0[4]; // prelit
|
||||
float color1[3]; // prelit
|
||||
u8 color0[4]; // prelit
|
||||
u8 color1[3]; // prelit
|
||||
};
|
||||
|
||||
DecVtxFormat GetTransformedVtxFormat(const DecVtxFormat &fmt);
|
||||
@@ -189,16 +195,16 @@ public:
|
||||
break;
|
||||
case DEC_S16_3:
|
||||
{
|
||||
s16 *p = (s16 *)(data_ + decFmt_.posoff);
|
||||
const s16 *p = (s16 *)(data_ + decFmt_.posoff);
|
||||
for (int i = 0; i < 3; i++)
|
||||
pos[i] = p[i] / 32767.0f;
|
||||
pos[i] = p[i] * (1.f / 32768.f);
|
||||
}
|
||||
break;
|
||||
case DEC_S8_3:
|
||||
{
|
||||
s8 *p = (s8 *)(data_ + decFmt_.posoff);
|
||||
const s8 *p = (s8 *)(data_ + decFmt_.posoff);
|
||||
for (int i = 0; i < 3; i++)
|
||||
pos[i] = p[i] / 127.0f;
|
||||
pos[i] = p[i] * (1.f / 128.f);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -214,16 +220,16 @@ public:
|
||||
break;
|
||||
case DEC_S16_3:
|
||||
{
|
||||
s16 *p = (s16 *)(data_ + decFmt_.nrmoff);
|
||||
const s16 *p = (s16 *)(data_ + decFmt_.nrmoff);
|
||||
for (int i = 0; i < 3; i++)
|
||||
nrm[i] = p[i] / 32767.0f;
|
||||
nrm[i] = p[i] * (1.f / 32768.f);
|
||||
}
|
||||
break;
|
||||
case DEC_S8_3:
|
||||
{
|
||||
s8 *p = (s8 *)(data_ + decFmt_.nrmoff);
|
||||
const s8 *p = (s8 *)(data_ + decFmt_.nrmoff);
|
||||
for (int i = 0; i < 3; i++)
|
||||
nrm[i] = p[i] / 127.0f;
|
||||
nrm[i] = p[i] * (1.f / 128.0f);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -233,9 +239,37 @@ public:
|
||||
}
|
||||
|
||||
void ReadUV(float uv[2]) {
|
||||
const u8 *b = (const u8 *)(data_ + decFmt_.uvoff);
|
||||
const u16 *s = (const u16 *)(data_ + decFmt_.uvoff);
|
||||
const float *f = (const float *)(data_ + decFmt_.uvoff);
|
||||
switch (decFmt_.uvfmt) {
|
||||
case DEC_U8_2:
|
||||
uv[0] = b[0] * (1.f / 128.f);
|
||||
uv[1] = b[1] * (1.f / 128.f);
|
||||
break;
|
||||
|
||||
case DEC_U16_2:
|
||||
uv[0] = s[0] * (1.f / 32768.f);
|
||||
uv[1] = s[1] * (1.f / 32768.f);
|
||||
break;
|
||||
|
||||
case DEC_FLOAT_2:
|
||||
memcpy(uv, data_ + decFmt_.uvoff, 8); break;
|
||||
if (isThrough()) {
|
||||
uv[0] = f[0];
|
||||
uv[1] = f[1];
|
||||
} else {
|
||||
uv[0] = f[0] * 2.0f;
|
||||
uv[1] = f[1] * 2.0f;
|
||||
}
|
||||
break;
|
||||
|
||||
case DEC_U16A_2:
|
||||
{
|
||||
const u16 *p = (const u16 *)(data_ + decFmt_.uvoff);
|
||||
uv[0] = (float)p[0];
|
||||
uv[1] = (float)p[1];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(G3D, "Reader: Unsupported UV Format");
|
||||
break;
|
||||
@@ -248,7 +282,7 @@ public:
|
||||
{
|
||||
const u8 *p = (const u8 *)(data_ + decFmt_.c0off);
|
||||
for (int i = 0; i < 4; i++)
|
||||
color[i] = p[i] / 255.0f;
|
||||
color[i] = p[i] * (1.f / 255.f);
|
||||
}
|
||||
break;
|
||||
case DEC_FLOAT_4:
|
||||
@@ -265,7 +299,7 @@ public:
|
||||
{
|
||||
const u8 *p = (const u8 *)(data_ + decFmt_.c1off);
|
||||
for (int i = 0; i < 3; i++)
|
||||
color[i] = p[i] / 255.0f;
|
||||
color[i] = p[i] * (1.f / 255.f);
|
||||
}
|
||||
break;
|
||||
case DEC_FLOAT_4:
|
||||
@@ -277,34 +311,48 @@ public:
|
||||
}
|
||||
|
||||
void ReadWeights(float weights[8]) {
|
||||
const float *f = (const float *)(data_ + decFmt_.w0off);
|
||||
const u8 *p = (const u8 *)(data_ + decFmt_.w0off);
|
||||
const u16 *s = (const u16 *)(data_ + decFmt_.w0off);
|
||||
switch (decFmt_.w0fmt) {
|
||||
case DEC_FLOAT_1: memcpy(weights, data_ + decFmt_.w0off, 4); break;
|
||||
case DEC_FLOAT_2: memcpy(weights, data_ + decFmt_.w0off, 8); break;
|
||||
case DEC_FLOAT_3: memcpy(weights, data_ + decFmt_.w0off, 12); break;
|
||||
case DEC_FLOAT_4: memcpy(weights, data_ + decFmt_.w0off, 16); break;
|
||||
case DEC_U8_1: weights[0] = p[0] / 128.f; break;
|
||||
case DEC_U8_2: for (int i = 0; i < 2; i++) weights[i] = p[i] / 128.f; break;
|
||||
case DEC_U8_3: for (int i = 0; i < 3; i++) weights[i] = p[i] / 128.f; break;
|
||||
case DEC_U8_4: for (int i = 0; i < 4; i++) weights[i] = p[i] / 128.f; break;
|
||||
case DEC_FLOAT_1:
|
||||
case DEC_FLOAT_2:
|
||||
case DEC_FLOAT_3:
|
||||
case DEC_FLOAT_4:
|
||||
for (int i = 0; i <= decFmt_.w0fmt - DEC_FLOAT_1; i++)
|
||||
weights[i] = f[i] * 2.0;
|
||||
break;
|
||||
case DEC_U8_1: weights[0] = p[0] * (1.f / 128.f); break;
|
||||
case DEC_U8_2: for (int i = 0; i < 2; i++) weights[i] = p[i] * (1.f / 128.f); break;
|
||||
case DEC_U8_3: for (int i = 0; i < 3; i++) weights[i] = p[i] * (1.f / 128.f); break;
|
||||
case DEC_U8_4: for (int i = 0; i < 4; i++) weights[i] = p[i] * (1.f / 128.f); break;
|
||||
case DEC_U16_1: weights[0] = s[0] * (1.f / 32768.f); break;
|
||||
case DEC_U16_2: for (int i = 0; i < 2; i++) weights[i] = s[i] * (1.f / 32768.f); break;
|
||||
case DEC_U16_3: for (int i = 0; i < 3; i++) weights[i] = s[i] * (1.f / 32768.f); break;
|
||||
case DEC_U16_4: for (int i = 0; i < 4; i++) weights[i] = s[i] * (1.f / 32768.f); break;
|
||||
default:
|
||||
ERROR_LOG(G3D, "Reader: Unsupported W0 Format");
|
||||
break;
|
||||
}
|
||||
|
||||
f = (const float*)(data_ + decFmt_.w1off);
|
||||
p = (const u8 *)(data_ + decFmt_.w1off);
|
||||
s = (const u16 *)(data_ + decFmt_.w1off);
|
||||
switch (decFmt_.w1fmt) {
|
||||
case 0:
|
||||
// It's fine for there to be w0 weights but not w1.
|
||||
break;
|
||||
case DEC_FLOAT_1: memcpy(weights + 4, data_ + decFmt_.w1off, 4); break;
|
||||
case DEC_FLOAT_2: memcpy(weights + 4, data_ + decFmt_.w1off, 8); break;
|
||||
case DEC_FLOAT_3: memcpy(weights + 4, data_ + decFmt_.w1off, 12); break;
|
||||
case DEC_FLOAT_4: memcpy(weights + 4, data_ + decFmt_.w1off, 16); break;
|
||||
case DEC_U8_1: weights[4] = p[0] / 128.f; break;
|
||||
case DEC_U8_2: for (int i = 0; i < 2; i++) weights[i+4] = p[i] / 128.f; break;
|
||||
case DEC_U8_3: for (int i = 0; i < 3; i++) weights[i+4] = p[i] / 128.f; break;
|
||||
case DEC_U8_4: for (int i = 0; i < 4; i++) weights[i+4] = p[i] / 128.f; break;
|
||||
case DEC_FLOAT_1:
|
||||
case DEC_FLOAT_2:
|
||||
case DEC_FLOAT_3:
|
||||
case DEC_FLOAT_4:
|
||||
for (int i = 0; i <= decFmt_.w1fmt - DEC_FLOAT_1; i++)
|
||||
weights[i+4] = f[i] * 2.0;
|
||||
break;
|
||||
case DEC_U16_1: weights[4] = s[0] * (1.f / 32768.f); break;
|
||||
case DEC_U16_2: for (int i = 0; i < 2; i++) weights[i+4] = s[i] * (1.f / 32768.f); break;
|
||||
case DEC_U16_3: for (int i = 0; i < 3; i++) weights[i+4] = s[i] * (1.f / 32768.f); break;
|
||||
case DEC_U16_4: for (int i = 0; i < 4; i++) weights[i+4] = s[i] * (1.f / 32768.f); break;
|
||||
default:
|
||||
ERROR_LOG(G3D, "Reader: Unsupported W1 Format");
|
||||
break;
|
||||
@@ -314,7 +362,7 @@ public:
|
||||
bool hasColor0() const { return decFmt_.c0fmt != 0; }
|
||||
bool hasNormal() const { return decFmt_.nrmfmt != 0; }
|
||||
bool hasUV() const { return decFmt_.uvfmt != 0; }
|
||||
|
||||
bool isThrough() const { return (vtype_ & GE_VTYPE_THROUGH) != 0; }
|
||||
void Goto(int index) {
|
||||
data_ = base_ + index * decFmt_.stride;
|
||||
}
|
||||
|
||||
@@ -297,7 +297,7 @@ void GenerateVertexShader(int prim, char *buffer) {
|
||||
const char *specular = (gstate.materialupdate & 4) ? "unlitColor" : "u_matspecular.rgb";
|
||||
|
||||
if (gstate.lightingEnable & 1) {
|
||||
WRITE(p, " vec4 lightSum0 = vec4(0.0);\n");
|
||||
WRITE(p, " vec4 lightSum0 = u_ambient * %s + vec4(u_matemissive, 0.0);\n", ambient);
|
||||
WRITE(p, " vec3 lightSum1 = vec3(0.0);\n");
|
||||
}
|
||||
|
||||
@@ -345,7 +345,7 @@ void GenerateVertexShader(int prim, char *buffer) {
|
||||
|
||||
if (gstate.lightingEnable & 1) {
|
||||
// Sum up ambient, emissive here.
|
||||
WRITE(p, " v_color0 = clamp(lightSum0 + u_ambient * %s + vec4(u_matemissive, 0.0), 0.0, 1.0);\n", ambient);
|
||||
WRITE(p, " v_color0 = clamp(lightSum0, 0.0, 1.0);\n");
|
||||
if (lmode) {
|
||||
WRITE(p, " v_color1 = clamp(lightSum1, 0.0, 1.0);\n");
|
||||
} else {
|
||||
@@ -375,7 +375,7 @@ void GenerateVertexShader(int prim, char *buffer) {
|
||||
WRITE(p, " vec3 temp_tc = a_position.xyz;\n");
|
||||
break;
|
||||
case 1: // Use unscaled UV as source
|
||||
WRITE(p, " vec3 temp_tc = vec3(a_texcoord.xy, 0.0);\n");
|
||||
WRITE(p, " vec3 temp_tc = vec3(a_texcoord.xy * 2.0f, 0.0);\n");
|
||||
break;
|
||||
case 2: // Use normalized transformed normal as source
|
||||
WRITE(p, " vec3 temp_tc = normalize(a_normal);\n");
|
||||
|
||||
+3
-3
@@ -145,7 +145,7 @@ struct GPUgstate
|
||||
clutformat,
|
||||
texfilter,
|
||||
texwrap,
|
||||
padxxxxx,
|
||||
texlevel,
|
||||
texfunc,
|
||||
texenvcolor,
|
||||
texflush,
|
||||
@@ -236,8 +236,8 @@ struct GPUStateCache
|
||||
|
||||
bool textureChanged;
|
||||
|
||||
float uScale,vScale,zScale;
|
||||
float uOff,vOff,zOff;
|
||||
float uScale,vScale;
|
||||
float uOff,vOff;
|
||||
float zMin, zMax;
|
||||
float lightpos[4][3];
|
||||
float lightdir[4][3];
|
||||
|
||||
+2
-2
@@ -521,13 +521,13 @@ void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer) {
|
||||
case GE_CMD_VIEWPORTZ1:
|
||||
{
|
||||
float zScale = getFloat24(data) / 65535.f;
|
||||
sprintf(buffer, "Z scale: %f", zScale);
|
||||
sprintf(buffer, "Viewport Z scale: %f", zScale);
|
||||
}
|
||||
break;
|
||||
case GE_CMD_VIEWPORTZ2:
|
||||
{
|
||||
float zOff = getFloat24(data) / 65535.f;
|
||||
sprintf(buffer, "Z pos: %f", zOff);
|
||||
sprintf(buffer, "Viewport Z pos: %f", zOff);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
+2
-1
@@ -48,7 +48,8 @@ SOURCES += ../Common/ColorUtil.cpp \
|
||||
../Common/Timer.cpp \
|
||||
../Common/Version.cpp \
|
||||
../Common/Crypto/*.cpp
|
||||
HEADERS += ../Common/ColorUtil.h \
|
||||
HEADERS += ../Common/ChunkFile.h \
|
||||
../Common/ColorUtil.h \
|
||||
../Common/ConsoleListener.h \
|
||||
../Common/ExtendedTrace.h \
|
||||
../Common/FileSearch.h \
|
||||
|
||||
+270
-97
@@ -17,22 +17,72 @@
|
||||
#include "gfx_es2/fbo.h"
|
||||
#include "gfx_es2/gl_state.h"
|
||||
#include "GPU/GPUState.h"
|
||||
#include "android/jni/ui_atlas.h"
|
||||
#include "native/util/random/rng.h"
|
||||
#include "native/base/timeutil.h"
|
||||
#include "native/base/colorutil.h"
|
||||
|
||||
#include "qtemugl.h"
|
||||
#include "QtHost.h"
|
||||
|
||||
void EmuThread_Start(QString filename, QtEmuGL* w)
|
||||
namespace
|
||||
{
|
||||
|
||||
static const int symbols[4] = {
|
||||
I_CROSS,
|
||||
I_CIRCLE,
|
||||
I_SQUARE,
|
||||
I_TRIANGLE
|
||||
};
|
||||
|
||||
static const uint32_t colors[4] = {
|
||||
/*
|
||||
0xFF6666FF, // blue
|
||||
0xFFFF6666, // red
|
||||
0xFFFF66FF, // pink
|
||||
0xFF66FF66, // green
|
||||
*/
|
||||
0xC0FFFFFF,
|
||||
0xC0FFFFFF,
|
||||
0xC0FFFFFF,
|
||||
0xC0FFFFFF,
|
||||
};
|
||||
|
||||
static void DrawBackground(float alpha) {
|
||||
static float xbase[100] = {0};
|
||||
static float ybase[100] = {0};
|
||||
if (xbase[0] == 0.0f) {
|
||||
GMRng rng;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
xbase[i] = rng.F() * dp_xres;
|
||||
ybase[i] = rng.F() * dp_yres;
|
||||
}
|
||||
}
|
||||
glClearColor(0.1f,0.2f,0.43f,1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
ui_draw2d.DrawImageStretch(I_BG, 0, 0, dp_xres, dp_yres);
|
||||
float t = time_now();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
float x = xbase[i];
|
||||
float y = ybase[i] + 40*cos(i * 7.2 + t * 1.3);
|
||||
float angle = sin(i + t);
|
||||
int n = i & 3;
|
||||
ui_draw2d.DrawImageRotated(symbols[n], x, y, 1.0f, angle, colorAlpha(colors[n], alpha * 0.1f));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void EmuThread_Start(QtEmuGL* w)
|
||||
{
|
||||
//_dbg_clear_();
|
||||
fileToStart = filename;
|
||||
glWindow = w;
|
||||
glWindow->doneCurrent();
|
||||
glWindow->start_rendering();
|
||||
}
|
||||
|
||||
void EmuThread_Stop()
|
||||
{
|
||||
// DSound_UpdateSound();
|
||||
Core_Stop();
|
||||
if(glWindow)
|
||||
{
|
||||
glWindow->stop_rendering();
|
||||
@@ -40,6 +90,31 @@ void EmuThread_Stop()
|
||||
host->UpdateUI();
|
||||
}
|
||||
|
||||
void EmuThread_StartGame(QString filename)
|
||||
{
|
||||
if(glWindow)
|
||||
{
|
||||
glWindow->start_game(filename);
|
||||
}
|
||||
}
|
||||
|
||||
void EmuThread_StopGame()
|
||||
{
|
||||
if(glWindow)
|
||||
{
|
||||
glWindow->stop_game();
|
||||
}
|
||||
}
|
||||
|
||||
void EmuThread_LockDraw(bool value)
|
||||
{
|
||||
if(glWindow)
|
||||
{
|
||||
glWindow->LockDraw(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EmuThread::init(InputState *inputState)
|
||||
{
|
||||
input_state = inputState;
|
||||
@@ -50,8 +125,6 @@ void EmuThread::run()
|
||||
running = true;
|
||||
setCurrentThreadName("EmuThread");
|
||||
|
||||
g_State.bEmuThreadStarted = true;
|
||||
|
||||
host->UpdateUI();
|
||||
host->InitGL();
|
||||
|
||||
@@ -64,80 +137,181 @@ void EmuThread::run()
|
||||
|
||||
INFO_LOG(BOOT, "Starting up hardware.");
|
||||
|
||||
CoreParameter coreParameter;
|
||||
coreParameter.fileToStart = fileToStart.toStdString();
|
||||
coreParameter.enableSound = true;
|
||||
coreParameter.gpuCore = GPU_GLES;
|
||||
coreParameter.cpuCore = (CPUCore)g_Config.iCpuCore;
|
||||
coreParameter.enableDebugging = true;
|
||||
coreParameter.printfEmuLog = false;
|
||||
coreParameter.headLess = false;
|
||||
coreParameter.renderWidth = 480 * g_Config.iWindowZoom;
|
||||
coreParameter.renderHeight = 272 * g_Config.iWindowZoom;
|
||||
coreParameter.outputWidth = dp_xres;
|
||||
coreParameter.outputHeight = dp_yres;
|
||||
coreParameter.pixelWidth = pixel_xres;
|
||||
coreParameter.pixelHeight = pixel_yres;
|
||||
coreParameter.startPaused = !g_Config.bAutoRun;
|
||||
|
||||
std::string error_string;
|
||||
if (!PSP_Init(coreParameter, &error_string))
|
||||
{
|
||||
ERROR_LOG(BOOT, "Error loading: %s", error_string.c_str());
|
||||
FinalShutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
LayoutGamepad(dp_xres, dp_yres);
|
||||
|
||||
_dbg_update_();
|
||||
|
||||
host->UpdateDisassembly();
|
||||
Core_EnableStepping(coreParameter.startPaused ? TRUE : FALSE);
|
||||
|
||||
g_State.bBooted = true;
|
||||
#ifdef _DEBUG
|
||||
host->UpdateMemView();
|
||||
#endif
|
||||
host->BootDone();
|
||||
|
||||
QElapsedTimer timer;
|
||||
|
||||
while(running) {
|
||||
//UpdateGamepad(*input_state);
|
||||
timer.start();
|
||||
|
||||
UpdateInputState(input_state);
|
||||
gameMutex.lock();
|
||||
bool gRun = gameRunning;
|
||||
gameMutex.unlock();
|
||||
|
||||
for (int i = 0; i < controllistCount; i++) {
|
||||
if (input_state->pad_buttons_down & controllist[i].emu_id) {
|
||||
__CtrlButtonDown(controllist[i].psp_id);
|
||||
if(gRun)
|
||||
{
|
||||
gameMutex.lock();
|
||||
|
||||
glWindow->makeCurrent();
|
||||
if(needInitGame)
|
||||
{
|
||||
g_State.bEmuThreadStarted = true;
|
||||
|
||||
CoreParameter coreParameter;
|
||||
coreParameter.fileToStart = fileToStart.toStdString();
|
||||
coreParameter.enableSound = true;
|
||||
coreParameter.gpuCore = GPU_GLES;
|
||||
coreParameter.cpuCore = (CPUCore)g_Config.iCpuCore;
|
||||
coreParameter.enableDebugging = true;
|
||||
coreParameter.printfEmuLog = false;
|
||||
coreParameter.headLess = false;
|
||||
coreParameter.renderWidth = 480 * g_Config.iWindowZoom;
|
||||
coreParameter.renderHeight = 272 * g_Config.iWindowZoom;
|
||||
coreParameter.outputWidth = dp_xres;
|
||||
coreParameter.outputHeight = dp_yres;
|
||||
coreParameter.pixelWidth = pixel_xres;
|
||||
coreParameter.pixelHeight = pixel_yres;
|
||||
coreParameter.startPaused = !g_Config.bAutoRun;
|
||||
|
||||
std::string error_string;
|
||||
if (!PSP_Init(coreParameter, &error_string))
|
||||
{
|
||||
ERROR_LOG(BOOT, "Error loading: %s", error_string.c_str());
|
||||
FinalShutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
LayoutGamepad(dp_xres, dp_yres);
|
||||
|
||||
_dbg_update_();
|
||||
|
||||
host->UpdateDisassembly();
|
||||
Core_EnableStepping(coreParameter.startPaused ? TRUE : FALSE);
|
||||
|
||||
g_State.bBooted = true;
|
||||
#ifdef _DEBUG
|
||||
host->UpdateMemView();
|
||||
#endif
|
||||
host->BootDone();
|
||||
needInitGame = false;
|
||||
}
|
||||
if (input_state->pad_buttons_up & controllist[i].emu_id) {
|
||||
__CtrlButtonUp(controllist[i].psp_id);
|
||||
UpdateInputState(input_state);
|
||||
|
||||
for (int i = 0; i < controllistCount; i++) {
|
||||
if (input_state->pad_buttons_down & controllist[i].emu_id) {
|
||||
__CtrlButtonDown(controllist[i].psp_id);
|
||||
}
|
||||
if (input_state->pad_buttons_up & controllist[i].emu_id) {
|
||||
__CtrlButtonUp(controllist[i].psp_id);
|
||||
}
|
||||
}
|
||||
__CtrlSetAnalog(input_state->pad_lstick_x, input_state->pad_lstick_y);
|
||||
|
||||
EndInputState(input_state);
|
||||
|
||||
glstate.Restore();
|
||||
glViewport(0, 0, pixel_xres, pixel_yres);
|
||||
Matrix4x4 ortho;
|
||||
ortho.setOrtho(0.0f, dp_xres, dp_yres, 0.0f, -1.0f, 1.0f);
|
||||
glsl_bind(UIShader_Get());
|
||||
glUniformMatrix4fv(UIShader_Get()->u_worldviewproj, 1, GL_FALSE, ortho.getReadPtr());
|
||||
|
||||
|
||||
ReapplyGfxState();
|
||||
|
||||
Core_Run();
|
||||
|
||||
// Hopefully coreState is now CORE_NEXTFRAME
|
||||
if (coreState == CORE_NEXTFRAME) {
|
||||
// set back to running for the next frame
|
||||
coreState = CORE_RUNNING;
|
||||
|
||||
qint64 time = timer.elapsed();
|
||||
const int frameTime = (1.0f/60.0f) * 1000;
|
||||
gameMutex.unlock();
|
||||
if(time < frameTime)
|
||||
{
|
||||
glWindow->doneCurrent();
|
||||
msleep(frameTime-time);
|
||||
glWindow->makeCurrent();
|
||||
}
|
||||
gameMutex.lock();
|
||||
timer.start();
|
||||
}
|
||||
|
||||
fbo_unbind();
|
||||
|
||||
UIShader_Prepare();
|
||||
|
||||
uiTexture->Bind(0);
|
||||
|
||||
glViewport(0, 0, pixel_xres, pixel_yres);
|
||||
|
||||
ui_draw2d.Begin(DBMODE_NORMAL);
|
||||
|
||||
//if (g_Config.bShowTouchControls)
|
||||
// DrawGamepad(ui_draw2d);
|
||||
|
||||
glsl_bind(UIShader_Get());
|
||||
ui_draw2d.End();
|
||||
ui_draw2d.Flush(UIShader_Get());
|
||||
|
||||
|
||||
// Tiled renderers like PowerVR should benefit greatly from this. However - seems I can't call it?
|
||||
#if defined(USING_GLES2)
|
||||
bool hasDiscard = false; // TODO
|
||||
if (hasDiscard) {
|
||||
//glDiscardFramebuffer(GL_COLOR_EXT | GL_DEPTH_EXT | GL_STENCIL_EXT);
|
||||
}
|
||||
#endif
|
||||
glWindow->swapBuffers();
|
||||
glWindow->doneCurrent();
|
||||
gameMutex.unlock();
|
||||
}
|
||||
__CtrlSetAnalog(input_state->pad_lstick_x, input_state->pad_lstick_y);
|
||||
else
|
||||
{
|
||||
gameMutex.lock();
|
||||
glWindow->makeCurrent();
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
EndInputState(input_state);
|
||||
time_update();
|
||||
float t = (float)frames_ / 60.0f;
|
||||
frames_++;
|
||||
|
||||
glstate.Restore();
|
||||
glViewport(0, 0, pixel_xres, pixel_yres);
|
||||
Matrix4x4 ortho;
|
||||
ortho.setOrtho(0.0f, dp_xres, dp_yres, 0.0f, -1.0f, 1.0f);
|
||||
glsl_bind(UIShader_Get());
|
||||
glUniformMatrix4fv(UIShader_Get()->u_worldviewproj, 1, GL_FALSE, ortho.getReadPtr());
|
||||
float alpha = t;
|
||||
if (t > 1.0f) alpha = 1.0f;
|
||||
float alphaText = alpha;
|
||||
//if (t > 2.0f) alphaText = 3.0f - t;
|
||||
|
||||
glstate.Restore();
|
||||
glViewport(0, 0, pixel_xres, pixel_yres);
|
||||
Matrix4x4 ortho;
|
||||
ortho.setOrtho(0.0f, dp_xres, dp_yres, 0.0f, -1.0f, 1.0f);
|
||||
glsl_bind(UIShader_Get());
|
||||
glUniformMatrix4fv(UIShader_Get()->u_worldviewproj, 1, GL_FALSE, ortho.getReadPtr());
|
||||
|
||||
|
||||
ReapplyGfxState();
|
||||
ReapplyGfxState();
|
||||
|
||||
Core_Run();
|
||||
UIShader_Prepare();
|
||||
UIBegin();
|
||||
DrawBackground(alpha);
|
||||
|
||||
// Hopefully coreState is now CORE_NEXTFRAME
|
||||
if (coreState == CORE_NEXTFRAME) {
|
||||
// set back to running for the next frame
|
||||
coreState = CORE_RUNNING;
|
||||
ui_draw2d.SetFontScale(1.5f, 1.5f);
|
||||
ui_draw2d.DrawText(UBUNTU48, "PPSSPP", dp_xres / 2, dp_yres / 2 - 30, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER);
|
||||
ui_draw2d.SetFontScale(1.0f, 1.0f);
|
||||
ui_draw2d.DrawText(UBUNTU24, "Created by Henrik Rydgard", dp_xres / 2, dp_yres / 2 + 40, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER);
|
||||
ui_draw2d.DrawText(UBUNTU24, "Free Software under GPL 2.0", dp_xres / 2, dp_yres / 2 + 70, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER);
|
||||
ui_draw2d.DrawText(UBUNTU24, "www.ppsspp.org", dp_xres / 2, dp_yres / 2 + 130, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER);
|
||||
|
||||
UIEnd();
|
||||
|
||||
glsl_bind(UIShader_Get());
|
||||
ui_draw2d.Flush(UIShader_Get());
|
||||
|
||||
glWindow->swapBuffers();
|
||||
glWindow->doneCurrent();
|
||||
gameMutex.unlock();
|
||||
qint64 time = timer.elapsed();
|
||||
const int frameTime = (1.0f/60.0f) * 1000;
|
||||
if(time < frameTime)
|
||||
@@ -147,41 +321,18 @@ void EmuThread::run()
|
||||
timer.start();
|
||||
}
|
||||
|
||||
fbo_unbind();
|
||||
|
||||
UIShader_Prepare();
|
||||
|
||||
uiTexture->Bind(0);
|
||||
|
||||
glViewport(0, 0, pixel_xres, pixel_yres);
|
||||
|
||||
ui_draw2d.Begin(DBMODE_NORMAL);
|
||||
|
||||
//if (g_Config.bShowTouchControls)
|
||||
// DrawGamepad(ui_draw2d);
|
||||
|
||||
glsl_bind(UIShader_Get());
|
||||
ui_draw2d.End();
|
||||
ui_draw2d.Flush(UIShader_Get());
|
||||
|
||||
|
||||
// Tiled renderers like PowerVR should benefit greatly from this. However - seems I can't call it?
|
||||
#if defined(USING_GLES2)
|
||||
bool hasDiscard = false; // TODO
|
||||
if (hasDiscard) {
|
||||
//glDiscardFramebuffer(GL_COLOR_EXT | GL_DEPTH_EXT | GL_STENCIL_EXT);
|
||||
}
|
||||
#endif
|
||||
|
||||
glWindow->swapBuffers();
|
||||
}
|
||||
glWindow->doneCurrent();
|
||||
|
||||
if(gameRunning)
|
||||
{
|
||||
stopGame();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void EmuThread::Shutdown()
|
||||
{
|
||||
host->PrepareShutdown();
|
||||
PSP_Shutdown();
|
||||
FinalShutdown();
|
||||
}
|
||||
void EmuThread::FinalShutdown()
|
||||
@@ -189,7 +340,6 @@ void EmuThread::FinalShutdown()
|
||||
|
||||
host->ShutdownGL();
|
||||
|
||||
|
||||
delete uiTexture;
|
||||
uiTexture = NULL;
|
||||
|
||||
@@ -197,10 +347,6 @@ void EmuThread::FinalShutdown()
|
||||
|
||||
gl_lost_manager_shutdown();
|
||||
|
||||
// TODO
|
||||
//The CPU should return when a game is stopped and cleanup should be done here,
|
||||
//so we can restart the plugins (or load new ones) for the next game
|
||||
g_State.bEmuThreadStarted = false;
|
||||
//_endthreadex(0);
|
||||
//return 0;
|
||||
}
|
||||
@@ -210,4 +356,31 @@ void EmuThread::setRunning(bool value)
|
||||
running = false;
|
||||
}
|
||||
|
||||
void EmuThread::startGame(QString filename)
|
||||
{
|
||||
gameMutex.lock();
|
||||
needInitGame = true;
|
||||
gameRunning = true;
|
||||
fileToStart = filename;
|
||||
gameMutex.unlock();
|
||||
|
||||
}
|
||||
|
||||
void EmuThread::stopGame()
|
||||
{
|
||||
Core_Stop();
|
||||
gameMutex.lock();
|
||||
gameRunning = false;
|
||||
|
||||
PSP_Shutdown();
|
||||
|
||||
// TODO
|
||||
//The CPU should return when a game is stopped and cleanup should be done here,
|
||||
//so we can restart the plugins (or load new ones) for the next game
|
||||
g_State.bEmuThreadStarted = false;
|
||||
frames_ = 0;
|
||||
|
||||
gameMutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
+13
-2
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
#include "input/input_state.h"
|
||||
|
||||
class QtEmuGL;
|
||||
@@ -7,17 +8,27 @@ class QtEmuGL;
|
||||
class EmuThread : public QThread
|
||||
{
|
||||
public:
|
||||
EmuThread() : running(false) {}
|
||||
EmuThread() : running(false), gameRunning(false), needInitGame(false), frames_(0) {}
|
||||
void init(InputState* inputState);
|
||||
void run();
|
||||
void FinalShutdown();
|
||||
void setRunning(bool value);
|
||||
void startGame(QString filename);
|
||||
void stopGame();
|
||||
QMutex gameMutex;
|
||||
public slots:
|
||||
void Shutdown();
|
||||
private:
|
||||
InputState* input_state;
|
||||
bool running;
|
||||
bool gameRunning;
|
||||
bool needInitGame;
|
||||
int frames_;
|
||||
|
||||
};
|
||||
|
||||
void EmuThread_Start(QString filename, QtEmuGL* w);
|
||||
void EmuThread_Start(QtEmuGL* w);
|
||||
void EmuThread_Stop();
|
||||
void EmuThread_StartGame(QString filename);
|
||||
void EmuThread_StopGame();
|
||||
void EmuThread_LockDraw(bool value);
|
||||
+22
-51
@@ -1,32 +1,29 @@
|
||||
TARGET = PPSSPPQt
|
||||
# Ubuntu user, remove multimedia
|
||||
QT += core gui opengl multimedia
|
||||
|
||||
QT += core gui opengl
|
||||
CONFIG += mobility
|
||||
MOBILITY += multimedia
|
||||
|
||||
include(Settings.pri)
|
||||
linux {
|
||||
CONFIG += mobility link_pkgconfig
|
||||
MOBILITY += multimedia
|
||||
}
|
||||
else {
|
||||
QT += multimedia
|
||||
}
|
||||
|
||||
# Libs
|
||||
symbian: LIBS += -lCore.lib -lCommon.lib -lNative.lib -lcone -leikcore -lavkon -lezlib
|
||||
|
||||
blackberry: LIBS += -L. -lCore -lCommon -lNative -lscreen -lsocket -lstdc++
|
||||
|
||||
win32: LIBS += -L. -lCore -lCommon -lNative -lwinmm -lws2_32 -lkernel32 -luser32 -lgdi32 -lshell32 -lcomctl32 -ldsound -lxinput
|
||||
linux: LIBS += -L. -lCore -lCommon -lNative
|
||||
|
||||
linux {
|
||||
LIBS += -L. -lCore -lCommon -lNative
|
||||
desktop_ui {
|
||||
PRE_TARGETDEPS += ./libCommon.a ./libCore.a ./libNative.a
|
||||
CONFIG += link_pkgconfig
|
||||
packagesExist(sdl) {
|
||||
DEFINES += QT_HAS_SDL
|
||||
PKGCONFIG += sdl
|
||||
DEFINES += QT_HAS_SDL
|
||||
PKGCONFIG += sdl
|
||||
}
|
||||
}
|
||||
|
||||
TRANSLATIONS = languages/ppsspp_en.ts \
|
||||
languages/ppsspp_pl.ts
|
||||
|
||||
# Main
|
||||
SOURCES += ../native/base/QtMain.cpp
|
||||
HEADERS += ../native/base/QtMain.h
|
||||
@@ -41,51 +38,25 @@ SOURCES += ../android/jni/EmuScreen.cpp \
|
||||
INCLUDEPATH += .. ../Common ../native
|
||||
|
||||
# Temporarily only use new UI for Linux desktop
|
||||
linux:!mobile_platform {
|
||||
SOURCES += mainwindow.cpp \
|
||||
debugger_disasm.cpp \
|
||||
EmuThread.cpp\
|
||||
QtHost.cpp \
|
||||
qtemugl.cpp \
|
||||
ctrldisasmview.cpp \
|
||||
ctrlregisterlist.cpp \
|
||||
controls.cpp \
|
||||
qkeyedit.cpp \
|
||||
gamepaddialog.cpp
|
||||
HEADERS += mainwindow.h \
|
||||
debugger_disasm.h \
|
||||
EmuThread.h \
|
||||
QtHost.h \
|
||||
qtemugl.h \
|
||||
ctrldisasmview.h \
|
||||
ctrlregisterlist.h \
|
||||
controls.h \
|
||||
qkeyedit.h \
|
||||
gamepaddialog.h
|
||||
desktop_ui {
|
||||
MOC_DIR = moc
|
||||
UI_DIR = ui
|
||||
SOURCES += *.cpp
|
||||
HEADERS += *.h
|
||||
FORMS += *.ui
|
||||
RESOURCES += resources.qrc
|
||||
} else {
|
||||
SOURCES += ../android/jni/NativeApp.cpp
|
||||
}
|
||||
|
||||
# Packaging
|
||||
symbian {
|
||||
vendorinfo = "%{\"Qtness\"}" ":\"Qtness\""
|
||||
packageheader = "$${LITERAL_HASH}{\"PPSSPP\"}, (0xE0095B1D), 0, 6, 1, TYPE=SA"
|
||||
deployinfo.pkg_prerules = packageheader vendorinfo
|
||||
deploy.pkg_prerules = "$${LITERAL_HASH}{\"PPSSPP\"}, (0xE0095B1D), 0, 6, 1, TYPE=SA" "%{\"Qtness\"}" ":\"Qtness\""
|
||||
assets.sources = ../android/assets/ui_atlas.zim ../assets/ppge_atlas.zim
|
||||
assets.path = E:/PPSSPP
|
||||
DEPLOYMENT += deployinfo assets
|
||||
DEPLOYMENT += deploy assets
|
||||
ICON = ../assets/icon.svg
|
||||
# 268MB maximum
|
||||
# 268MB maximum
|
||||
TARGET.EPOCHEAPSIZE = 0x40000 0x10000000
|
||||
TARGET.EPOCSTACKSIZE = 0x10000
|
||||
}
|
||||
|
||||
linux:!mobile_platform {
|
||||
FORMS += mainwindow.ui \
|
||||
debugger_disasm.ui \
|
||||
controls.ui\
|
||||
gamepaddialog.ui
|
||||
|
||||
RESOURCES += \
|
||||
resources.qrc
|
||||
}
|
||||
+1
-2
@@ -38,8 +38,7 @@ void QtHost::ShutdownGL()
|
||||
|
||||
void QtHost::SetWindowTitle(const char *message)
|
||||
{
|
||||
// Really need a better way to deal with versions.
|
||||
QString title = "PPSSPP v0.5 - " + QString::fromUtf8(message);
|
||||
QString title = "PPSSPP " + QString(PPSSPP_VERSION_STR) + " - " + QString::fromUtf8(message);
|
||||
|
||||
mainWindow->setWindowTitle(title);
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,9 +1,11 @@
|
||||
DEFINES += USING_QT_UI
|
||||
blackberry|symbian|contains(MEEGO_EDITION,harmattan): CONFIG += mobile_platform
|
||||
unix:!blackberry:!symbian:!macx: CONFIG += linux
|
||||
linux:!mobile_platform: CONFIG += desktop_ui
|
||||
|
||||
# Global specific
|
||||
QMAKE_CXXFLAGS += -std=c++0x -Wno-unused-function -Wno-unused-variable -Wno-multichar -Wno-uninitialized -Wno-ignored-qualifiers -Wno-missing-field-initializers -Wno-unused-parameter
|
||||
QMAKE_CXXFLAGS += -Wno-unused-function -Wno-unused-variable -Wno-multichar -Wno-uninitialized -Wno-ignored-qualifiers -Wno-missing-field-initializers -Wno-unused-parameter
|
||||
QMAKE_CXXFLAGS += -std=c++0x -ffast-math -fno-strict-aliasing
|
||||
|
||||
# Arch specific
|
||||
contains(QT_ARCH, i686)|contains(QT_ARCH, x86)|contains(QT_ARCH, x86_64): {
|
||||
@@ -34,4 +36,3 @@ symbian: {
|
||||
DEFINES += __MARM_ARMV6__
|
||||
CONFIG += 4.6.3
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "controls.h"
|
||||
#include "ui_controls.h"
|
||||
#include "Core/Config.h"
|
||||
#include "EmuThread.h"
|
||||
#include <QTimer>
|
||||
|
||||
Controls_ controllist[] = {
|
||||
{"Edit_Start", "Start", Qt::Key_1, PAD_BUTTON_START, CTRL_START},
|
||||
@@ -43,6 +45,12 @@ Controls::~Controls()
|
||||
|
||||
void Controls::showEvent(QShowEvent*)
|
||||
{
|
||||
#ifdef Q_WS_X11
|
||||
// Hack to remove the X11 crash with threaded opengl when opening the first dialog
|
||||
EmuThread_LockDraw(true);
|
||||
QTimer::singleShot(100, this, SLOT(releaseLock()));
|
||||
#endif
|
||||
|
||||
for(int i = 0; i < controllistCount; i++)
|
||||
{
|
||||
if(g_Config.iMappingMap.find(i) != g_Config.iMappingMap.end())
|
||||
@@ -62,6 +70,11 @@ void Controls::showEvent(QShowEvent*)
|
||||
}
|
||||
}
|
||||
|
||||
void Controls::releaseLock()
|
||||
{
|
||||
EmuThread_LockDraw(false);
|
||||
}
|
||||
|
||||
void Controls::on_buttonBox_accepted()
|
||||
{
|
||||
for(int i = 0; i < controllistCount; i++)
|
||||
|
||||
@@ -32,6 +32,7 @@ public:
|
||||
|
||||
void showEvent(QShowEvent *);
|
||||
private slots:
|
||||
void releaseLock();
|
||||
void on_buttonBox_accepted();
|
||||
|
||||
private:
|
||||
|
||||
+61
-32
@@ -2,6 +2,7 @@
|
||||
#include "ui_gamepaddialog.h"
|
||||
#include <QTimer>
|
||||
#include "Core/Config.h"
|
||||
#include "EmuThread.h"
|
||||
|
||||
// Input
|
||||
struct GamePadInfo
|
||||
@@ -15,26 +16,26 @@ struct GamePadInfo
|
||||
|
||||
// Initial values are PS3 controller
|
||||
GamePadInfo GamepadPadMapping[] = {
|
||||
{0, 14, 0, "Prev_X", "Cross"}, //A
|
||||
{0, 13, 0, "Prev_O", "Circle"}, //B
|
||||
{0, 15, 0, "Prev_S", "Square"}, //X
|
||||
{0, 12, 0, "Prev_T", "Triangle"}, //Y
|
||||
{0, 10, 0, "Prev_LT", "Left Trigger"}, //LBUMPER
|
||||
{0, 11, 0, "Prev_RT", "Right Trigger"}, //RBUMPER
|
||||
{0, 3, 0, "Prev_Start", "Start"}, //START
|
||||
{0, 0, 0, "Prev_Select", "Select"}, //SELECT
|
||||
{0, 4, 0, "Prev_Up", "Up"}, //UP
|
||||
{0, 6, 0, "Prev_Down", "Down"}, //DOWN
|
||||
{0, 7, 0, "Prev_Left", "Left"}, //LEFT
|
||||
{0, 5, 0, "Prev_Right", "Right"}, //RIGHT
|
||||
{0, 0, 0, ""}, //MENU (event)
|
||||
{0, 16, 0, "Prev_Home", "Home"}, //BACK
|
||||
{0, 14, 0, "Prev_X", QT_TRANSLATE_NOOP("gamepadMapping", "Cross")}, //A
|
||||
{0, 13, 0, "Prev_O", QT_TRANSLATE_NOOP("gamepadMapping", "Circle")}, //B
|
||||
{0, 15, 0, "Prev_S", QT_TRANSLATE_NOOP("gamepadMapping", "Square")}, //X
|
||||
{0, 12, 0, "Prev_T", QT_TRANSLATE_NOOP("gamepadMapping", "Triangle")}, //Y
|
||||
{0, 10, 0, "Prev_LT", QT_TRANSLATE_NOOP("gamepadMapping", "Left Trigger")}, //LBUMPER
|
||||
{0, 11, 0, "Prev_RT", QT_TRANSLATE_NOOP("gamepadMapping", "Right Trigger")}, //RBUMPER
|
||||
{0, 3, 0, "Prev_Start", QT_TRANSLATE_NOOP("gamepadMapping", "Start")}, //START
|
||||
{0, 0, 0, "Prev_Select", QT_TRANSLATE_NOOP("gamepadMapping", "Select")}, //SELECT
|
||||
{0, 4, 0, "Prev_Up", QT_TRANSLATE_NOOP("gamepadMapping", "Up")}, //UP
|
||||
{0, 6, 0, "Prev_Down", QT_TRANSLATE_NOOP("gamepadMapping", "Down")}, //DOWN
|
||||
{0, 7, 0, "Prev_Left", QT_TRANSLATE_NOOP("gamepadMapping", "Left")}, //LEFT
|
||||
{0, 5, 0, "Prev_Right", QT_TRANSLATE_NOOP("gamepadMapping", "Right")}, //RIGHT
|
||||
{0, 0, 0, ""}, //MENU (event)
|
||||
{0, 16, 0, "Prev_Home", QT_TRANSLATE_NOOP("gamepadMapping", "Home")}, //BACK
|
||||
|
||||
// Special case for analog stick
|
||||
{1, 0, -1, "Prev_ALeft", "Stick left"},
|
||||
{1, 0, 1, "Prev_ARight", "Stick right"},
|
||||
{1, 1, -1, "Prev_AUp", "Stick up"},
|
||||
{1, 1, 1, "Prev_ADown", "Stick bottom"}
|
||||
{1, 0, -1, "Prev_ALeft", QT_TRANSLATE_NOOP("gamepadMapping", "Stick left")},
|
||||
{1, 0, 1, "Prev_ARight", QT_TRANSLATE_NOOP("gamepadMapping", "Stick right")},
|
||||
{1, 1, -1, "Prev_AUp", QT_TRANSLATE_NOOP("gamepadMapping", "Stick up")},
|
||||
{1, 1, 1, "Prev_ADown", QT_TRANSLATE_NOOP("gamepadMapping", "Stick bottom")}
|
||||
};
|
||||
|
||||
// id for mapping in config start at offset 200 to not get over key mapping
|
||||
@@ -96,13 +97,41 @@ GamePadDialog::~GamePadDialog()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void GamePadDialog::showEvent(QShowEvent *)
|
||||
{
|
||||
#ifdef Q_WS_X11
|
||||
// Hack to remove the X11 crash with threaded opengl when opening the first dialog
|
||||
EmuThread_LockDraw(true);
|
||||
QTimer::singleShot(100, this, SLOT(releaseLock()));
|
||||
#endif
|
||||
}
|
||||
|
||||
void GamePadDialog::changeEvent(QEvent *event)
|
||||
{
|
||||
QDialog::changeEvent(event);
|
||||
|
||||
if (0 != event)
|
||||
{
|
||||
if (event->type() == QEvent::LanguageChange)
|
||||
{
|
||||
ui->retranslateUi(this);
|
||||
on_refreshListBtn_clicked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GamePadDialog::releaseLock()
|
||||
{
|
||||
EmuThread_LockDraw(false);
|
||||
}
|
||||
|
||||
void GamePadDialog::on_refreshListBtn_clicked()
|
||||
{
|
||||
#if QT_HAS_SDL
|
||||
if(m_joystick)
|
||||
{
|
||||
SDL_JoystickClose(m_joystick);
|
||||
ui->JoyName->setText("<b>No GamePad</b>");
|
||||
ui->JoyName->setText(tr("<b>No gamepad</b>"));
|
||||
m_joystick = 0;
|
||||
}
|
||||
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
||||
@@ -114,7 +143,7 @@ void GamePadDialog::on_refreshListBtn_clicked()
|
||||
{
|
||||
QListWidgetItem* item = new QListWidgetItem();
|
||||
QString padName = SDL_JoystickName(i);
|
||||
if(padName == "") padName = "<b>Unknown GamePad</b>";
|
||||
if(padName == "") padName = tr("<b>Unknown gamepad</b>");
|
||||
item->setText(padName);
|
||||
item->setData(Qt::UserRole,i);
|
||||
ui->GamePadList->addItem(item);
|
||||
@@ -255,7 +284,7 @@ void GamePadDialog::on_SelectPadBtn_clicked()
|
||||
ui->comboPSPButton->clear();
|
||||
|
||||
QTreeWidgetItem* buttonItem = new QTreeWidgetItem();
|
||||
buttonItem->setText(0,"Buttons");
|
||||
buttonItem->setText(0,tr("Buttons"));
|
||||
ui->padValues->addTopLevelItem(buttonItem);
|
||||
|
||||
for(int i = 0; i < SDL_JoystickNumButtons(m_joystick); i++)
|
||||
@@ -269,37 +298,37 @@ void GamePadDialog::on_SelectPadBtn_clicked()
|
||||
buttonItem->addChild(item);
|
||||
|
||||
int id = i << 8;
|
||||
ui->comboPadInput->addItem("Button "+QVariant(i).toString(),GetIntFromMapping(i,0,0));
|
||||
ui->comboPadInput->addItem(tr("Button %1").arg(i),GetIntFromMapping(i,0,0));
|
||||
}
|
||||
QTreeWidgetItem* axesItem = new QTreeWidgetItem();
|
||||
axesItem->setText(0,"Axes");
|
||||
axesItem->setText(0,tr("Axes"));
|
||||
ui->padValues->addTopLevelItem(axesItem);
|
||||
|
||||
for(int i = 0; i < SDL_JoystickNumAxes(m_joystick); i++)
|
||||
{
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||
item->setText(0,QVariant(i).toString()+" Neg");
|
||||
item->setText(0,tr("%1 Neg").arg(i));
|
||||
item->setText(1,QVariant(0).toString());
|
||||
item->setData(0, Qt::UserRole,1);
|
||||
item->setData(0, Qt::UserRole+1,i);
|
||||
item->setData(0, Qt::UserRole+2,-1);
|
||||
axesItem->addChild(item);
|
||||
|
||||
ui->comboPadInput->addItem("Axes "+QVariant(i).toString()+" Neg",GetIntFromMapping(i,1,-1));
|
||||
ui->comboPadInput->addItem(tr("Axes %1 Neg").arg(i),GetIntFromMapping(i,1,-1));
|
||||
|
||||
item = new QTreeWidgetItem();
|
||||
item->setText(0,QVariant(i).toString()+" Pos");
|
||||
item->setText(0,tr("%1 Pos").arg(i));
|
||||
item->setText(1,QVariant(0).toString());
|
||||
item->setData(0, Qt::UserRole,1);
|
||||
item->setData(0, Qt::UserRole+1,i);
|
||||
item->setData(0, Qt::UserRole+2,1);
|
||||
axesItem->addChild(item);
|
||||
|
||||
ui->comboPadInput->addItem("Axes "+QVariant(i).toString()+" Pos",GetIntFromMapping(i,1,1));
|
||||
ui->comboPadInput->addItem(tr("Axes %1 Pos").arg(i),GetIntFromMapping(i,1,1));
|
||||
}
|
||||
|
||||
QTreeWidgetItem* hatsItem = new QTreeWidgetItem();
|
||||
hatsItem->setText(0,"Hats");
|
||||
hatsItem->setText(0,tr("Hats"));
|
||||
ui->padValues->addTopLevelItem(hatsItem);
|
||||
|
||||
for(int i = 0; i < SDL_JoystickNumHats(m_joystick); i++)
|
||||
@@ -312,14 +341,14 @@ void GamePadDialog::on_SelectPadBtn_clicked()
|
||||
item->setData(0, Qt::UserRole+2,0);
|
||||
hatsItem->addChild(item);
|
||||
|
||||
ui->comboPadInput->addItem("Button "+QVariant(i).toString(),GetIntFromMapping(i,2,0));
|
||||
ui->comboPadInput->addItem(tr("Button %1").arg(i),GetIntFromMapping(i,2,0));
|
||||
}
|
||||
|
||||
for(int i = 0; i < 18; i++)
|
||||
{
|
||||
if(GamepadPadMapping[i].Name != "")
|
||||
{
|
||||
ui->comboPSPButton->addItem(GamepadPadMapping[i].Name,i);
|
||||
ui->comboPSPButton->addItem(QApplication::translate("gamepadMapping", GamepadPadMapping[i].Name.toStdString().c_str()),i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,9 +363,9 @@ void GamePadDialog::SetViewMode()
|
||||
ui->refreshListBtn->setEnabled(true);
|
||||
ui->SelectPadBtn->setEnabled(true);
|
||||
if(!m_joystick)
|
||||
ui->JoyName->setText("<b>No GamePad</b>");
|
||||
ui->JoyName->setText(tr("<b>No gamepad</b>"));
|
||||
else
|
||||
ui->JoyName->setText(QString("<b>Current gamepad : ")+SDL_JoystickName(m_joyId)+"</b>");
|
||||
ui->JoyName->setText(tr("<b>Current gamepad: %1</b>").arg(SDL_JoystickName(m_joyId)));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,11 @@ public:
|
||||
void SetViewMode();
|
||||
void SetCalibMode();
|
||||
void CalibNextButton();
|
||||
protected:
|
||||
void showEvent(QShowEvent *);
|
||||
void changeEvent(QEvent *);
|
||||
private slots:
|
||||
void releaseLock();
|
||||
void on_refreshListBtn_clicked();
|
||||
|
||||
void on_SelectPadBtn_clicked();
|
||||
|
||||
@@ -0,0 +1,634 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.0" language="en_US">
|
||||
<context>
|
||||
<name>Controls</name>
|
||||
<message>
|
||||
<location filename="../controls.ui" line="20"/>
|
||||
<source>Controls</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Debugger_Disasm</name>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="17"/>
|
||||
<source>Dialog</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="25"/>
|
||||
<source>Ctr:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="38"/>
|
||||
<source>&Go to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="73"/>
|
||||
<source>&PC</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="86"/>
|
||||
<source>&LR</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="118"/>
|
||||
<source>Tab 1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="128"/>
|
||||
<source>Tab 2</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="153"/>
|
||||
<source>&Go</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="166"/>
|
||||
<source>Stop</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="179"/>
|
||||
<source>Step &Into</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="192"/>
|
||||
<source>Step &Over</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="205"/>
|
||||
<source>S&kip</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="218"/>
|
||||
<source>Next &HLE</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GamePadDialog</name>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="14"/>
|
||||
<source>Gamepad Configuration</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="22"/>
|
||||
<source>GamePad List</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="46"/>
|
||||
<source>Refresh</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="53"/>
|
||||
<source>Select</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="62"/>
|
||||
<source>Gamepad Values :</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="86"/>
|
||||
<source>TextLabel</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="98"/>
|
||||
<source>Assign Gamepad input</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="108"/>
|
||||
<source> to PSP button/axis</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="118"/>
|
||||
<source>Assign</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="127"/>
|
||||
<source>Press buttons on your gamePad to verify mapping :</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="134"/>
|
||||
<location filename="../gamepaddialog.cpp" line="366"/>
|
||||
<source><b>No gamepad</b></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="146"/>
|
||||
<source><b>Unknown gamepad</b></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="287"/>
|
||||
<source>Buttons</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="301"/>
|
||||
<location filename="../gamepaddialog.cpp" line="344"/>
|
||||
<source>Button %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="304"/>
|
||||
<source>Axes</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="310"/>
|
||||
<source>%1 Neg</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="317"/>
|
||||
<source>Axes %1 Neg</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="320"/>
|
||||
<source>%1 Pos</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="327"/>
|
||||
<source>Axes %1 Pos</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="331"/>
|
||||
<source>Hats</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="368"/>
|
||||
<source><b>Current gamepad: %1</b></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MainWindow</name>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="20"/>
|
||||
<source>PPSSPP</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="52"/>
|
||||
<source>&File</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="66"/>
|
||||
<source>&Emulation</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="79"/>
|
||||
<source>Debu&g</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="91"/>
|
||||
<source>&Options</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="95"/>
|
||||
<source>&Log Levels</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="99"/>
|
||||
<source>G3D</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="108"/>
|
||||
<source>HLE</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="117"/>
|
||||
<source>Default</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="131"/>
|
||||
<source>Zoom</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="140"/>
|
||||
<source>Language</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="167"/>
|
||||
<source>&Help</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="182"/>
|
||||
<source>&Open...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="187"/>
|
||||
<source>&Close</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="192"/>
|
||||
<source>-</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="197"/>
|
||||
<source>Quickload state</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="200"/>
|
||||
<source>F4</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="205"/>
|
||||
<source>Quicksave state</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="208"/>
|
||||
<source>F2</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="213"/>
|
||||
<source>&Load State File...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="218"/>
|
||||
<source>&Save State File...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="223"/>
|
||||
<source>E&xit</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="228"/>
|
||||
<source>&Run</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="231"/>
|
||||
<source>F7</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="236"/>
|
||||
<source>&Pause</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="239"/>
|
||||
<source>F8</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="244"/>
|
||||
<source>R&eset</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="252"/>
|
||||
<source>&Interpreter</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="260"/>
|
||||
<source>&Slightly Faster Interpreter</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="268"/>
|
||||
<source>&Dynarec</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="276"/>
|
||||
<source>Load &Map File...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="284"/>
|
||||
<source>&Save Map File...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="292"/>
|
||||
<source>&Reset Symbol Table</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="300"/>
|
||||
<source>&Disassembly</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="303"/>
|
||||
<source>Ctrl+D</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="311"/>
|
||||
<source>&Log Console</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="314"/>
|
||||
<source>Ctrl+L</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="322"/>
|
||||
<source>Memory &View...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="325"/>
|
||||
<source>Ctrl+M</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="330"/>
|
||||
<source>Keyboard &Controls</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="335"/>
|
||||
<source>&Toggle Full Screen</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="338"/>
|
||||
<source>F12</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="346"/>
|
||||
<source>&Buffered Rendering</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="349"/>
|
||||
<source>F5</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="357"/>
|
||||
<source>&Hardware Transform</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="360"/>
|
||||
<source>F6</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="368"/>
|
||||
<source>&Linear Filtering</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="376"/>
|
||||
<source>&Wireframe (experimental)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="384"/>
|
||||
<source>&Display Raw Framebuffer</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="392"/>
|
||||
<source>&Show Debug Statistics</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="400"/>
|
||||
<source>Screen &1x</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="403"/>
|
||||
<source>Ctrl+1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="411"/>
|
||||
<source>Screen &2x</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="414"/>
|
||||
<source>Ctrl+2</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="422"/>
|
||||
<source>Screen &3x</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="425"/>
|
||||
<source>Ctrl+3</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="433"/>
|
||||
<source>Screen &4x</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="436"/>
|
||||
<source>Ctrl+4</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="444"/>
|
||||
<source>&Fast Memory (dynarec, unstable)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="452"/>
|
||||
<source>&Ignore illegal reads/writes</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="457"/>
|
||||
<source>&Go to http://www.ppsspp.org/</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="462"/>
|
||||
<source>&About PPSSPP...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="467"/>
|
||||
<source>&Use VBO</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="475"/>
|
||||
<location filename="../mainwindow.ui" line="507"/>
|
||||
<location filename="../mainwindow.ui" line="539"/>
|
||||
<source>Debug</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="483"/>
|
||||
<location filename="../mainwindow.ui" line="515"/>
|
||||
<location filename="../mainwindow.ui" line="547"/>
|
||||
<source>Warning</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="491"/>
|
||||
<location filename="../mainwindow.ui" line="531"/>
|
||||
<location filename="../mainwindow.ui" line="563"/>
|
||||
<source>Error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="499"/>
|
||||
<location filename="../mainwindow.ui" line="523"/>
|
||||
<location filename="../mainwindow.ui" line="555"/>
|
||||
<source>Info</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="568"/>
|
||||
<source>GamePad Controls</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="828"/>
|
||||
<source>No translations</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>gamepadMapping</name>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="19"/>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="20"/>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="21"/>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="22"/>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="23"/>
|
||||
<source>Left Trigger</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="24"/>
|
||||
<source>Right Trigger</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="25"/>
|
||||
<source>Start</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="26"/>
|
||||
<source>Select</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="27"/>
|
||||
<source>Up</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="28"/>
|
||||
<source>Down</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="29"/>
|
||||
<source>Left</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="30"/>
|
||||
<source>Right</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="32"/>
|
||||
<source>Home</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="35"/>
|
||||
<source>Stick left</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="36"/>
|
||||
<source>Stick right</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="37"/>
|
||||
<source>Stick up</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="38"/>
|
||||
<source>Stick bottom</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
@@ -0,0 +1,634 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.0" language="pl_PL">
|
||||
<context>
|
||||
<name>Controls</name>
|
||||
<message>
|
||||
<location filename="../controls.ui" line="20"/>
|
||||
<source>Controls</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Debugger_Disasm</name>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="17"/>
|
||||
<source>Dialog</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="25"/>
|
||||
<source>Ctr:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="38"/>
|
||||
<source>&Go to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="73"/>
|
||||
<source>&PC</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="86"/>
|
||||
<source>&LR</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="118"/>
|
||||
<source>Tab 1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="128"/>
|
||||
<source>Tab 2</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="153"/>
|
||||
<source>&Go</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="166"/>
|
||||
<source>Stop</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="179"/>
|
||||
<source>Step &Into</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="192"/>
|
||||
<source>Step &Over</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="205"/>
|
||||
<source>S&kip</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugger_disasm.ui" line="218"/>
|
||||
<source>Next &HLE</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GamePadDialog</name>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="14"/>
|
||||
<source>Gamepad Configuration</source>
|
||||
<translation>Konfiguracja kontrolera</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="22"/>
|
||||
<source>GamePad List</source>
|
||||
<translation>Lista kontrolerów</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="46"/>
|
||||
<source>Refresh</source>
|
||||
<translation>Odśwież</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="53"/>
|
||||
<source>Select</source>
|
||||
<translation>Wybierz</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="62"/>
|
||||
<source>Gamepad Values :</source>
|
||||
<translation>Wartości przycisków/osi:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="86"/>
|
||||
<source>TextLabel</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="98"/>
|
||||
<source>Assign Gamepad input</source>
|
||||
<translation>Przypisz przycisk</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="108"/>
|
||||
<source> to PSP button/axis</source>
|
||||
<translation>do przycisku/osi PSP</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="118"/>
|
||||
<source>Assign</source>
|
||||
<translation>Przypisz</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.ui" line="127"/>
|
||||
<source>Press buttons on your gamePad to verify mapping :</source>
|
||||
<translation>Naciśnij przyciski na kontrolerze:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="134"/>
|
||||
<location filename="../gamepaddialog.cpp" line="366"/>
|
||||
<source><b>No gamepad</b></source>
|
||||
<translation><b>Nie wykryto pada</b></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="146"/>
|
||||
<source><b>Unknown gamepad</b></source>
|
||||
<translation><b>Nieznany pad</b></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="287"/>
|
||||
<source>Buttons</source>
|
||||
<translation>Przyciski</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="301"/>
|
||||
<location filename="../gamepaddialog.cpp" line="344"/>
|
||||
<source>Button %1</source>
|
||||
<translation>Przycisk %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="304"/>
|
||||
<source>Axes</source>
|
||||
<translation>Osie</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="310"/>
|
||||
<source>%1 Neg</source>
|
||||
<translation>%1 zanegowany</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="317"/>
|
||||
<source>Axes %1 Neg</source>
|
||||
<translation>Oś %1 zanegowana</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="320"/>
|
||||
<source>%1 Pos</source>
|
||||
<translation>%1 pozycja</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="327"/>
|
||||
<source>Axes %1 Pos</source>
|
||||
<translation>Pozycja osi %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="331"/>
|
||||
<source>Hats</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="368"/>
|
||||
<source><b>Current gamepad: %1</b></source>
|
||||
<translation><b>Wybrany pad: %1</b></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MainWindow</name>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="20"/>
|
||||
<source>PPSSPP</source>
|
||||
<translation>PPSSPP</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="52"/>
|
||||
<source>&File</source>
|
||||
<translation>&Plik</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="66"/>
|
||||
<source>&Emulation</source>
|
||||
<translation>&Emulacja</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="79"/>
|
||||
<source>Debu&g</source>
|
||||
<translation>&Debugger</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="91"/>
|
||||
<source>&Options</source>
|
||||
<translation>&Opcje</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="95"/>
|
||||
<source>&Log Levels</source>
|
||||
<translation>P&oziomy logowania</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="99"/>
|
||||
<source>G3D</source>
|
||||
<translation>G3D</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="108"/>
|
||||
<source>HLE</source>
|
||||
<translation>HLE</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="117"/>
|
||||
<source>Default</source>
|
||||
<translation>Domyślne</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="131"/>
|
||||
<source>Zoom</source>
|
||||
<translation>Zoom</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="140"/>
|
||||
<source>Language</source>
|
||||
<translation>Język</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="167"/>
|
||||
<source>&Help</source>
|
||||
<translation>Pomo&c</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="182"/>
|
||||
<source>&Open...</source>
|
||||
<translation>&Otwórz...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="187"/>
|
||||
<source>&Close</source>
|
||||
<translation>&Zamknij</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="192"/>
|
||||
<source>-</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="197"/>
|
||||
<source>Quickload state</source>
|
||||
<translation>Wczytaj stan</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="200"/>
|
||||
<source>F4</source>
|
||||
<translation>F4</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="205"/>
|
||||
<source>Quicksave state</source>
|
||||
<translation>Zapisz stan</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="208"/>
|
||||
<source>F2</source>
|
||||
<translation>F2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="213"/>
|
||||
<source>&Load State File...</source>
|
||||
<translation>&Wczytaj plik stanu...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="218"/>
|
||||
<source>&Save State File...</source>
|
||||
<translation>&Zapisz plik stanu...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="223"/>
|
||||
<source>E&xit</source>
|
||||
<translation>Wyj&dź</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="228"/>
|
||||
<source>&Run</source>
|
||||
<translation>&Uruchom</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="231"/>
|
||||
<source>F7</source>
|
||||
<translation>F7</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="236"/>
|
||||
<source>&Pause</source>
|
||||
<translation>&Pauza</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="239"/>
|
||||
<source>F8</source>
|
||||
<translation>F8</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="244"/>
|
||||
<source>R&eset</source>
|
||||
<translation>&Reset</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="252"/>
|
||||
<source>&Interpreter</source>
|
||||
<translation>&Interpreter</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="260"/>
|
||||
<source>&Slightly Faster Interpreter</source>
|
||||
<translation>&Szybszy interpreter</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="268"/>
|
||||
<source>&Dynarec</source>
|
||||
<translation>R&ekompilacja (Dynarec)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="276"/>
|
||||
<source>Load &Map File...</source>
|
||||
<translation>&Wczytaj plik mapy...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="284"/>
|
||||
<source>&Save Map File...</source>
|
||||
<translation>&Zapisz plik mapy...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="292"/>
|
||||
<source>&Reset Symbol Table</source>
|
||||
<translation>Zresetuj &tablicę symboli</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="300"/>
|
||||
<source>&Disassembly</source>
|
||||
<translation>&Dekompiluj</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="303"/>
|
||||
<source>Ctrl+D</source>
|
||||
<translation>Ctrl+D</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="311"/>
|
||||
<source>&Log Console</source>
|
||||
<translation>&Konsola logowania</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="314"/>
|
||||
<source>Ctrl+L</source>
|
||||
<translation>Ctrl+L</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="322"/>
|
||||
<source>Memory &View...</source>
|
||||
<translation>Widok &pamięci...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="325"/>
|
||||
<source>Ctrl+M</source>
|
||||
<translation>Ctrl+M</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="330"/>
|
||||
<source>Keyboard &Controls</source>
|
||||
<translation>Ustawienia &klawiatury</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="335"/>
|
||||
<source>&Toggle Full Screen</source>
|
||||
<translation>&Pełny ekran</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="338"/>
|
||||
<source>F12</source>
|
||||
<translation>F12</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="346"/>
|
||||
<source>&Buffered Rendering</source>
|
||||
<translation>&Buffered rendering</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="349"/>
|
||||
<source>F5</source>
|
||||
<translation>F5</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="357"/>
|
||||
<source>&Hardware Transform</source>
|
||||
<translation>&Hardware Transform</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="360"/>
|
||||
<source>F6</source>
|
||||
<translation>F6</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="368"/>
|
||||
<source>&Linear Filtering</source>
|
||||
<translation>&Linear Filtering</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="376"/>
|
||||
<source>&Wireframe (experimental)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="384"/>
|
||||
<source>&Display Raw Framebuffer</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="392"/>
|
||||
<source>&Show Debug Statistics</source>
|
||||
<translation>Pokaż &statystyki emulacji</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="400"/>
|
||||
<source>Screen &1x</source>
|
||||
<translation>&1x</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="403"/>
|
||||
<source>Ctrl+1</source>
|
||||
<translation>Ctrl+1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="411"/>
|
||||
<source>Screen &2x</source>
|
||||
<translation>&2x</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="414"/>
|
||||
<source>Ctrl+2</source>
|
||||
<translation>Ctrl+2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="422"/>
|
||||
<source>Screen &3x</source>
|
||||
<translation>&3x</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="425"/>
|
||||
<source>Ctrl+3</source>
|
||||
<translation>Ctrl+3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="433"/>
|
||||
<source>Screen &4x</source>
|
||||
<translation>&4x</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="436"/>
|
||||
<source>Ctrl+4</source>
|
||||
<translation>Ctrl+4</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="444"/>
|
||||
<source>&Fast Memory (dynarec, unstable)</source>
|
||||
<translation>&Fast memory (wymagany Dynarec, niestabilne)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="452"/>
|
||||
<source>&Ignore illegal reads/writes</source>
|
||||
<translation>&Ignoruj nieprawidłowe odczyty/zapisy</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="457"/>
|
||||
<source>&Go to http://www.ppsspp.org/</source>
|
||||
<translation>&Idź do http://www.ppsspp.org</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="462"/>
|
||||
<source>&About PPSSPP...</source>
|
||||
<translation>&O PPSSPP...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="467"/>
|
||||
<source>&Use VBO</source>
|
||||
<translation>Użyj &VBO</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="475"/>
|
||||
<location filename="../mainwindow.ui" line="507"/>
|
||||
<location filename="../mainwindow.ui" line="539"/>
|
||||
<source>Debug</source>
|
||||
<translation>Debug</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="483"/>
|
||||
<location filename="../mainwindow.ui" line="515"/>
|
||||
<location filename="../mainwindow.ui" line="547"/>
|
||||
<source>Warning</source>
|
||||
<translation>Ostrzeżenia</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="491"/>
|
||||
<location filename="../mainwindow.ui" line="531"/>
|
||||
<location filename="../mainwindow.ui" line="563"/>
|
||||
<source>Error</source>
|
||||
<translation>Błędy</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="499"/>
|
||||
<location filename="../mainwindow.ui" line="523"/>
|
||||
<location filename="../mainwindow.ui" line="555"/>
|
||||
<source>Info</source>
|
||||
<translation>Info</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="568"/>
|
||||
<source>GamePad Controls</source>
|
||||
<translation>&Ustawienia pada</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="828"/>
|
||||
<source>No translations</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>gamepadMapping</name>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="19"/>
|
||||
<source>Cross</source>
|
||||
<translation>Krzyżyk</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="20"/>
|
||||
<source>Circle</source>
|
||||
<translation>Kółko</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="21"/>
|
||||
<source>Square</source>
|
||||
<translation>Kwadrat</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="22"/>
|
||||
<source>Triangle</source>
|
||||
<translation>Trójkąt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="23"/>
|
||||
<source>Left Trigger</source>
|
||||
<translation>Lewy trigger</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="24"/>
|
||||
<source>Right Trigger</source>
|
||||
<translation>Prawy trigger</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="25"/>
|
||||
<source>Start</source>
|
||||
<translation>Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="26"/>
|
||||
<source>Select</source>
|
||||
<translation>Select</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="27"/>
|
||||
<source>Up</source>
|
||||
<translation>Góra</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="28"/>
|
||||
<source>Down</source>
|
||||
<translation>Dół</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="29"/>
|
||||
<source>Left</source>
|
||||
<translation>Lewo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="30"/>
|
||||
<source>Right</source>
|
||||
<translation>Prawo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="32"/>
|
||||
<source>Home</source>
|
||||
<translation>Klawisz Home</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="35"/>
|
||||
<source>Stick left</source>
|
||||
<translation>Lewo (analog)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="36"/>
|
||||
<source>Stick right</source>
|
||||
<translation>Prawo (analog)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="37"/>
|
||||
<source>Stick up</source>
|
||||
<translation>Góra (analog)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gamepaddialog.cpp" line="38"/>
|
||||
<source>Stick bottom</source>
|
||||
<translation>Dół (analog)</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
-101
@@ -1,101 +0,0 @@
|
||||
#include "mainui.h"
|
||||
|
||||
#include <QAudioOutput>
|
||||
#include <QAudioFormat>
|
||||
#include "base/display.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/timeutil.h"
|
||||
#include "file/zip_read.h"
|
||||
#include "base/NativeApp.h"
|
||||
#include "net/resolve.h"
|
||||
#include "base/display.h"
|
||||
|
||||
|
||||
void SimulateGamepad(InputState *input) {
|
||||
input->pad_lstick_x = 0;
|
||||
input->pad_lstick_y = 0;
|
||||
input->pad_rstick_x = 0;
|
||||
input->pad_rstick_y = 0;
|
||||
|
||||
if (input->pad_buttons & (1<<14))
|
||||
input->pad_lstick_y=1;
|
||||
else if (input->pad_buttons & (1<<15))
|
||||
input->pad_lstick_y=-1;
|
||||
if (input->pad_buttons & (1<<16))
|
||||
input->pad_lstick_x=-1;
|
||||
else if (input->pad_buttons & (1<<17))
|
||||
input->pad_lstick_x=1;
|
||||
}
|
||||
|
||||
MainUI::~MainUI() {
|
||||
NativeShutdownGraphics();
|
||||
}
|
||||
|
||||
bool MainUI::event(QEvent *e)
|
||||
{
|
||||
QList<QTouchEvent::TouchPoint> touchPoints;
|
||||
switch(e->type())
|
||||
{
|
||||
case QEvent::TouchBegin:
|
||||
case QEvent::TouchUpdate:
|
||||
case QEvent::TouchEnd:
|
||||
touchPoints = static_cast<QTouchEvent *>(e)->touchPoints();
|
||||
foreach (const QTouchEvent::TouchPoint &touchPoint, touchPoints) {
|
||||
switch (touchPoint.state()) {
|
||||
case Qt::TouchPointStationary:
|
||||
break;
|
||||
case Qt::TouchPointPressed:
|
||||
case Qt::TouchPointReleased:
|
||||
input_state.pointer_down[touchPoint.id()] = (touchPoint.state() == Qt::TouchPointPressed);
|
||||
case Qt::TouchPointMoved:
|
||||
input_state.pointer_x[touchPoint.id()] = touchPoint.pos().x() * dpi_scale;
|
||||
input_state.pointer_y[touchPoint.id()] = touchPoint.pos().y() * dpi_scale;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case QEvent::MouseButtonPress:
|
||||
case QEvent::MouseButtonRelease:
|
||||
input_state.pointer_down[0] = (e->type() == QEvent::MouseButtonPress);
|
||||
case QEvent::MouseMove:
|
||||
input_state.pointer_x[0] = ((QMouseEvent*)e)->pos().x() * dpi_scale;
|
||||
input_state.pointer_y[0] = ((QMouseEvent*)e)->pos().y() * dpi_scale;
|
||||
break;
|
||||
case QEvent::KeyPress:
|
||||
for (int b = 0; b < 14; b++) {
|
||||
if (((QKeyEvent*)e)->key() == buttonMappings[b])
|
||||
input_state.pad_buttons |= (1<<b);
|
||||
}
|
||||
break;
|
||||
case QEvent::KeyRelease:
|
||||
for (int b = 0; b < 14; b++) {
|
||||
if (((QKeyEvent*)e)->key() == buttonMappings[b])
|
||||
input_state.pad_buttons &= ~(1<<b);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return QWidget::event(e);
|
||||
}
|
||||
e->accept();
|
||||
return true;
|
||||
}
|
||||
|
||||
void MainUI::initializeGL()
|
||||
{
|
||||
#ifndef USING_GLES2
|
||||
glewInit();
|
||||
#endif
|
||||
NativeInitGraphics();
|
||||
}
|
||||
void MainUI::paintGL()
|
||||
{
|
||||
SimulateGamepad(&input_state);
|
||||
UpdateInputState(&input_state);
|
||||
NativeUpdate(input_state);
|
||||
EndInputState(&input_state);
|
||||
NativeRender();
|
||||
|
||||
update();
|
||||
}
|
||||
+106
-5
@@ -48,6 +48,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
DialogManager::AddDlg(vfpudlg = new CVFPUDlg(_hInstance, hwndMain, currentDebugMIPS));
|
||||
*/
|
||||
// Update();
|
||||
createLanguageMenu();
|
||||
UpdateMenus();
|
||||
|
||||
int zoom = g_Config.iWindowZoom;
|
||||
@@ -55,16 +56,16 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
if (zoom > 4) zoom = 4;
|
||||
SetZoom(zoom);
|
||||
|
||||
EmuThread_Start(w);
|
||||
|
||||
if (!fileToStart.isNull())
|
||||
{
|
||||
SetPlaying(fileToStart);
|
||||
//Update();
|
||||
UpdateMenus();
|
||||
|
||||
EmuThread_Start(fileToStart, w);
|
||||
EmuThread_StartGame(fileToStart);
|
||||
}
|
||||
else
|
||||
BrowseAndBoot();
|
||||
|
||||
if (!fileToStart.isNull() && stateToLoad != NULL)
|
||||
SaveState::Load(stateToLoad);
|
||||
@@ -195,7 +196,7 @@ void MainWindow::BrowseAndBoot(void)
|
||||
{
|
||||
QFileInfo info(filename);
|
||||
g_Config.currentDirectory = info.absolutePath().toStdString();
|
||||
EmuThread_Start(filename, w);
|
||||
EmuThread_StartGame(filename);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,7 +325,7 @@ void MainWindow::on_action_EmulationStop_triggered()
|
||||
if (memoryWindow[i])
|
||||
SendMessage(memoryWindow[i]->GetDlgHandle(), WM_CLOSE, 0, 0);*/
|
||||
|
||||
EmuThread_Stop();
|
||||
EmuThread_StopGame();
|
||||
SetPlaying(0);
|
||||
//Update();
|
||||
UpdateMenus();
|
||||
@@ -485,6 +486,7 @@ void MainWindow::on_action_OptionsHardwareTransform_triggered()
|
||||
void MainWindow::on_action_FileExit_triggered()
|
||||
{
|
||||
on_action_EmulationStop_triggered();
|
||||
EmuThread_Stop();
|
||||
QApplication::exit(0);
|
||||
}
|
||||
|
||||
@@ -778,3 +780,102 @@ void MainWindow::on_action_OptionsGamePadControls_triggered()
|
||||
QMessageBox::information(this,"Gamepad","You need to compile with SDL to have Gamepad support.", QMessageBox::Ok);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MainWindow::on_language_changed(QAction *action)
|
||||
{
|
||||
if (0 != action)
|
||||
{
|
||||
loadLanguage(action->data().toString());
|
||||
}
|
||||
}
|
||||
|
||||
void switchTranslator(QTranslator &translator, const QString &filename)
|
||||
{
|
||||
qApp->removeTranslator(&translator);
|
||||
|
||||
if (translator.load(filename))
|
||||
qApp->installTranslator(&translator);
|
||||
}
|
||||
|
||||
void MainWindow::loadLanguage(const QString& language)
|
||||
{
|
||||
if (currentLanguage != language)
|
||||
{
|
||||
currentLanguage = language;
|
||||
QLocale locale = QLocale(currentLanguage);
|
||||
QLocale::setDefault(locale);
|
||||
QString languageName = QLocale::languageToString(locale.language());
|
||||
switchTranslator(translator, QString("languages/ppsspp_%1.qm").arg(language));
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::createLanguageMenu()
|
||||
{
|
||||
QActionGroup *langGroup = new QActionGroup(ui->menuLanguage);
|
||||
langGroup->setExclusive(true);
|
||||
|
||||
connect(langGroup, SIGNAL(triggered(QAction *)), this, SLOT(on_language_changed(QAction *)));
|
||||
|
||||
QString defaultLocale = QLocale::system().name();
|
||||
defaultLocale.truncate(defaultLocale.lastIndexOf('_'));
|
||||
languagePath = QApplication::applicationDirPath();
|
||||
languagePath.append("/languages");
|
||||
QDir langDir(languagePath);
|
||||
QStringList fileNames = langDir.entryList(QStringList("ppsspp_*.qm"));
|
||||
|
||||
if (fileNames.size() == 0)
|
||||
{
|
||||
QAction *action = new QAction(tr("No translations"), this);
|
||||
action->setCheckable(false);
|
||||
action->setDisabled(true);
|
||||
ui->menuLanguage->addAction(action);
|
||||
langGroup->addAction(action);
|
||||
}
|
||||
|
||||
for (int i = 0; i < fileNames.size(); ++i)
|
||||
{
|
||||
QString locale = fileNames[i];
|
||||
locale.truncate(locale.lastIndexOf('.'));
|
||||
locale.remove(0, locale.indexOf('_') + 1);
|
||||
|
||||
//QString language = QLocale::languageToString(QLocale(locale).language());
|
||||
QString language = QLocale(locale).nativeLanguageName();
|
||||
QAction *action = new QAction(language, this);
|
||||
action->setCheckable(true);
|
||||
action->setData(locale);
|
||||
|
||||
ui->menuLanguage->addAction(action);
|
||||
langGroup->addAction(action);
|
||||
|
||||
// TODO check en as default until we save language to config
|
||||
if ("en" == locale)
|
||||
{
|
||||
action->setChecked(true);
|
||||
currentLanguage = "en";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::changeEvent(QEvent *event)
|
||||
{
|
||||
QMainWindow::changeEvent(event);
|
||||
|
||||
if (0 != event)
|
||||
{
|
||||
switch (event->type())
|
||||
{
|
||||
case QEvent::LanguageChange:
|
||||
ui->retranslateUi(this);
|
||||
break;
|
||||
case QEvent::LocaleChange:
|
||||
{
|
||||
QString locale = QLocale::system().name();
|
||||
locale.truncate(locale.lastIndexOf('_'));
|
||||
loadLanguage(locale);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QTranslator>
|
||||
|
||||
#include "Core/Core.h"
|
||||
#include "input/input_state.h"
|
||||
@@ -135,7 +136,18 @@ private slots:
|
||||
|
||||
void on_action_OptionsGamePadControls_triggered();
|
||||
|
||||
void on_language_changed(QAction *action);
|
||||
|
||||
private:
|
||||
void loadLanguage(const QString &language);
|
||||
void createLanguageMenu();
|
||||
void changeEvent(QEvent *);
|
||||
|
||||
QTranslator translator;
|
||||
QTranslator qtTranslator;
|
||||
QString currentLanguage;
|
||||
QString languagePath;
|
||||
|
||||
Ui::MainWindow *ui;
|
||||
|
||||
QtEmuGL* w;
|
||||
|
||||
+7
-1
@@ -44,7 +44,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>23</height>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_File">
|
||||
@@ -135,6 +135,11 @@
|
||||
<addaction name="action_OptionsScreen3x"/>
|
||||
<addaction name="action_OptionsScreen4x"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuLanguage">
|
||||
<property name="title">
|
||||
<string>Language</string>
|
||||
</property>
|
||||
</widget>
|
||||
<addaction name="action_OptionsControls"/>
|
||||
<addaction name="action_OptionsGamePadControls"/>
|
||||
<addaction name="separator"/>
|
||||
@@ -155,6 +160,7 @@
|
||||
<addaction name="action_OptionsFastMemory"/>
|
||||
<addaction name="action_OptionsIgnoreIllegalReadsWrites"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="menuLanguage"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Help">
|
||||
<property name="title">
|
||||
|
||||
@@ -38,6 +38,28 @@ void QtEmuGL::stop_rendering()
|
||||
thread.Shutdown();
|
||||
}
|
||||
|
||||
void QtEmuGL::start_game(QString filename)
|
||||
{
|
||||
thread.startGame(filename);
|
||||
}
|
||||
|
||||
void QtEmuGL::stop_game()
|
||||
{
|
||||
thread.stopGame();
|
||||
}
|
||||
|
||||
void QtEmuGL::LockDraw(bool value)
|
||||
{
|
||||
if(value)
|
||||
{
|
||||
thread.gameMutex.lock();
|
||||
}
|
||||
else
|
||||
{
|
||||
thread.gameMutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void QtEmuGL::resizeEvent(QResizeEvent *evt)
|
||||
{
|
||||
// TODO
|
||||
|
||||
@@ -16,6 +16,9 @@ public:
|
||||
|
||||
void start_rendering();
|
||||
void stop_rendering();
|
||||
void start_game(QString filename);
|
||||
void stop_game();
|
||||
void LockDraw(bool value);
|
||||
protected:
|
||||
void initializeGL();
|
||||
|
||||
|
||||
@@ -61,8 +61,7 @@ with the mouse.
|
||||
Alternatively, a Qt-based frontend is available in the Qt/ dir.
|
||||
Open PPSSPPQt.pro with Qt Creator.
|
||||
Install libsdl1.2 if you want to use USB Gamepad.
|
||||
For Ubuntu user (>= 12.10) :
|
||||
- Remove multimedia in PPSSPP.pro on line 3
|
||||
If the build has an error about finding mobility or multimedia:
|
||||
- Install the package "qtmobility-dev"
|
||||
|
||||
Building for OSX
|
||||
|
||||
@@ -191,6 +191,8 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
|
||||
}
|
||||
}
|
||||
|
||||
VFSShutdown();
|
||||
|
||||
LogManager::Shutdown();
|
||||
DialogManager::DestroyAll();
|
||||
timeEndPeriod(1);
|
||||
|
||||
+2
-2
@@ -179,8 +179,8 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,176,217,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,230,217,50,14
|
||||
LTEXT "NOTE: Currently controls are NOT configurable.",IDC_STATIC,7,7,188,10
|
||||
LISTBOX IDC_LISTCONTROLS,7,19,273,184,LBS_SORT | LBS_USETABSTOPS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "NOTE: Currently controls are NOT configurable.\nHowever: Xbox 360 controllers are supported! Just plug one in and use it!",IDC_STATIC,7,7,188,30
|
||||
LISTBOX IDC_LISTCONTROLS,7,39,273,164,LBS_SORT | LBS_USETABSTOPS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
|
||||
END
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.ppsspp.ppsspp"
|
||||
android:versionCode="5"
|
||||
android:versionName="0.5" >
|
||||
android:versionCode="61"
|
||||
android:versionName="0.61" >
|
||||
|
||||
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="8"/>
|
||||
|
||||
@@ -26,4 +26,4 @@
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
</manifest>
|
||||
@@ -451,6 +451,7 @@ static const char *credits[] =
|
||||
"soywiz",
|
||||
"kovensky",
|
||||
"raven02",
|
||||
"xele",
|
||||
"",
|
||||
"Written in C++ for speed and portability",
|
||||
"",
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
// 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 "Compare.h"
|
||||
#include "FileUtil.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
bool CompareOutput(const std::string bootFilename)
|
||||
{
|
||||
std::string expect_filename = bootFilename.substr(bootFilename.length() - 4) + ".expected";
|
||||
if (File::Exists(expect_filename))
|
||||
{
|
||||
// TODO: Do the compare here
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Expectation file %s not found", expect_filename.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline int ComparePixel(u32 pix1, u32 pix2)
|
||||
{
|
||||
// For now, if they're different at all except alpha, it's an error.
|
||||
if ((pix1 & 0xFFFFFF) != (pix2 & 0xFFFFFF))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
double CompareScreenshot(const u8 *pixels, int w, int h, int stride, const std::string screenshotFilename, std::string &error)
|
||||
{
|
||||
u32 *pixels32 = (u32 *) pixels;
|
||||
// We assume the bitmap is the specified size, not including whatever stride.
|
||||
u32 *reference = (u32 *) calloc(w * h, sizeof(u32));
|
||||
|
||||
FILE *bmp = fopen(screenshotFilename.c_str(), "rb");
|
||||
if (bmp)
|
||||
{
|
||||
// The bitmap header is 14 + 40 bytes. We could validate it but the test would fail either way.
|
||||
fseek(bmp, 14 + 40, SEEK_SET);
|
||||
fread(reference, sizeof(u32), w * h, bmp);
|
||||
fclose(bmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = "Unable to read screenshot: " + screenshotFilename;
|
||||
free(reference);
|
||||
return -1.0f;
|
||||
}
|
||||
|
||||
u32 errors = 0;
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
errors += ComparePixel(pixels32[y * stride + x], reference[y * w + x]);
|
||||
}
|
||||
|
||||
free(reference);
|
||||
|
||||
return (double) errors / (double) (w * h);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// 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 <string>
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
bool CompareOutput(std::string bootFilename);
|
||||
double CompareScreenshot(const u8 *pixels, int w, int h, int stride, const std::string screenshotFilename, std::string &error);
|
||||
+16
-13
@@ -13,6 +13,7 @@
|
||||
#include "Log.h"
|
||||
#include "LogManager.h"
|
||||
|
||||
#include "Compare.h"
|
||||
#include "StubHost.h"
|
||||
#ifdef _WIN32
|
||||
#include "WindowsHeadlessHost.h"
|
||||
@@ -59,10 +60,14 @@ void printUsage(const char *progname, const char *reason)
|
||||
HEADLESSHOST_CLASS h1;
|
||||
HeadlessHost h2;
|
||||
if (typeid(h1) != typeid(h2))
|
||||
{
|
||||
fprintf(stderr, " --graphics use the full gpu backend (slower)\n");
|
||||
fprintf(stderr, " --screenshot=FILE compare against a screenshot\n");
|
||||
}
|
||||
|
||||
fprintf(stderr, " -i use the interpreter\n");
|
||||
fprintf(stderr, " -f use the fast interpreter\n");
|
||||
fprintf(stderr, " -j use jit (overrides -f)\n");
|
||||
fprintf(stderr, " -j use jit (default)\n");
|
||||
fprintf(stderr, " -c, --compare compare with output in file.expected\n");
|
||||
fprintf(stderr, "\nSee headless.txt for details.\n");
|
||||
}
|
||||
@@ -77,6 +82,7 @@ int main(int argc, const char* argv[])
|
||||
|
||||
const char *bootFilename = 0;
|
||||
const char *mountIso = 0;
|
||||
const char *screenshotFilename = 0;
|
||||
bool readMount = false;
|
||||
|
||||
for (int i = 1; i < argc; i++)
|
||||
@@ -91,6 +97,8 @@ int main(int argc, const char* argv[])
|
||||
readMount = true;
|
||||
else if (!strcmp(argv[i], "-l") || !strcmp(argv[i], "--log"))
|
||||
fullLog = true;
|
||||
else if (!strcmp(argv[i], "-i"))
|
||||
useJit = false;
|
||||
else if (!strcmp(argv[i], "-j"))
|
||||
useJit = true;
|
||||
else if (!strcmp(argv[i], "-f"))
|
||||
@@ -99,6 +107,8 @@ int main(int argc, const char* argv[])
|
||||
autoCompare = true;
|
||||
else if (!strcmp(argv[i], "--graphics"))
|
||||
useGraphics = true;
|
||||
else if (!strncmp(argv[i], "--screenshot=", strlen("--screenshot=")) && strlen(argv[i]) > strlen("--screenshot="))
|
||||
screenshotFilename = argv[i] + strlen("--screenshot=");
|
||||
else if (bootFilename == 0)
|
||||
bootFilename = argv[i];
|
||||
else
|
||||
@@ -146,7 +156,7 @@ int main(int argc, const char* argv[])
|
||||
coreParameter.fileToStart = bootFilename;
|
||||
coreParameter.mountIso = mountIso ? mountIso : "";
|
||||
coreParameter.startPaused = false;
|
||||
coreParameter.cpuCore = useJit ? CPU_JIT : (fastInterpreter ? CPU_FASTINTERPRETER : CPU_INTERPRETER);
|
||||
coreParameter.cpuCore = fastInterpreter ? CPU_FASTINTERPRETER : (useJit ? CPU_JIT : CPU_INTERPRETER);
|
||||
coreParameter.gpuCore = headlessHost->isGLWorking() ? GPU_GLES : GPU_NULL;
|
||||
coreParameter.enableSound = false;
|
||||
coreParameter.headLess = true;
|
||||
@@ -174,6 +184,9 @@ int main(int argc, const char* argv[])
|
||||
|
||||
host->BootDone();
|
||||
|
||||
if (screenshotFilename != 0)
|
||||
headlessHost->SetComparisonScreenshot(screenshotFilename);
|
||||
|
||||
coreState = CORE_RUNNING;
|
||||
while (coreState == CORE_RUNNING)
|
||||
{
|
||||
@@ -195,17 +208,7 @@ int main(int argc, const char* argv[])
|
||||
headlessHost = NULL;
|
||||
|
||||
if (autoCompare)
|
||||
{
|
||||
std::string expect_filename = std::string(bootFilename).substr(strlen(bootFilename - 4)) + ".expected";
|
||||
if (File::Exists(expect_filename))
|
||||
{
|
||||
// TODO: Do the compare here
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Expectation file %s not found", expect_filename.c_str());
|
||||
}
|
||||
}
|
||||
CompareOutput(bootFilename);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -145,6 +145,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\native\ext\glew\glew.c" />
|
||||
<ClCompile Include="Compare.cpp" />
|
||||
<ClCompile Include="Headless.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
||||
@@ -177,6 +178,7 @@
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Compare.h" />
|
||||
<ClInclude Include="StubHost.h" />
|
||||
<ClInclude Include="WindowsHeadlessHost.h" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<ClCompile Include="Headless.cpp" />
|
||||
<ClCompile Include="..\native\ext\glew\glew.c" />
|
||||
<ClCompile Include="WindowsHeadlessHost.cpp" />
|
||||
<ClCompile Include="Compare.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="headless.txt" />
|
||||
@@ -11,5 +12,6 @@
|
||||
<ItemGroup>
|
||||
<ClInclude Include="StubHost.h" />
|
||||
<ClInclude Include="WindowsHeadlessHost.h" />
|
||||
<ClInclude Include="Compare.h" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
virtual bool AttemptLoadSymbolMap() {return false;}
|
||||
|
||||
virtual void SendDebugOutput(const std::string &output) { printf("%s", output.c_str()); }
|
||||
virtual void SetComparisonScreenshot(const std::string &filename) {}
|
||||
|
||||
virtual bool isGLWorking() { return false; }
|
||||
};
|
||||
@@ -16,6 +16,7 @@
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "WindowsHeadlessHost.h"
|
||||
#include "Compare.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
@@ -89,6 +90,54 @@ void WindowsHeadlessHost::SendDebugOutput(const std::string &output)
|
||||
OutputDebugString(output.c_str());
|
||||
}
|
||||
|
||||
void WindowsHeadlessHost::SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h)
|
||||
{
|
||||
// We ignore the current framebuffer parameters and just grab the full screen.
|
||||
const static int FRAME_WIDTH = 512;
|
||||
const static int FRAME_HEIGHT = 272;
|
||||
u8 *pixels = new u8[FRAME_WIDTH * FRAME_HEIGHT * 4];
|
||||
|
||||
// TODO: Maybe this code should be moved into GLES_GPU.
|
||||
glReadBuffer(GL_FRONT);
|
||||
glReadPixels(0, 0, FRAME_WIDTH, FRAME_HEIGHT, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
std::string error;
|
||||
double errors = CompareScreenshot(pixels, FRAME_WIDTH, FRAME_HEIGHT, FRAME_WIDTH, comparisonScreenshot, error);
|
||||
if (errors < 0)
|
||||
fprintf_s(out, "%s\n", error.c_str());
|
||||
|
||||
if (errors > 0)
|
||||
{
|
||||
fprintf_s(out, "Screenshot error: %f%%\n", errors * 100.0f);
|
||||
|
||||
// Lazy, just read in the original header to output the failed screenshot.
|
||||
u8 header[14 + 40] = {0};
|
||||
FILE *bmp = fopen(comparisonScreenshot.c_str(), "rb");
|
||||
if (bmp)
|
||||
{
|
||||
fread(&header, sizeof(header), 1, bmp);
|
||||
fclose(bmp);
|
||||
}
|
||||
|
||||
FILE *saved = fopen("__testfailure.bmp", "wb");
|
||||
if (saved)
|
||||
{
|
||||
fwrite(&header, sizeof(header), 1, saved);
|
||||
fwrite(pixels, sizeof(u32), FRAME_WIDTH * FRAME_HEIGHT, saved);
|
||||
fclose(saved);
|
||||
|
||||
fprintf_s(out, "Actual output written to: __testfailure.bmp\n");
|
||||
}
|
||||
}
|
||||
|
||||
delete [] pixels;
|
||||
}
|
||||
|
||||
void WindowsHeadlessHost::SetComparisonScreenshot(const std::string &filename)
|
||||
{
|
||||
comparisonScreenshot = filename;
|
||||
}
|
||||
|
||||
void WindowsHeadlessHost::InitGL()
|
||||
{
|
||||
glOkay = false;
|
||||
|
||||
@@ -35,6 +35,8 @@ public:
|
||||
virtual bool isGLWorking() { return glOkay; }
|
||||
|
||||
virtual void SendDebugOutput(const std::string &output);
|
||||
virtual void SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h);
|
||||
virtual void SetComparisonScreenshot(const std::string &filename);
|
||||
|
||||
private:
|
||||
bool ResizeGL();
|
||||
@@ -45,4 +47,5 @@ private:
|
||||
HDC hDC;
|
||||
HGLRC hRC;
|
||||
FILE *out;
|
||||
std::string comparisonScreenshot;
|
||||
};
|
||||
+1
-1
Submodule native updated: f22ad17d40...3caced8524.
+1
-1
Submodule pspautotests updated: 4f047eb8c7...c4427bd55d.
@@ -109,6 +109,12 @@ tests_good = [
|
||||
"threads/semaphores/refer/refer",
|
||||
"threads/semaphores/signal/signal",
|
||||
"threads/semaphores/wait/wait",
|
||||
"threads/vpl/vpl",
|
||||
"threads/vpl/delete",
|
||||
"threads/vpl/free",
|
||||
"threads/vpl/priority",
|
||||
"threads/vpl/refer",
|
||||
"threads/vpl/try",
|
||||
"power/power",
|
||||
"umd/callbacks/umd",
|
||||
"umd/wait/wait",
|
||||
@@ -124,11 +130,13 @@ tests_next = [
|
||||
"threads/msgpipe/msgpipe",
|
||||
"threads/scheduling/scheduling",
|
||||
"threads/threads/threads",
|
||||
"threads/vpl/vpl",
|
||||
"threads/vtimers/vtimer",
|
||||
"threads/vpl/allocate",
|
||||
"threads/vpl/create",
|
||||
"threads/wakeup/wakeup",
|
||||
"gpu/simple/simple",
|
||||
"gpu/triangle/triangle",
|
||||
"gpu/commands/basic",
|
||||
"hle/check_not_used_uids",
|
||||
"font/fonttest",
|
||||
"io/cwd/cwd",
|
||||
@@ -222,6 +230,8 @@ def run_tests(test_list, args):
|
||||
|
||||
cmdline = [PPSSPP_EXE, elf_filename]
|
||||
cmdline.extend([i for i in args if i not in ['-v', '-g']])
|
||||
if os.path.exists(expected_filename + ".bmp"):
|
||||
cmdline.extend(["--screenshot=" + expected_filename + ".bmp", "--graphics"])
|
||||
|
||||
c = Command(cmdline)
|
||||
c.run(TIMEOUT)
|
||||
@@ -231,6 +241,7 @@ def run_tests(test_list, args):
|
||||
if c.timeout:
|
||||
print(output)
|
||||
print("Test exceded limit of %d seconds." % TIMEOUT)
|
||||
tests_failed.append(test)
|
||||
tcprint("##teamcity[testFailed name='%s' message='Test timeout']" % test)
|
||||
tcprint("##teamcity[testFinished name='%s']" % test)
|
||||
continue
|
||||
|
||||
Reference in new issue
Block a user