Merge remote-tracking branch 'origin/master' into pmp_video_branch

This commit is contained in:
kaienfr 2014-04-07 19:36:57 +02:00
commit 99cf2654b7
32 changed files with 314 additions and 182 deletions

View File

@ -127,6 +127,12 @@ public:
log_[type]->SetLevel(level);
}
void SetAllLogLevels(LogTypes::LOG_LEVELS level) {
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) {
log_[i]->SetLevel(level);
}
}
void SetEnable(LogTypes::LOG_TYPE type, bool enable) {
log_[type]->SetEnable(enable);
}

View File

@ -61,7 +61,8 @@ public:
SCE_UTILITY_STATUS_INITIALIZE = 1,
SCE_UTILITY_STATUS_RUNNING = 2,
SCE_UTILITY_STATUS_FINISHED = 3,
SCE_UTILITY_STATUS_SHUTDOWN = 4
SCE_UTILITY_STATUS_SHUTDOWN = 4,
SCE_UTILITY_STATUS_SCREENSHOT_UNKNOWN = 5,
};
enum DialogStockButton

View File

@ -40,6 +40,10 @@ int PSPPlaceholderDialog::Update(int animSpeed)
}
else if (status == SCE_UTILITY_STATUS_RUNNING)
{
//Check with JPCSPTrace log of Dream Club Portable
//But break Project Divx extand and Kenka Banchou Bros when take screenshot
//They are not call sceUtilityScreenshotContStart;
//status = SCE_UTILITY_STATUS_SCREENSHOT_UNKNOWN;
status = SCE_UTILITY_STATUS_FINISHED;
}
else if (status == SCE_UTILITY_STATUS_FINISHED)
@ -48,3 +52,16 @@ int PSPPlaceholderDialog::Update(int animSpeed)
}
return 0;
}
int PSPPlaceholderDialog::ContStart()
{
// base on JPCSP http://code.google.com/p/jpcsp/source/detail?r=3381
// be initialized with sceUtilityScreenshotInitStart and the startupType
// parameter has to be PSP_UTILITY_SCREENSHOT_TYPE_CONT_AUTO, otherwise, an
// error is returned.
if (status != SCE_UTILITY_STATUS_SCREENSHOT_UNKNOWN)
return SCE_ERROR_UTILITY_INVALID_STATUS;
// Check with JPCSPTrace log of Dream Club Portable
status = SCE_UTILITY_STATUS_FINISHED;
return 0;
}

View File

@ -26,5 +26,7 @@ public:
virtual int Init();
virtual int Update(int animSpeed);
virtual int ContStart();
};

View File

@ -37,8 +37,6 @@
#define CTRL_MODE_DIGITAL 0
#define CTRL_MODE_ANALOG 1
const int PSP_CTRL_ERROR_INVALID_IDLE_PTR = 0x80000023;
const u32 NUM_CTRL_BUFFERS = 64;
enum {
@ -433,9 +431,9 @@ int sceCtrlGetIdleCancelThreshold(u32 idleResetPtr, u32 idleBackPtr)
DEBUG_LOG(SCECTRL, "sceCtrlSetIdleCancelThreshold(%08x, %08x)", idleResetPtr, idleBackPtr);
if (idleResetPtr && !Memory::IsValidAddress(idleResetPtr))
return PSP_CTRL_ERROR_INVALID_IDLE_PTR;
return SCE_KERNEL_ERROR_PRIV_REQUIRED;
if (idleBackPtr && !Memory::IsValidAddress(idleBackPtr))
return PSP_CTRL_ERROR_INVALID_IDLE_PTR;
return SCE_KERNEL_ERROR_PRIV_REQUIRED;
if (idleResetPtr)
Memory::Write_U32(ctrlIdleReset, idleResetPtr);

View File

@ -75,9 +75,9 @@ u32 sceDmacMemcpy(u32 dst, u32 src, u32 size) {
ERROR_LOG(HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i): invalid address", dst, src, size);
return SCE_KERNEL_ERROR_INVALID_POINTER;
}
if (dst + size >= 0x80000000 || src + size >= 0x80000000) {
if (dst + size >= 0x80000000 || src + size >= 0x80000000 || size >= 0x80000000) {
ERROR_LOG(HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i): illegal size", dst, src, size);
return 0x80000023;
return SCE_KERNEL_ERROR_PRIV_REQUIRED;
}
if (dmacMemcpyDeadline > CoreTiming::GetTicks()) {
@ -100,9 +100,9 @@ u32 sceDmacTryMemcpy(u32 dst, u32 src, u32 size) {
ERROR_LOG(HLE, "sceDmacTryMemcpy(dest=%08x, src=%08x, size=%i): invalid address", dst, src, size);
return SCE_KERNEL_ERROR_INVALID_POINTER;
}
if (dst + size >= 0x80000000 || src + size >= 0x80000000) {
if (dst + size >= 0x80000000 || src + size >= 0x80000000 || size >= 0x80000000) {
ERROR_LOG(HLE, "sceDmacTryMemcpy(dest=%08x, src=%08x, size=%i): illegal size", dst, src, size);
return 0x80000023;
return SCE_KERNEL_ERROR_PRIV_REQUIRED;
}
if (dmacMemcpyDeadline > CoreTiming::GetTicks()) {

View File

@ -301,9 +301,10 @@ bool __GeTriggerWait(WaitType waitType, SceUID waitId, WaitingThreadList &waitin
bool __GeTriggerWait(GPUSyncType type, SceUID waitId)
{
if (type == GPU_SYNC_DRAW)
// We check for the old type for old savestate compatibility.
if (type == GPU_SYNC_DRAW || type == WAITTYPE_GEDRAWSYNC)
return __GeTriggerWait(WAITTYPE_GEDRAWSYNC, waitId, drawWaitingThreads);
else if (type == GPU_SYNC_LIST)
else if (type == GPU_SYNC_LIST || type == WAITTYPE_GELISTSYNC)
return __GeTriggerWait(WAITTYPE_GELISTSYNC, waitId, listWaitingThreads[waitId]);
else
ERROR_LOG_REPORT(SCEGE, "__GeTriggerWait: bad wait type");
@ -420,7 +421,7 @@ int sceGeBreak(u32 mode, u32 unknownPtr)
if ((int)unknownPtr < 0 || (int)unknownPtr + 16 < 0)
{
WARN_LOG_REPORT(SCEGE, "sceGeBreak(mode=%d, unknown=%08x): invalid ptr", mode, unknownPtr);
return 0x80000023;
return SCE_KERNEL_ERROR_PRIV_REQUIRED;
}
else if (unknownPtr != 0)
WARN_LOG_REPORT(SCEGE, "sceGeBreak(mode=%d, unknown=%08x): unknown ptr (%s)", mode, unknownPtr, Memory::IsValidAddress(unknownPtr) ? "valid" : "invalid");

View File

@ -30,6 +30,7 @@ enum
SCE_KERNEL_ERROR_ALREADY = 0x80000020,
SCE_KERNEL_ERROR_BUSY = 0x80000021,
SCE_KERNEL_ERROR_OUT_OF_MEMORY = 0x80000022,
SCE_KERNEL_ERROR_PRIV_REQUIRED = 0x80000023,
SCE_KERNEL_ERROR_INVALID_ID = 0x80000100,
SCE_KERNEL_ERROR_INVALID_NAME = 0x80000101,
SCE_KERNEL_ERROR_INVALID_INDEX = 0x80000102,
@ -561,4 +562,4 @@ void Register_ThreadManForKernel();
void Register_LoadExecForUser();
void Register_LoadExecForKernel();
void Register_SysMemForKernel();
void Register_UtilsForKernel();
void Register_UtilsForKernel();

View File

@ -40,8 +40,6 @@ extern "C" {
}
#endif
static const int MP3_BITRATES[] = {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320};
struct Mp3Context;
int __Mp3InitContext(Mp3Context *ctx);
@ -150,7 +148,6 @@ void __Mp3DoState(PointerWrap &p) {
p.Do(mp3Map);
}
/* MP3 */
int sceMp3Decode(u32 mp3, u32 outPcmPtr) {
DEBUG_LOG(ME, "sceMp3Decode(%08x,%08x)", mp3, outPcmPtr);
@ -245,8 +242,8 @@ int sceMp3Decode(u32 mp3, u32 outPcmPtr) {
fclose(file);
}
#endif
// 2 bytes per channel and we always two channels per mp3 so it is 2 * 2
ctx->mp3SumDecodedSamples += bytesdecoded / 2 * 2;
// 2 bytes per channel and we have frame.channels in mp3 source
ctx->mp3SumDecodedSamples += bytesdecoded / (2 * frame.channels);
return bytesdecoded;
}
@ -367,12 +364,14 @@ int sceMp3TermResource() {
int __Mp3InitContext(Mp3Context *ctx) {
#ifdef USE_FFMPEG
InitFFmpeg();
u8 *avio_buffer = static_cast<u8*>(av_malloc(ctx->mp3BufSize));
ctx->avio_context = avio_alloc_context(avio_buffer, ctx->mp3BufSize, 0, ctx, readFunc, NULL, NULL);
u8 *avio_buffer = (u8*)(av_malloc(ctx->mp3BufSize));
ctx->avio_context = avio_alloc_context(avio_buffer, ctx->mp3BufSize, 0, (void*)ctx, readFunc, NULL, NULL);
ctx->avformat_context = avformat_alloc_context();
ctx->avformat_context->pb = ctx->avio_context;
int ret;
// Load audio buffer
if ((ret = avformat_open_input(&ctx->avformat_context, NULL, av_find_input_format("mp3"), NULL)) < 0) {
ERROR_LOG(ME, "avformat_open_input: Cannot open input %d", ret);
return -1;
@ -384,17 +383,20 @@ int __Mp3InitContext(Mp3Context *ctx) {
}
AVCodec *dec;
/* select the audio stream */
// Select the audio stream
ret = av_find_best_stream(ctx->avformat_context, AVMEDIA_TYPE_AUDIO, -1, -1, &dec, 0);
if (ret < 0) {
ERROR_LOG(ME, "av_find_best_stream: Cannot find an audio stream in the input file %d", ret);
if (ret == AVERROR_DECODER_NOT_FOUND) {
ERROR_LOG(HLE, "av_find_best_stream: No appropriate decoder found");
} else {
ERROR_LOG(HLE, "av_find_best_stream: Cannot find an audio stream in the input file %d", ret);
}
return -1;
}
ctx->audio_stream_index = ret;
ctx->decoder_context = ctx->avformat_context->streams[ctx->audio_stream_index]->codec;
/* init the audio decoder */
// Init the audio decoder
if ((ret = avcodec_open2(ctx->decoder_context, dec, NULL)) < 0) {
ERROR_LOG(ME, "avcodec_open2: Cannot open audio decoder %d", ret);
return -1;
@ -433,12 +435,7 @@ int sceMp3Init(u32 mp3) {
}
// Read in the header and swap the endian
int header = Memory::Read_U32(ctx->mp3Buf);
header = (header >> 24) |
((header<<8) & 0x00FF0000) |
((header>>8) & 0x0000FF00) |
(header << 24);
int header = bswap32(Memory::Read_U32(ctx->mp3Buf));
ctx->mp3Version = ((header >> 19) & 0x3);
#ifdef USE_FFMPEG
@ -451,7 +448,8 @@ int sceMp3Init(u32 mp3) {
ctx->mp3SamplingRate = ctx->decoder_context->sample_rate;
ctx->mp3Channels = ctx->decoder_context->channels;
ctx->mp3Bitrate = ctx->decoder_context->bit_rate / 1000;
INFO_LOG(ME, "sceMp3Init(): channels=%i, samplerate=%ikHz, bitrate=%ikbps", ctx->mp3Channels, ctx->mp3SamplingRate, ctx->mp3Bitrate);
av_dump_format(ctx->avformat_context, 0, "mp3", 0);
#endif
@ -602,7 +600,6 @@ int sceMp3ReleaseMp3Handle(u32 mp3) {
}
mp3Map.erase(mp3Map.find(mp3));
delete ctx;
return 0;

View File

@ -36,7 +36,6 @@ struct VolatileWaitingThread {
const int PSP_POWER_ERROR_TAKEN_SLOT = 0x80000020;
const int PSP_POWER_ERROR_SLOTS_FULL = 0x80000022;
const int PSP_POWER_ERROR_PRIVATE_SLOT = 0x80000023;
const int PSP_POWER_ERROR_EMPTY_SLOT = 0x80000025;
const int PSP_POWER_ERROR_INVALID_CB = 0x80000100;
const int PSP_POWER_ERROR_INVALID_SLOT = 0x80000102;
@ -47,7 +46,10 @@ const int PSP_POWER_CB_BATTERY_FULL = 0x00000064;
const int POWER_CB_AUTO = -1;
// These are the callback slots for user mode applications.
const int numberOfCBPowerSlots = 16;
// These are the callback slots for kernel mode applications.
const int numberOfCBPowerSlotsPrivate = 32;
static bool volatileMemLocked;
@ -132,7 +134,7 @@ int scePowerRegisterCallback(int slot, int cbId) {
return PSP_POWER_ERROR_INVALID_SLOT;
}
if (slot >= numberOfCBPowerSlots) {
return PSP_POWER_ERROR_PRIVATE_SLOT;
return SCE_KERNEL_ERROR_PRIV_REQUIRED;
}
// TODO: If cbId is invalid return PSP_POWER_ERROR_INVALID_CB.
if (cbId == 0) {
@ -173,7 +175,7 @@ int scePowerUnregisterCallback(int slotId) {
return PSP_POWER_ERROR_INVALID_SLOT;
}
if (slotId >= numberOfCBPowerSlots) {
return PSP_POWER_ERROR_PRIVATE_SLOT;
return SCE_KERNEL_ERROR_PRIV_REQUIRED;
}
if (powerCbSlots[slotId] != 0) {

View File

@ -424,18 +424,18 @@ int sceUtilityNetconfGetStatus()
//TODO: Implement all sceUtilityScreenshot* for real, it doesn't seem to be complex
//but it requires more investigation
u32 sceUtilityScreenshotInitStart(u32 unknown1, u32 unknown2, u32 unknown3, u32 unknown4, u32 unknown5, u32 unknown6)
u32 sceUtilityScreenshotInitStart(u32 paramAddr)
{
if (currentDialogActive && currentDialogType != UTILITY_DIALOG_SCREENSHOT)
{
WARN_LOG(SCEUTILITY, "sceUtilityScreenshotInitStart(%x, %x, %x, %x, %x, %x): wrong dialog type", unknown1, unknown2, unknown3, unknown4, unknown5, unknown6);
WARN_LOG(SCEUTILITY, "sceUtilityScreenshotInitStart(%08x): wrong dialog type", paramAddr);
return SCE_ERROR_UTILITY_WRONG_TYPE;
}
currentDialogType = UTILITY_DIALOG_SCREENSHOT;
currentDialogActive = true;
u32 retval = screenshotDialog.Init();
WARN_LOG_REPORT(SCEUTILITY, "UNIMPL %08x=sceUtilityScreenshotInitStart(%x, %x, %x, %x, %x, %x)", retval, unknown1, unknown2, unknown3, unknown4, unknown5, unknown6);
WARN_LOG_REPORT(SCEUTILITY, "%08x=sceUtilityScreenshotInitStart(%08x)", retval, paramAddr);
return retval;
}
@ -448,7 +448,7 @@ u32 sceUtilityScreenshotShutdownStart()
}
currentDialogActive = false;
int ret = screenshotDialog.Shutdown();
WARN_LOG(SCEUTILITY, "UNTESTED %08x=sceUtilityScreenshotShutdownStart()",ret);
WARN_LOG(SCEUTILITY, "%08x=sceUtilityScreenshotShutdownStart()",ret);
return ret;
}
@ -460,7 +460,7 @@ u32 sceUtilityScreenshotUpdate(u32 animSpeed)
return SCE_ERROR_UTILITY_WRONG_TYPE;
}
int ret = screenshotDialog.Update(animSpeed);
ERROR_LOG(SCEUTILITY, "UNIMPL %08x=sceUtilityScreenshotUpdate(%d)",ret,animSpeed);
WARN_LOG(SCEUTILITY, "%08x=sceUtilityScreenshotUpdate(%d)", ret, animSpeed);
return ret;
}
@ -473,10 +473,22 @@ int sceUtilityScreenshotGetStatus()
}
u32 retval = screenshotDialog.GetStatus();
WARN_LOG(SCEUTILITY, "UNIMPL %08x=sceUtilityScreenshotGetStatus()", retval);
WARN_LOG(SCEUTILITY, "%08x=sceUtilityScreenshotGetStatus()", retval);
return retval;
}
u32 sceUtilityScreenshotContStart(u32 paramAddr)
{
if (currentDialogType != UTILITY_DIALOG_SCREENSHOT)
{
WARN_LOG(SCEUTILITY, "sceUtilityScreenshotUpdate(): wrong dialog type");
return SCE_ERROR_UTILITY_WRONG_TYPE;
}
u32 ret = screenshotDialog.ContStart();
WARN_LOG(SCEUTILITY, "%08x=sceUtilityScreenshotContStart(%08x)", ret, paramAddr);
return ret;
}
int sceUtilityGamedataInstallInitStart(u32 paramsAddr)
{
if (currentDialogActive && currentDialogType != UTILITY_DIALOG_GAMEDATAINSTALL)
@ -762,11 +774,11 @@ const HLEFunction sceUtility[] =
{0x2a2b3de0, &WrapU_U<sceUtilityLoadModule>, "sceUtilityLoadModule"},
{0xe49bfe92, &WrapU_U<sceUtilityUnloadModule>, "sceUtilityUnloadModule"},
{0x0251B134, &WrapU_UUUUUU<sceUtilityScreenshotInitStart>, "sceUtilityScreenshotInitStart"},
{0x0251B134, &WrapU_U<sceUtilityScreenshotInitStart>, "sceUtilityScreenshotInitStart"},
{0xF9E0008C, &WrapU_V<sceUtilityScreenshotShutdownStart>, "sceUtilityScreenshotShutdownStart"},
{0xAB083EA9, &WrapU_U<sceUtilityScreenshotUpdate>, "sceUtilityScreenshotUpdate"},
{0xD81957B7, &WrapI_V<sceUtilityScreenshotGetStatus>, "sceUtilityScreenshotGetStatus"},
{0x86A03A27, 0, "sceUtilityScreenshotContStart"},
{0x86A03A27, &WrapU_U<sceUtilityScreenshotContStart>, "sceUtilityScreenshotContStart"},
{0x0D5BC6D2, 0, "sceUtilityLoadUsbModule"},
{0xF64910F0, 0, "sceUtilityUnloadUsbModule"},

View File

@ -313,8 +313,8 @@ void MediaEngine::closeContext()
m_pCodecCtxs.clear();
if (m_pFormatCtx)
avformat_close_input(&m_pFormatCtx);
if (m_sws_ctx != NULL)
sws_freeContext(m_sws_ctx);
sws_freeContext(m_sws_ctx);
m_sws_ctx = NULL;
m_pIOContext = 0;
#endif
m_buffer = 0;
@ -414,9 +414,7 @@ bool MediaEngine::setVideoDim(int width, int height)
// Allocate video frame
m_pFrame = av_frame_alloc();
if (m_sws_ctx != NULL) {
sws_freeContext(m_sws_ctx);
}
sws_freeContext(m_sws_ctx);
m_sws_ctx = NULL;
m_sws_fmt = -1;
updateSwsFormat(GE_CMODE_32BIT_ABGR8888);
@ -475,7 +473,7 @@ bool MediaEngine::stepVideo(int videoPixelMode) {
// Update the linesize for the new format too. We started with the largest size, so it should fit.
m_pFrameRGB->linesize[0] = getPixelFormatBytes(videoPixelMode) * m_desWidth;
AVPacket packet;
AVPacket packet = {0};
av_init_packet(&packet);
int frameFinished;
bool bGetFrame = false;

View File

@ -15,6 +15,7 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include <cstring>
#include "base/logging.h"
#include "Common/CPUDetect.h"
#include "Core/MIPS/ARM/ArmRegCacheFPU.h"
@ -22,7 +23,7 @@
using namespace ArmGen;
ArmRegCacheFPU::ArmRegCacheFPU(MIPSState *mips) : mips_(mips), vr(mr + 32) {
ArmRegCacheFPU::ArmRegCacheFPU(MIPSState *mips) : mips_(mips), vr(mr + 32), initialReady(false) {
if (cpu_info.bNEON) {
numARMFpuReg_ = 32;
} else {
@ -35,22 +36,33 @@ void ArmRegCacheFPU::Init(ARMXEmitter *emitter) {
}
void ArmRegCacheFPU::Start(MIPSAnalyst::AnalysisResults &stats) {
if (!initialReady) {
SetupInitialRegs();
initialReady = true;
}
memcpy(ar, arInitial, sizeof(ar));
memcpy(mr, mrInitial, sizeof(mr));
pendingFlush = false;
}
void ArmRegCacheFPU::SetupInitialRegs() {
for (int i = 0; i < numARMFpuReg_; i++) {
ar[i].mipsReg = -1;
ar[i].isDirty = false;
arInitial[i].mipsReg = -1;
arInitial[i].isDirty = false;
}
for (int i = 0; i < NUM_MIPSFPUREG; i++) {
mr[i].loc = ML_MEM;
mr[i].reg = INVALID_REG;
mr[i].spillLock = false;
mr[i].tempLock = false;
mrInitial[i].loc = ML_MEM;
mrInitial[i].reg = INVALID_REG;
mrInitial[i].spillLock = false;
mrInitial[i].tempLock = false;
}
}
static const ARMReg *GetMIPSAllocationOrder(int &count) {
// We reserve S0-S1 as scratch. Can afford two registers. Maybe even four, which could simplify some things.
static const ARMReg allocationOrder[] = {
S2, S3,
S2, S3,
S4, S5, S6, S7,
S8, S9, S10, S11,
S12, S13, S14, S15
@ -86,6 +98,7 @@ static const ARMReg *GetMIPSAllocationOrder(int &count) {
}
ARMReg ArmRegCacheFPU::MapReg(MIPSReg mipsReg, int mapFlags) {
pendingFlush = true;
// Let's see if it's already mapped. If so we just need to update the dirty flag.
// We don't need to check for ML_NOINIT because we assume that anyone who maps
// with that flag immediately writes a "known" value to the register.
@ -329,6 +342,11 @@ int ArmRegCacheFPU::FlushGetSequential(int a, int maxArmReg) {
}
void ArmRegCacheFPU::FlushAll() {
if (!pendingFlush) {
// Nothing allocated. FPU regs are not nearly as common as GPR.
return;
}
// Discard temps!
for (int i = TEMP0; i < TEMP0 + NUM_TEMPS; i++) {
DiscardR(i);
@ -393,6 +411,7 @@ void ArmRegCacheFPU::FlushAll() {
ERROR_LOG(JIT, "Flush fail: ar[%i].mipsReg=%i", i, ar[i].mipsReg);
}
}
pendingFlush = false;
}
void ArmRegCacheFPU::DiscardR(MIPSReg r) {
@ -432,6 +451,7 @@ bool ArmRegCacheFPU::IsTempX(ARMReg r) const {
}
int ArmRegCacheFPU::GetTempR() {
pendingFlush = true;
for (int r = TEMP0; r < TEMP0 + NUM_TEMPS; ++r) {
if (mr[r].loc == ML_MEM && !mr[r].tempLock) {
mr[r].tempLock = true;

View File

@ -122,6 +122,8 @@ public:
int GetNumARMFPURegs();
private:
void SetupInitialRegs();
MIPSState *mips_;
ARMXEmitter *emit_;
u32 compilerPC_;
@ -136,4 +138,9 @@ private:
FPURegARM ar[MAX_ARMFPUREG];
FPURegMIPS mr[NUM_MIPSFPUREG];
FPURegMIPS *vr;
bool pendingFlush;
bool initialReady;
FPURegARM arInitial[MAX_ARMFPUREG];
FPURegMIPS mrInitial[NUM_MIPSFPUREG];
};

View File

@ -40,6 +40,7 @@ void FPURegCache::Start(MIPSState *mips, MIPSAnalyst::AnalysisResults &stats) {
memcpy(xregs, xregsInitial, sizeof(xregs));
memcpy(regs, regsInitial, sizeof(regs));
pendingFlush = false;
}
void FPURegCache::SetupInitialRegs() {
@ -115,6 +116,7 @@ void FPURegCache::ReleaseSpillLocks() {
}
void FPURegCache::MapReg(const int i, bool doLoad, bool makeDirty) {
pendingFlush = true;
_assert_msg_(JIT, !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.
@ -176,6 +178,7 @@ bool FPURegCache::IsTempX(X64Reg xr) {
}
int FPURegCache::GetTempR() {
pendingFlush = true;
for (int r = TEMP0; r < TEMP0 + NUM_TEMPS; ++r) {
if (!regs[r].away && !regs[r].tempLocked) {
regs[r].tempLocked = true;
@ -188,6 +191,9 @@ int FPURegCache::GetTempR() {
}
void FPURegCache::Flush() {
if (!pendingFlush) {
return;
}
for (int i = 0; i < NUM_MIPS_FPRS; i++) {
if (regs[i].locked) {
PanicAlert("Somebody forgot to unlock MIPS reg %i.", i);
@ -204,6 +210,7 @@ void FPURegCache::Flush() {
}
}
}
pendingFlush = false;
}
OpArg FPURegCache::GetDefaultLocation(int reg) const {
@ -244,6 +251,7 @@ const int *FPURegCache::GetAllocationOrder(int &count) {
}
X64Reg FPURegCache::GetFreeXReg() {
pendingFlush = true;
int aCount;
const int *aOrder = GetAllocationOrder(aCount);
for (int i = 0; i < aCount; i++) {
@ -284,4 +292,5 @@ void FPURegCache::GetState(FPURegCacheState &state) const {
void FPURegCache::RestoreState(const FPURegCacheState state) {
memcpy(regs, state.regs, sizeof(regs));
memcpy(xregs, state.xregs, sizeof(xregs));
pendingFlush = true;
}

View File

@ -163,6 +163,7 @@ private:
X64CachedFPReg xregs[NUM_X_FPREGS];
MIPSCachedFPReg *vregs;
bool pendingFlush;
bool initialReady;
MIPSCachedFPReg regsInitial[NUM_MIPS_FPRS];
X64CachedFPReg xregsInitial[NUM_X_FPREGS];

View File

@ -660,15 +660,7 @@ void FramebufferManager::DestroyFramebuf(VirtualFramebuffer *v) {
delete v;
}
void FramebufferManager::SetRenderFrameBuffer() {
if (!gstate_c.framebufChanged && currentRenderVfb_) {
currentRenderVfb_->last_frame_render = gpuStats.numFlips;
currentRenderVfb_->dirtyAfterDisplay = true;
if (!gstate_c.skipDrawReason)
currentRenderVfb_->reallyDirtyAfterDisplay = true;
return;
}
void FramebufferManager::DoSetRenderFrameBuffer() {
/*
if (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE && currentRenderVfb_) {
// Hack is enabled, and there was a previous framebuffer.

View File

@ -135,7 +135,18 @@ public:
void Resized();
void DeviceLost();
void CopyDisplayToOutput();
void SetRenderFrameBuffer(); // Uses parameters computed from gstate
void DoSetRenderFrameBuffer(); // Uses parameters computed from gstate
void SetRenderFrameBuffer() {
// Inlining this part since it's so frequent.
if (!gstate_c.framebufChanged && currentRenderVfb_) {
currentRenderVfb_->last_frame_render = gpuStats.numFlips;
currentRenderVfb_->dirtyAfterDisplay = true;
if (!gstate_c.skipDrawReason)
currentRenderVfb_->reallyDirtyAfterDisplay = true;
return;
}
DoSetRenderFrameBuffer();
}
void UpdateFromMemory(u32 addr, int size, bool safe);
void SetLineWidth();

View File

@ -1138,6 +1138,31 @@ void TextureCache::SetTexture(bool force) {
// If GLES3 is available, we can preallocate the storage, which makes texture loading more efficient.
GLenum dstFmt = GetDestFormat(format, gstate.getClutPaletteFormat());
int scaleFactor;
// Auto-texture scale upto 5x rendering resolution
if (g_Config.iTexScalingLevel == 0) {
scaleFactor = g_Config.iInternalResolution;
if (scaleFactor == 0) {
scaleFactor = (PSP_CoreParameter().renderWidth + 479) / 480;
}
#ifndef MOBILE_DEVICE
scaleFactor = std::min(gl_extensions.OES_texture_npot ? 5 : 4, scaleFactor);
if (!gl_extensions.OES_texture_npot && scaleFactor == 3) {
scaleFactor = 2;
}
#else
scaleFactor = std::min(gl_extensions.OES_texture_npot ? 3 : 2, scaleFactor);
#endif
} else {
scaleFactor = g_Config.iTexScalingLevel;
}
// Don't scale the PPGe texture.
if (entry->addr > 0x05000000 && entry->addr < 0x08800000)
scaleFactor = 1;
#if defined(MAY_HAVE_GLES3)
if (gl_extensions.GLES3 && maxLevel > 0) {
// glTexStorage2D requires the use of sized formats.
@ -1152,7 +1177,7 @@ void TextureCache::SetTexture(bool force) {
break;
}
// TODO: This may cause bugs, since it hard-sets the texture w/h, and we might try to reuse it later with a different size.
glTexStorage2D(GL_TEXTURE_2D, maxLevel + 1, storageFmt, w, h);
glTexStorage2D(GL_TEXTURE_2D, maxLevel + 1, storageFmt, w * scaleFactor, h * scaleFactor);
// Make sure we don't use glTexImage2D after glTexStorage2D.
replaceImages = true;
}
@ -1164,7 +1189,8 @@ void TextureCache::SetTexture(bool force) {
// be as good quality as the game's own (might even be better in some cases though).
// Always load base level texture here
LoadTextureLevel(*entry, 0, replaceImages, dstFmt);
LoadTextureLevel(*entry, 0, replaceImages, scaleFactor, dstFmt);
// Mipmapping only enable when texture scaling disable
if (maxLevel > 0 && g_Config.iTexScalingLevel == 1) {
@ -1173,22 +1199,22 @@ void TextureCache::SetTexture(bool force) {
glGenerateMipmap(GL_TEXTURE_2D);
} else {
for (int i = 1; i <= maxLevel; i++) {
LoadTextureLevel(*entry, i, replaceImages, dstFmt);
LoadTextureLevel(*entry, i, replaceImages, scaleFactor, dstFmt);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, maxLevel);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, (float)maxLevel);
}
#else
glGenerateMipmap(GL_TEXTURE_2D);
glGenerateMipmap(GL_TEXTURE_2D);
#endif
} else {
#ifndef USING_GLES2
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0);
#elif defined(MAY_HAVE_GLES3)
if (gl_extensions.GLES3) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
}
if (gl_extensions.GLES3) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
}
#endif
}
@ -1518,7 +1544,7 @@ void TextureCache::CheckAlpha(TexCacheEntry &entry, u32 *pixelData, GLenum dstFm
entry.status |= TexCacheEntry::STATUS_ALPHA_FULL;
}
void TextureCache::LoadTextureLevel(TexCacheEntry &entry, int level, bool replaceImages, GLenum dstFmt) {
void TextureCache::LoadTextureLevel(TexCacheEntry &entry, int level, bool replaceImages, int scaleFactor, GLenum dstFmt) {
// TODO: only do this once
u32 texByteAlign = 1;
@ -1545,30 +1571,6 @@ void TextureCache::LoadTextureLevel(TexCacheEntry &entry, int level, bool replac
glPixelStorei(GL_UNPACK_ALIGNMENT, texByteAlign);
int scaleFactor;
// Auto-texture scale upto 5x rendering resolution
if (g_Config.iTexScalingLevel == 0) {
scaleFactor = g_Config.iInternalResolution;
if (scaleFactor == 0) {
scaleFactor = (PSP_CoreParameter().renderWidth + 479) / 480;
}
#ifndef MOBILE_DEVICE
scaleFactor = std::min(gl_extensions.OES_texture_npot ? 5 : 4, scaleFactor);
if (!gl_extensions.OES_texture_npot && scaleFactor == 3) {
scaleFactor = 2;
}
#else
scaleFactor = std::min(gl_extensions.OES_texture_npot ? 3 : 2, scaleFactor);
#endif
} else {
scaleFactor = g_Config.iTexScalingLevel;
}
// Don't scale the PPGe texture.
if (entry.addr > 0x05000000 && entry.addr < 0x08800000)
scaleFactor = 1;
u32 *pixelData = (u32 *)finalBuf;
if (scaleFactor > 1 && (entry.status & TexCacheEntry::STATUS_CHANGE_FREQUENT) == 0)
scaler.Scale(pixelData, dstFmt, w, h, scaleFactor);

View File

@ -123,7 +123,7 @@ private:
void *UnswizzleFromMem(const u8 *texptr, u32 bufw, u32 bytesPerPixel, u32 level);
void *ReadIndexedTex(int level, const u8 *texptr, int bytesPerIndex, GLuint dstFmt, int bufw);
void UpdateSamplingParams(TexCacheEntry &entry, bool force);
void LoadTextureLevel(TexCacheEntry &entry, int level, bool replaceImages, GLenum dstFmt);
void LoadTextureLevel(TexCacheEntry &entry, int level, bool replaceImages, int scaleFactor, GLenum dstFmt);
GLenum GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const;
void *DecodeTextureLevel(GETextureFormat format, GEPaletteFormat clutformat, int level, u32 &texByteAlign, GLenum dstFmt, int *bufw = 0);
void CheckAlpha(TexCacheEntry &entry, u32 *pixelData, GLenum dstFmt, int stride, int w, int h);

View File

@ -255,9 +255,13 @@ VertexDecoder *TransformDrawEngine::GetVertexDecoder(u32 vtype) {
}
void TransformDrawEngine::SetupVertexDecoder(u32 vertType) {
SetupVertexDecoderInternal(vertType);
}
inline void TransformDrawEngine::SetupVertexDecoderInternal(u32 vertType) {
// As the decoder depends on the UVGenMode when we use UV prescale, we simply mash it
// into the top of the verttype where there are unused bits.
u32 vertTypeID = (vertType & 0xFFFFFF) | (gstate.getUVGenMode() << 24);
const u32 vertTypeID = (vertType & 0xFFFFFF) | (gstate.getUVGenMode() << 24);
// If vtype has changed, setup the vertex decoder.
// TODO: Simply cache the setup decoders instead.
@ -267,34 +271,6 @@ void TransformDrawEngine::SetupVertexDecoder(u32 vertType) {
}
}
int TransformDrawEngine::EstimatePerVertexCost() {
// TODO: This is transform cost, also account for rasterization cost somehow... although it probably
// runs in parallel with transform.
// Also, this is all pure guesswork. If we can find a way to do measurements, that would be great.
// GTA wants a low value to run smooth, GoW wants a high value (otherwise it thinks things
// went too fast and starts doing all the work over again).
int cost = 20;
if (gstate.isLightingEnabled()) {
cost += 10;
}
for (int i = 0; i < 4; i++) {
if (gstate.isLightChanEnabled(i))
cost += 10;
}
if (gstate.getUVGenMode() != GE_TEXMAP_TEXTURE_COORDS) {
cost += 20;
}
if (dec_ && dec_->morphcount > 1) {
cost += 5 * dec_->morphcount;
}
return cost;
}
void TransformDrawEngine::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int *bytesRead) {
if (vertexCount == 0)
return; // we ignore zero-sized draw calls.
@ -308,7 +284,7 @@ void TransformDrawEngine::SubmitPrim(void *verts, void *inds, GEPrimitiveType pr
}
prevPrim_ = prim;
SetupVertexDecoder(vertType);
SetupVertexDecoderInternal(vertType);
dec_->IncrementStat(STAT_VERTSSUBMITTED, vertexCount);
@ -401,33 +377,45 @@ void TransformDrawEngine::DecodeVertsStep() {
// 1. Look ahead to find the max index, only looking as "matching" drawcalls.
// Expand the lower and upper bounds as we go.
int j = i + 1;
int lastMatch = i;
while (j < numDrawCalls) {
if (drawCalls[j].verts != dc.verts)
break;
if (uvScale && memcmp(&uvScale[j], &uvScale[i], sizeof(uvScale[0])) != 0)
break;
const int total = numDrawCalls;
if (uvScale) {
for (int j = i + 1; j < total; ++j) {
if (drawCalls[j].verts != dc.verts)
break;
if (memcmp(&uvScale[j], &uvScale[i], sizeof(uvScale[0])) != 0)
break;
indexLowerBound = std::min(indexLowerBound, (int)drawCalls[j].indexLowerBound);
indexUpperBound = std::max(indexUpperBound, (int)drawCalls[j].indexUpperBound);
lastMatch = j;
j++;
}
indexLowerBound = std::min(indexLowerBound, (int)drawCalls[j].indexLowerBound);
indexUpperBound = std::max(indexUpperBound, (int)drawCalls[j].indexUpperBound);
lastMatch = j;
}
} else {
for (int j = i + 1; j < total; ++j) {
if (drawCalls[j].verts != dc.verts)
break;
// 2. Loop through the drawcalls, translating indices as we go.
for (j = i; j <= lastMatch; j++) {
switch (indexType) {
case GE_VTYPE_IDX_8BIT >> GE_VTYPE_IDX_SHIFT:
indexGen.TranslatePrim(drawCalls[j].prim, drawCalls[j].vertexCount, (const u8 *)drawCalls[j].inds, indexLowerBound);
break;
case GE_VTYPE_IDX_16BIT >> GE_VTYPE_IDX_SHIFT:
indexGen.TranslatePrim(drawCalls[j].prim, drawCalls[j].vertexCount, (const u16 *)drawCalls[j].inds, indexLowerBound);
break;
indexLowerBound = std::min(indexLowerBound, (int)drawCalls[j].indexLowerBound);
indexUpperBound = std::max(indexUpperBound, (int)drawCalls[j].indexUpperBound);
lastMatch = j;
}
}
int vertexCount = indexUpperBound - indexLowerBound + 1;
// 2. Loop through the drawcalls, translating indices as we go.
switch (indexType) {
case GE_VTYPE_IDX_8BIT >> GE_VTYPE_IDX_SHIFT:
for (int j = i; j <= lastMatch; j++) {
indexGen.TranslatePrim(drawCalls[j].prim, drawCalls[j].vertexCount, (const u8 *)drawCalls[j].inds, indexLowerBound);
}
break;
case GE_VTYPE_IDX_16BIT >> GE_VTYPE_IDX_SHIFT:
for (int j = i; j <= lastMatch; j++) {
indexGen.TranslatePrim(drawCalls[j].prim, drawCalls[j].vertexCount, (const u16 *)drawCalls[j].inds, indexLowerBound);
}
break;
}
const int vertexCount = indexUpperBound - indexLowerBound + 1;
// 3. Decode that range of vertex data.
dec_->DecodeVerts(decoded + decodedVerts_ * (int)dec_->GetDecVtxFmt().stride,
dc.verts, indexLowerBound, indexUpperBound);

View File

@ -21,6 +21,7 @@
#include "GPU/Common/GPUDebugInterface.h"
#include "GPU/Common/IndexGenerator.h"
#include "GPU/GLES/VertexDecoder.h"
#include "gfx/gl_common.h"
#include "gfx/gl_lost_manager.h"
@ -28,8 +29,6 @@ class LinkedShader;
class ShaderManager;
class TextureCache;
class FramebufferManager;
class VertexDecoder;
class VertexDecoderJitCache;
struct TransformedVertex;
struct DecVtxFormat;
@ -125,9 +124,37 @@ public:
void ClearTrackedVertexArrays();
void SetupVertexDecoder(u32 vertType);
inline void SetupVertexDecoderInternal(u32 vertType);
// This requires a SetupVertexDecoder call first.
int EstimatePerVertexCost();
int EstimatePerVertexCost() {
// TODO: This is transform cost, also account for rasterization cost somehow... although it probably
// runs in parallel with transform.
// Also, this is all pure guesswork. If we can find a way to do measurements, that would be great.
// GTA wants a low value to run smooth, GoW wants a high value (otherwise it thinks things
// went too fast and starts doing all the work over again).
int cost = 20;
if (gstate.isLightingEnabled()) {
cost += 10;
for (int i = 0; i < 4; i++) {
if (gstate.isLightChanEnabled(i))
cost += 10;
}
}
if (gstate.getUVGenMode() != GE_TEXMAP_TEXTURE_COORDS) {
cost += 20;
}
if (dec_ && dec_->morphcount > 1) {
cost += 5 * dec_->morphcount;
}
return cost;
}
// So that this can be inlined
void Flush() {

View File

@ -811,8 +811,7 @@ void VertexDecoderJitCache::Jit_Color565Morph() {
PSHUFD(fpScratchReg2, R(fpScratchReg2), _MM_SHUFFLE(0, 0, 0, 0));
PAND(fpScratchReg2, R(XMM5));
// Alpha - start with 1.
MOVD_xmm(reg, R(tempReg2));
// Alpha handled in Jit_WriteMorphColor.
// Blue first.
MOVSS(reg, R(fpScratchReg2));
@ -908,16 +907,20 @@ void VertexDecoderJitCache::Jit_WriteMorphColor(int outOff, bool checkAlpha) {
CVTPS2DQ(fpScratchReg, R(fpScratchReg));
PACKSSDW(fpScratchReg, R(fpScratchReg));
PACKUSWB(fpScratchReg, R(fpScratchReg));
MOVD_xmm(MDisp(dstReg, outOff), fpScratchReg);
MOVD_xmm(R(tempReg1), fpScratchReg);
// TODO: May be a faster way to do this without the MOVD.
if (checkAlpha) {
MOVD_xmm(R(tempReg1), fpScratchReg);
CMP(32, R(tempReg1), Imm32(0xFF000000));
FixupBranch skip = J_CC(CC_AE, false);
MOV(8, M(&gstate_c.textureFullAlpha), Imm8(0));
SetJumpTarget(skip);
} else {
// Force alpha to full if we're not checking it.
OR(32, R(tempReg1), Imm32(0xFF000000));
}
MOV(32, MDisp(dstReg, outOff), R(tempReg1));
}
// Copy 3 bytes and then a zero. Might as well copy four.

View File

@ -559,17 +559,19 @@ void GPUCommon::SlowRunLoop(DisplayList &list)
// The newPC parameter is used for jumps, we don't count cycles between.
void GPUCommon::UpdatePC(u32 currentPC, u32 newPC) {
// Rough estimate, 2 CPU ticks (it's double the clock rate) per GPU instruction.
int executed = (currentPC - cycleLastPC) / 4;
u32 executed = (currentPC - cycleLastPC) / 4;
cyclesExecuted += 2 * executed;
gpuStats.otherGPUCycles += 2 * executed;
cycleLastPC = newPC == 0 ? currentPC : newPC;
cycleLastPC = newPC;
gpuStats.gpuCommandsAtCallLevel[std::min(currentList->stackptr, 3)] += executed;
if (g_Config.bShowDebugStats) {
gpuStats.otherGPUCycles += 2 * executed;
gpuStats.gpuCommandsAtCallLevel[std::min(currentList->stackptr, 3)] += executed;
}
// Exit the runloop and recalculate things. This happens a lot in some games.
easy_guard innerGuard(listLock);
if (currentList)
downcount = currentList->stall == 0 ? 0x0FFFFFFF : (currentList->stall - cycleLastPC) / 4;
downcount = currentList->stall == 0 ? 0x0FFFFFFF : (currentList->stall - newPC) / 4;
else
downcount = 0;
}

View File

@ -81,7 +81,10 @@ protected:
// To avoid virtual calls to PreExecuteOp().
virtual void FastRunLoop(DisplayList &list) = 0;
void SlowRunLoop(DisplayList &list);
void UpdatePC(u32 currentPC, u32 newPC = 0);
void UpdatePC(u32 currentPC, u32 newPC);
void UpdatePC(u32 currentPC) {
UpdatePC(currentPC, currentPC);
}
void UpdateState(GPUState state);
void PopDLQueue();
void CheckDrawSync();

View File

@ -77,6 +77,7 @@ private:
SDLJoyButtonMap[12] = NKCODE_BUTTON_3;
SDLJoyButtonMap[13] = NKCODE_BUTTON_4;
SDLJoyButtonMap[14] = NKCODE_BUTTON_1;
SDLJoyButtonMap[15] = NKCODE_BUTTON_11;
SDLJoyAxisMap[0] = JOYSTICK_AXIS_X;
SDLJoyAxisMap[1] = JOYSTICK_AXIS_Y;

View File

@ -19,6 +19,7 @@
#include <algorithm>
#include "base/colorutil.h"
#include "base/display.h"
#include "base/timeutil.h"
#include "file/path.h"
#include "gfx_es2/draw_buffer.h"
@ -689,7 +690,7 @@ void MainScreen::CreateViews() {
using namespace UI;
// Vertical mode is not finished.
bool vertical = false; // dp_yres > dp_xres;
bool vertical = dp_yres > dp_xres;
I18NCategory *m = GetI18NCategory("MainMenu");

View File

@ -2,16 +2,16 @@
set LOGFILE=ppsspplog.txt
del "%LOGFILE%" 2> NUL
if exist PPSSPPDebug64.exe (
PPSSPPDebug64.exe --log="%LOGFILE%"
if exist PPSSPPWindows64.exe (
start PPSSPPWindows64.exe --log="%LOGFILE%" -d
goto exit
)
if exist PPSSPPDebug.exe (
PPSSPPDebug.exe --log="%LOGFILE%"
if exist PPSSPPWindows.exe (
start PPSSPPWindows.exe --log="%LOGFILE%" -d
goto exit
)
echo Unable to find PPSSPPDebug.exe.
echo Unable to find PPSSPPWindows.exe.
pause
:exit
:exit

View File

@ -177,17 +177,41 @@ bool GL_Init(HWND window, std::string *error_message) {
return false;
}
// Alright, now for the modernity.
static const int attribs[] = {
CheckGLExtensions();
int contextFlags = enableGLDebug ? WGL_CONTEXT_DEBUG_BIT_ARB : 0;
// Alright, now for the modernity. First try a 4.4, then 4.3, context, if that fails try 3.3.
// I can't seem to find a way that lets you simply request the newest version available.
const int attribs44[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
WGL_CONTEXT_MINOR_VERSION_ARB, 4,
WGL_CONTEXT_FLAGS_ARB, contextFlags,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
0
};
const int attribs43[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
WGL_CONTEXT_MINOR_VERSION_ARB, 3,
WGL_CONTEXT_FLAGS_ARB, contextFlags,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
0
};
const int attribs33[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 1,
WGL_CONTEXT_FLAGS_ARB, enableGLDebug ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
WGL_CONTEXT_MINOR_VERSION_ARB, 3,
WGL_CONTEXT_FLAGS_ARB, contextFlags,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
0
};
HGLRC m_hrc;
if(wglewIsSupported("WGL_ARB_create_context") == 1) {
m_hrc = wglCreateContextAttribsARB(hDC, 0, attribs);
m_hrc = wglCreateContextAttribsARB(hDC, 0, attribs44);
if (!m_hrc)
m_hrc = wglCreateContextAttribsARB(hDC, 0, attribs43);
if (!m_hrc)
m_hrc = wglCreateContextAttribsARB(hDC, 0, attribs33);
if (!m_hrc) {
// Fall back
m_hrc = hRC;
@ -222,8 +246,6 @@ bool GL_Init(HWND window, std::string *error_message) {
MessageBox(0,ConvertUTF8ToWString((const char *)glGetString(GL_SHADING_LANGUAGE_VERSION)).c_str(),0,0);
*/
CheckGLExtensions();
glstate.Initialize();
if (wglSwapIntervalEXT)
wglSwapIntervalEXT(0);

View File

@ -310,6 +310,8 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
g_Config.SetDefaultPath(GetSysDirectory(DIRECTORY_SYSTEM));
g_Config.Load(configFilename, controlsConfigFilename);
bool debugLogLevel = false;
// The rest is handled in NativeInit().
for (int i = 1; i < __argc; ++i)
{
@ -328,6 +330,9 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
g_Config.bAutoRun = false;
g_Config.bSaveSettings = false;
break;
case 'd':
debugLogLevel = true;
break;
}
if (!strncmp(__argv[i], "--fullscreen", strlen("--fullscreen")))
@ -351,7 +356,9 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
// - The -l switch is expected to show the log console, REGARDLESS of config settings.
// - It should be possible to log to a file without showing the console.
LogManager::GetInstance()->GetConsoleListener()->Init(showLog, 150, 120, "PPSSPP Debug Console");
if (debugLogLevel)
LogManager::GetInstance()->SetAllLogLevels(LogTypes::LDEBUG);
//Windows, API init stuff
INITCOMMONCONTROLSEX comm;

View File

@ -34,6 +34,7 @@ dr_ID = "Duri"
fa_IR = "فارسی"
ms_MY = "Melayu"
da_DK = "Dansk"
no_NO = "Norsk"
[SystemLanguage]
ja_JP = "JAPANESE"

2
lang

@ -1 +1 @@
Subproject commit ec04fc188efc08ccf1c43ec337145f706e1fb807
Subproject commit 84f3840e69413d32f87d9be9c86f8a1eec933c3f